9

My app load local html file that located under getFilesDir() via WebView#loadUrl().
Before targetSdkVersion = 29, below code is working.

        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();

Full example is here.

However, it's not working after change targetSdkVersion = 30.

  • WebView respond net::ERR_ACCESS_DINIED
  • Could load local html if it's located android_asset

How to load local html file on targetSdkVersion = 30?
Is it changed to be denied by Android FW??

JchanKchan
  • 91
  • 1
  • 3

3 Answers3

13

WebSettings#setAllowFileAccess() is default to false when your app is targeting R and above for security reasons, note that you need to set the API level 30. https://developer.android.com/reference/android/webkit/WebSettings#setAllowFileAccess(boolean)

user14039297
  • 131
  • 2
1

Try setting webview.getSettings().setAllowFileAccess(true);

Suraj Rao
  • 29,388
  • 11
  • 94
  • 103
Sunil Kumar
  • 127
  • 2
  • 8
  • Works great. Just one line of code. I found this issue in Cordova but I notice the latest version has a switch to enable this. See AndroidInsecureFileModeEnabled in https://github.com/apache/cordova-android/blob/master/framework/src/org/apache/cordova/engine/SystemWebViewEngine.java – mike nelson Feb 22 '22 at 03:31
0

to show local html files in webView in api level 30, I used this code

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()) }
    }

now WebClient class is

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
}
}

and use webKit dependency

implementation 'androidx.webkit:webkit:1.4.0'
Abdur Rehman
  • 1,247
  • 10
  • 13