Kitkat kills: Not allowed to load local resource: file:///android_asset/webkit/android-weberror.png
I have an app that uses WebViews. I've changed my targetAPI from 18 to 19 and I'm currently testing on the new 4.4. For some reason I'm getting this error: Not allowed to load local resource: file:///android_asset/webkit/android-weberror.png
on 4.4 but not on 4.3, does somebody have clue why?
Since I don't really know where to start looking I can't give the complete code. It might have something to do with the shouldInterceptRequest(Webview, String)
method in the WebViewClient but I'm not really sure. If I know more, I'll update the question.
I found that I had this problem on KitKat when I used webview.loadData()
. If I instead used webview.loadDataWithBaseURL()
(I used "file:///android_asset/" as the baseURL), then the problem went away.
The methods setAllowFileAccess()
, setAllowFileAccessFromFileURLs()
, and setAllowUniversalAccessFromFileURLs()
did not have any affect that I could see.
A bit of an intrusive hack, but I worked around this issue by introducing a "unique token" and implementing the WebViewClient
with a shouldInterceptRequest
override.
First, change the URL from file:///android/asset
to a relative path with a uniquely identifying token:
<script src="**injection**www/scripts.js"></script>
Then, override shouldInterceptRequest
as follows:
// 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;
}
});
This is likely to degrade WebView performance slightly as we are calling the contains()
on each resource which is attempted to be loaded, but it's the only workaround I've found to this issue.
"Not allowed to load local resource" is a security origin error. The KitKat WebView has stronger security restrictions and it seems like these are kicking in. FWIW I tried just loading a file:///android_asset URL and it worked fine.
Did you call any of the file-related WebSettings APIs (like setAllowFileAccess(false)) by any chance? Are you trying to load the resource from an https: URL?