Android WebView注入JS加载Assets文件遇本地资源加载限制问题求助
嘿,这个问题完全是可以解决的!你遇到的错误本质是WebView的同源策略和安全限制在搞鬼,尤其是当你的WebView加载的是远程页面时,直接用file:///android_asset/xxx这种路径加载本地资源会被拦截。下面给你具体的可行方案:
为什么会出错?
当WebView加载的是远程页面(比如https://xxx.com),页面的源属于远程服务器,而本地assets的file://协议属于完全不同的源。浏览器的同源策略会阻止跨源访问本地资源,所以你直接给script标签的src设置本地assets路径时,就会触发"not allowed to load local resource"错误。
可行的解决方案
方案1:读取assets文件内容,直接注入到页面中(推荐)
这种方式绕过了跨源限制,因为我们是把本地JS文件的内容直接插入到页面上下文里执行,而不是通过URL加载。
首先写一个工具方法读取assets里的文件内容:
private String readAssetFile(Context context, String fileName) throws IOException { InputStream inputStream = context.getAssets().open(fileName); int fileSize = inputStream.available(); byte[] buffer = new byte[fileSize]; inputStream.read(buffer); inputStream.close(); return new String(buffer, StandardCharsets.UTF_8); }
然后在WebView页面加载完成后,把JS内容注入进去:
webView.setWebViewClient(new WebViewClient() { @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); try { // 先读取依赖的JS文件(如果有的话) String dependencyJs = readAssetFile(getApplicationContext(), "dependency.js"); view.evaluateJavascript("javascript:" + dependencyJs, null); // 再读取主JS文件并注入 String mainJs = readAssetFile(getApplicationContext(), "main-script.js"); view.evaluateJavascript("javascript:" + mainJs, null); } catch (IOException e) { e.printStackTrace(); } } });
方案2:仅当WebView加载本地HTML时适用
如果你的WebView加载的是本地assets里的HTML文件(比如webView.loadUrl("file:///android_asset/index.html")),那只需要配置WebView的安全设置,就可以直接在JS里用file:///android_asset/xxx.js路径加载:
WebSettings webSettings = webView.getSettings(); webSettings.setAllowFileAccess(true); webSettings.setAllowFileAccessFromFileURLs(true); webSettings.setAllowUniversalAccessFromFileURLs(true);
⚠️ 注意:Android 10及以上,setAllowFileAccessFromFileURLs和setAllowUniversalAccessFromFileURLs默认是关闭的,而且如果加载的是远程页面,开启这些设置会有安全风险,不推荐。
额外提示
如果你的主JS文件需要加载多个本地assets资源(比如CSS、图片),也可以用类似的思路:把CSS内容读取后注入到style标签,图片可以转换成base64格式再注入到页面中,同样能绕过本地资源加载限制。
内容的提问来源于stack exchange,提问作者izik

