Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Navigating asset based html files in webview on Nougat

I am loading a HTML file from assets into a webview.

The html has links to other html asset files. Clicking the links works correctly on SDK < 24 but produces a FileUriExposedException error when clicking a link to a second html page on Nougat (SDK 24) devices.

Code to load the html from assets into a webview:

wbHelp.loadDataWithBaseURL("file:///android_asset/", readAssetFileAsString("Index.html"), "text/html", "UTF-8", null);

and readAssetFileAsString is:

private String readAssetFileAsString(String sourceHtmlLocation)
{
    InputStream is;
    try
    {
        is = getContext().getAssets().open(sourceHtmlLocation);
        int size = is.available();

        byte[] buffer = new byte[size];
        is.read(buffer);
        is.close();

        return new String(buffer, "UTF-8");
    }
    catch(IOException e)
    {
        e.printStackTrace();
    }

    return "";
}

The html can be very basic. Index.html

<html><a href="Page2.html">Page 2</a></html>

Page2.html

<html><h1>Page 2</h1>

The full error log is:

11-12 17:58:03.694 5831-5831/appname W/System.err: android.os.FileUriExposedException: file:///android_asset/Page2.html exposed beyond app through Intent.getData()
11-12 17:58:03.694 5831-5831/appname W/System.err:     at android.os.StrictMode.onFileUriExposed(StrictMode.java:1799)
11-12 17:58:03.694 5831-5831/appname W/System.err:     at android.net.Uri.checkFileUriExposed(Uri.java:2346)
11-12 17:58:03.694 5831-5831/appname W/System.err:     at android.content.Intent.prepareToLeaveProcess(Intent.java:8933)
11-12 17:58:03.694 5831-5831/appname W/System.err:     at android.content.Intent.prepareToLeaveProcess(Intent.java:8894)
11-12 17:58:03.694 5831-5831/appname W/System.err:     at android.app.Instrumentation.execStartActivity(Instrumentation.java:1517)
11-12 17:58:03.694 5831-5831/appname W/System.err:     at android.app.Activity.startActivityForResult(Activity.java:4224)
11-12 17:58:03.694 5831-5831/appname W/System.err:     at android.support.v4.app.BaseFragmentActivityJB.startActivityForResult(BaseFragmentActivityJB.java:48)
11-12 17:58:03.694 5831-5831/appname W/System.err:     at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:77)
11-12 17:58:03.694 5831-5831/appname W/System.err:     at android.app.Activity.startActivityForResult(Activity.java:4183)
11-12 17:58:03.695 5831-5831/appname W/System.err:     at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:859)
11-12 17:58:03.695 5831-5831/appname W/System.err:     at android.app.Activity.startActivity(Activity.java:4507)
11-12 17:58:03.695 5831-5831/appname W/System.err:     at android.app.Activity.startActivity(Activity.java:4475)
11-12 17:58:03.695 5831-5831/appname W/System.err:     at android.content.ContextWrapper.startActivity(ContextWrapper.java:356)
11-12 17:58:03.695 5831-5831/appname W/System.err:     at org.chromium.android_webview.ResourcesContextWrapperFactory$WebViewContextWrapper.startActivity(ResourcesContextWrapperFactory.java:121)
11-12 17:58:03.695 5831-5831/appname W/System.err:     at org.chromium.android_webview.AwContentsClient.sendBrowsingIntent(AwContentsClient.java:203)
11-12 17:58:03.695 5831-5831/appname W/System.err:     at org.chromium.android_webview.AwContentsClient.shouldIgnoreNavigation(AwContentsClient.java:170)
11-12 17:58:03.695 5831-5831/appname W/System.err:     at org.chromium.android_webview.AwContentsClientBridge.shouldOverrideUrlLoading(AwContentsClientBridge.java:256)
11-12 17:58:03.695 5831-5831/appname W/System.err:     at org.chromium.base.SystemMessageHandler.nativeDoRunLoopOnce(Native Method)
11-12 17:58:03.695 5831-5831/appname W/System.err:     at org.chromium.base.SystemMessageHandler.handleMessage(SystemMessageHandler.java:39)
11-12 17:58:03.695 5831-5831/appname W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:102)
11-12 17:58:03.695 5831-5831/appname W/System.err:     at android.os.Looper.loop(Looper.java:154)
11-12 17:58:03.695 5831-5831/appname W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:6077)
11-12 17:58:03.695 5831-5831/appname W/System.err:     at java.lang.reflect.Method.invoke(Native Method)
11-12 17:58:03.695 5831-5831/appname W/System.err:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
11-12 17:58:03.695 5831-5831/appname W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
11-12 17:58:03.699 5831-5831/appname A/chromium: [FATAL:jni_android.cc(236)] Please include Java exception stack in crash report
                                                    
                                                    
                                                    --------- beginning of crash
11-12 17:58:03.856 5831-5831/appname W/google-breakpad: ### ### ### ### ### ### ### ### ### ### ### ### ###
11-12 17:58:03.856 5831-5831/appname W/google-breakpad: Chrome build fingerprint:
11-12 17:58:03.856 5831-5831/appname W/google-breakpad: 1.0
11-12 17:58:03.856 5831-5831/appname W/google-breakpad: 72
11-12 17:58:03.856 5831-5831/appname W/google-breakpad: ### ### ### ### ### ### ### ### ### ### ### ### ###
11-12 17:58:03.857 5831-5831/appname A/libc: Fatal signal 6 (SIGABRT), code -6 in tid 5831 (appname)
                                                
                                                [ 11-12 17:58:03.857   270:  270 W/         ]
                                                debuggerd: handling request: pid=5831 uid=10379 gid=10379 tid=5831

I've tried using some form of provider (such as in this answer: android.os.FileUriExposedException: file:///storage/emulated/0/test.txt exposed beyond app through Intent.getData()) but it doesn't have any effect.

like image 499
behelit Avatar asked Nov 12 '16 07:11

behelit


People also ask

How do I open an HTML file in WebView?

The WebView method to load our file takes a URI , so we need to access the HTML file using that URI . Since we stored it in the assets folder, we can access it using file:///android_asset/{file_name} . Now let's load that file in our MainActivity .

What does file Android_asset www index HTML mean?

super.loadUrl("file:///android_asset/www/index.html", 1000); } means you finished your splash screen work in android activity.

Is Android WebView deprecated?

The Android system webview custom cache file has been deprecated and removed in Android 13. New apps and any app updates will now use the operating system default cache location.


2 Answers

I was able to overcome the exception by using the shouldOverrideUrlLoading, as suggested by @CommonsWare here:

Tested on an emulator running Nougat:

    web.setWebViewClient(new WebViewClient()
    {
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url)
        {
            Log.i("WebView", "Attempting to load URL: " + url);

            view.loadUrl(url);
            return true;
        }
    });
like image 180
behelit Avatar answered Sep 28 '22 19:09

behelit


Also you can add this code in the onCreate method of you application or activity:

   StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
   StrictMode.setVmPolicy(builder.build());

this lines makes your app ignore that exception.

And reading the documentation you will find that just using this code:

    WebViewClient client = new WebViewClient() {
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            return false;
        }
    };

    webView.setWebViewClient(client);

Will also work, because returning false you are asking for your webView to handle that operation. https://developer.android.com/reference/android/webkit/WebViewClient.html#shouldOverrideUrlLoading(android.webkit.WebView, java.lang.String)

like image 21
Sebastian Corradi Avatar answered Sep 28 '22 20:09

Sebastian Corradi