簡體   English   中英

Kitkat 殺死:不允許加載本地資源:file:///android_asset/webkit/android-weberror.png

[英]Kitkat kills: Not allowed to load local resource: file:///android_asset/webkit/android-weberror.png

我有一個使用 WebViews 的應用程序。 我已將我的 targetAPI 從 18 更改為 19,並且我目前正在測試新的 4.4。 出於某種原因,我收到此錯誤: Not allowed to load local resource: file:///android_asset/webkit/android-weberror.png在 4.4 但不是在 4.3,有人知道為什么嗎?

由於我真的不知道從哪里開始尋找我無法提供完整的代碼。 它可能與 WebViewClient 中的shouldInterceptRequest(Webview, String)方法有關,但我不太確定。 如果我知道更多,我會更新問題。

有點干擾,但我通過引入“唯一令牌”並使用shouldInterceptRequest覆蓋實現WebViewClient來解決這個問題。

首先,將URL從file:///android/asset更改為具有唯一標識標記的相對路徑:

<script src="**injection**www/scripts.js"></script>

然后,覆蓋shouldInterceptRequest ,如下所示:

// Injection token as specified in HTML source
private static final String INJECTION_TOKEN = "**injection**";

webView.setWebViewClient(new WebViewClient() {

    @Override
    public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
        WebResourceResponse response = super.shouldInterceptRequest(view, url);
        if(url != null && url.contains(INJECTION_TOKEN)) {
            String assetPath = url.substring(url.indexOf(INJECTION_TOKEN) + INJECTION_TOKEN.length(), url.length());
            try {
                response = new WebResourceResponse(
                        "application/javascript",
                        "UTF8",
                        getContext().getAssets().open(assetPath)
                );
            } catch (IOException e) {
                e.printStackTrace(); // Failed to load asset file
            }
        }
        return response;
    }
});

這可能會稍微降低WebView性能,因為我們在每個嘗試加載的資源上調用contains() ,但這是我發現此問題的唯一解決方法。

當我使用webview.loadData()時,我發現我在KitKat上遇到了這個問題。 如果我改為使用webview.loadDataWithBaseURL() (我使用“file:/// android_asset /”作為baseURL),那么問題就消失了。

方法setAllowFileAccess()setAllowFileAccessFromFileURLs()setAllowUniversalAccessFromFileURLs()沒有任何影響,我可以看到。

“不允許加載本地資源”是安全起源錯誤。 KitKat WebView具有更強的安全限制,看起來似乎正在進行.FWIW我嘗試只加載一個文件:/// android_asset URL並且它工作正常。

您是否有機會調用任何與文件相關的WebSettings API(如setAllowFileAccess(false))? 您是否嘗試從https:URL加載資源?

這是解決方案:當您嘗試從庫項目加載文件時,會發生此問題。 如果您的應用程序依賴於webview和html文件所在的庫,那么您需要在編譯時將該庫項目中的資源包含到主應用程序項目中。 例如,IntelliJ有一個選項來執行此操作。 在編譯器設置“將資源從依賴項包含到APK”中,但請確保您的資產文件應具有與主應用程序不同的名稱。 您不希望主應用程序覆蓋庫項目的index.html。

可能需要添加權限

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

到清單。

從API級別19開始強制執行此權限。

以下解決方案適合我。

webview.loadDataWithBaseURL( baseUrl, htmlStr, "text/html", "UTF-8", "");

其中baseUrl是您的外部域,而不是file:/// android_asset /(即http://a.domain.com )。

當時不可用,現在可以使用(雖然不推薦):

webView.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);

以下是doc對setMixedContentMode的說法:

當安全源嘗試從不安全的源加載資源時,配置WebView的行為。 默認情況下,以KITKAT或以下為目標的應用默認為MIXED_CONTENT_ALWAYS_ALLOW。 針對LOLLIPOP的應用默認為MIXED_CONTENT_NEVER_ALLOW。 WebView的首選和最安全的操作模式是MIXED_CONTENT_NEVER_ALLOW,強烈建議不要使用MIXED_CONTENT_ALWAYS_ALLOW。

但是,這可能無法回答原來的問題; 看起來這個限制只是從Lollipop開始的。

我在這個鏈接中找到了一個很好的解決方法: http//trentmilton.com/android-webview.html

解決方案的摘要如下:

WebView webView = new WebView(this); // this is the context
webView.getSettings().setDomStorageEnabled(true);

希望有所幫助

處理此問題的正確方法是使用AndroidX中的WebViewAssetLoader (Android 支持庫的后續版本)。 這個 class 使任何頁面元素都可以使用資產文件。

您可以通過將此行添加到應用程序的build.gradle來將庫添加到您的項目中:

implementation 'androidx.webkit:webkit:1.5.0'

創建WebViewAssetLoader的實例並將其指向您希望向 WebView 公開的資產路徑:

val assetLoader = WebViewAssetLoader.Builder()
    .addPathHandler("/some/path/", AssetsPathHandler(context))
    .build()

然后覆蓋WebViewClient.shouldInterceptRequest()

webView.webViewClient = object : WebViewClient() {
    override fun shouldInterceptRequest(
        view: WebView,
        request: WebResourceRequest
    ): WebResourceResponse? {
        return assetLoader.shouldInterceptRequest(request.url)
    }
}

現在,您的 URL 不再是file:///android_asset/... ,而是:

https://appassets.androidplatform.net/...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM