无法在 API 级别 30 上加载本地 html 文件

Posted

技术标签:

【中文标题】无法在 API 级别 30 上加载本地 html 文件【英文标题】:Unable to load local html file on API Level 30 【发布时间】:2020-11-17 13:50:28 【问题描述】:

我的应用通过WebView#loadUrl()加载位于getFilesDir()下的本地html文件。 在targetSdkVersion = 29 之前,下面的代码正在运行。

        copyAssetsFile(this, "sample.html", getFilesDir().getAbsolutePath());
        webView.getSettings().setjavascriptEnabled(true);
        String url = "file://" + getFilesDir().getAbsolutePath() + "/sample.html";
        webView.loadUrl(url);
    

    private static void copyAssetsFile(Context context, String fileName, String directoryPath) 
        try 
            InputStream inputStream = context.getResources().getAssets().open(fileName);
            FileOutputStream fileOutputStream = new FileOutputStream(
                    new File(directoryPath, fileName), false);
            byte[] buffer = new byte[1024];
            int length = 0;
            while ((length = inputStream.read(buffer)) >= 0) 
                fileOutputStream.write(buffer, 0, length);
            

            fileOutputStream.close();
            inputStream.close();

完整的例子是here。

但是,更改 targetSdkVersion = 30 后它不起作用。

WebView 回复net::ERR_ACCESS_DINIED 如果本地 html 位于 android_asset,则可以加载它

如何在targetSdkVersion = 30上加载本地html文件? 是不是改成被Android FW拒绝了??

【问题讨论】:

我们不相信你的代码,因为 webview 不会开始谈论资产。 【参考方案1】:

出于安全原因,当您的应用程序以R 及以上为目标时,WebSettings#setAllowFileAccess() 默认为 false,请注意您需要将 API 级别设置为 30。https://developer.android.com/reference/android/webkit/WebSettings#setAllowFileAccess(boolean)

【讨论】:

【参考方案2】:

尝试设置webview.getSettings().setAllowFileAccess(true);

【讨论】:

【参考方案3】:

为了在 api 级别 30 的 webView 中显示本地 html 文件,我使用了这段代码

binding.webView.apply 
        visible()
        settings.apply 
            useWideViewPort = true
            loadWithOverviewMode = true
            builtInZoomControls = true
            displayZoomControls = false
            allowFileAccess = false
            allowFileAccessFromFileURLs = false
            allowUniversalAccessFromFileURLs = false
            allowContentAccess = true
        
        val contentUri = FileProvider.getUriForFile(
            this@DocViewerActivity,
            "$BuildConfig.APPLICATION_ID.provider",
            File(filePath!!)
        )
        webViewClient = MyWebClient(this@DocViewerActivity)

        contentUri?.let  loadUrl(contentUri.toString()) 
    

现在WebClient 类是

import android.content.Context
import android.content.Intent
import android.webkit.WebResourceRequest
import android.webkit.WebResourceResponse
import android.webkit.WebView
import androidx.webkit.WebViewAssetLoader
import androidx.webkit.WebViewClientCompat
import java.io.File

class MyWebClient(context: Context) : WebViewClientCompat() 
private val assetLoader: WebViewAssetLoader = WebViewAssetLoader.Builder()
    .addPathHandler(
        "/public/", WebViewAssetLoader.InternalStoragePathHandler(
            context,
            File(context.filesDir, "public")
        )
    )
    .build()

override fun shouldInterceptRequest(
    view: WebView,
    request: WebResourceRequest
): WebResourceResponse? 
    return assetLoader.shouldInterceptRequest(request.url)


override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest): Boolean 
    return if (request.isForMainFrame) 
        view.context.startActivity(
            Intent(Intent.ACTION_VIEW, request.url)
        )
        true
     else false


并使用webKit 依赖

implementation 'androidx.webkit:webkit:1.4.0'

【讨论】:

以上是关于无法在 API 级别 30 上加载本地 html 文件的主要内容,如果未能解决你的问题,请参考以下文章

无法打开相机意图。 queryIntentActivities 在 api 级别 30 返回一个空列表,但在级别 29 中找到结果。发生了啥变化?

OpenLayers显示本地图片

Fetch API 无法加载“.php”本地文件 - React JS + PHP

flutter 安卓webview 无法加载http解决方案net::ERR_CLEARTEXT_NOT_PERMITTED

无法在 Android Studio 上更改 API 级别

无法仅将本地 html 文件加载到设备上的 WKWebView 中(适用于模拟器)