You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WebView加载本地HTML后点击链接崩溃,报FileUriExposedException错误

Got it, let's resolve this crash you're facing. The root cause here is Android's security restriction introduced in API level 24 (Android 7.0): apps are blocked from exposing file:// URIs to other components (even within your own app) via Intents. When your WebView tries to navigate to a local asset link like file:///android_asset/page2.html, it triggers this FileUriExposedException and crashes the app.

Here are two reliable solutions, with the first being the official recommended approach:

Google provides the WebViewAssetLoader as part of the AndroidX WebKit library to safely load local assets/files in WebView without exposing risky file:// URIs. It uses a secure fake HTTPS domain to serve your assets.

Step 1: Add the dependency

Add this to your module-level build.gradle file (use the latest available version):

dependencies {
    implementation 'androidx.webkit:webkit:1.5.0'
}

Step 2: Configure WebView with the asset loader

In your Activity/Fragment where you initialize the WebView:

WebView webView = findViewById(R.id.your_webview_id);
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true); // Enable if your HTML uses JS

// Initialize the asset loader to serve files from the assets folder
final WebViewAssetLoader assetLoader = new WebViewAssetLoader.Builder()
        .addPathHandler("/assets/", new WebViewAssetLoader.AssetsPathHandler(this))
        .build();

// Set a custom WebViewClient to intercept requests and use the asset loader
webView.setWebViewClient(new WebViewClient() {
    @Override
    public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
        // Let the asset loader handle requests to local assets
        return assetLoader.shouldInterceptRequest(request.getUrl());
    }

    // Optional: Ensure links open within the WebView instead of triggering an Intent
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
        view.loadUrl(request.getUrl().toString());
        return true;
    }
});

// Load your initial HTML using the secure asset loader URL
webView.loadUrl("https://appassets.androidplatform.net/assets/index.html");

How it works

All links in your HTML (like <a href="page2.html">) will automatically resolve to the secure HTTPS-like URI, avoiding any file:// exposure. This is the cleanest, most future-proof solution.

2. Custom ContentProvider (For non-AndroidX projects)

If you can't use AndroidX, create a custom ContentProvider to serve your assets via safe content:// URIs.

Step 1: Create the ContentProvider class

public class AssetContentProvider extends ContentProvider {
    private static final String AUTHORITY = "com.your.package.name.assetprovider"; // Replace with your app's package
    private static final Uri BASE_URI = Uri.parse("content://" + AUTHORITY);

    // Helper method to convert asset paths to content URIs
    public static Uri getAssetUri(String assetPath) {
        return BASE_URI.buildUpon().appendEncodedPath(assetPath).build();
    }

    @Override
    public boolean onCreate() {
        return true;
    }

    @Override
    public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
        String assetPath = uri.getEncodedPath().substring(1); // Remove leading '/'
        return getContext().getAssets().openFd(assetPath).getParcelFileDescriptor();
    }

    @Override
    public String getType(Uri uri) {
        String assetPath = uri.getEncodedPath().substring(1);
        return MimeTypeMap.getSingleton().getMimeTypeFromExtension(MimeTypeMap.getFileExtensionFromUrl(assetPath));
    }
}

Step 2: Register the provider in AndroidManifest.xml

Add this inside the <application> tag:

<provider
    android:name=".AssetContentProvider"
    android:authorities="com.your.package.name.assetprovider" // Match the AUTHORITY above
    android:exported="false" />

Step 3: Update WebView setup

WebView webView = findViewById(R.id.your_webview_id);
webView.setWebViewClient(new WebViewClient() {
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        // Convert any file:///android_asset/ links to content URIs
        if (url.startsWith("file:///android_asset/")) {
            String assetPath = url.substring("file:///android_asset/".length());
            Uri contentUri = AssetContentProvider.getAssetUri(assetPath);
            view.loadUrl(contentUri.toString());
            return true;
        }
        return super.shouldOverrideUrlLoading(view, url);
    }
});

// Load initial HTML using the content URI
webView.loadUrl(AssetContentProvider.getAssetUri("index.html").toString());

This approach wraps your assets in content:// URIs, which are allowed to be used within your app without triggering the exception.

Whichever method you choose, make sure to test on devices running Android 7.0+ to confirm the crash is resolved.

内容的提问来源于stack exchange,提问作者Ashonko

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 04:24:58