I am developing an Android application that needs to display offline HTML content stored on the SD card, but the WebView refuses to load the path "file:///sdcard/index.html". I’ve already added the READ_EXTERNAL_STORAGE permission to my manifest, but the screen just stays blank or shows a "net::ERR_ACCESS_DENIED" error on Android 11 and above. Is there a specific setting in WebSettings I need to enable to permit local file access, or has the new Scoped Storage policy completely blocked WebView from accessing the root SD card directory?
3 answers
The issue is likely twofold: WebSettings configuration and Android's Scoped Storage. First, you must explicitly enable file access in your Java/Kotlin code using settings.setAllowFileAccess(true) and settings.setAllowContentAccess(true). However, since Android 11 (API 30), direct access to /sdcard/ is heavily restricted. The best practice now is to use the WebViewAssetLoader. This helper allows you to map a virtual domain like https://appassets.androidplatform.net/ to a local directory. This bypasses the security risks of file:// schemes and complies with Scoped Storage, ensuring your CSS and JavaScript files load correctly without triggering "Same-Origin" policy violations that usually block local resources.
If I use the WebViewAssetLoader as suggested, do I still need to request the MANAGE_EXTERNAL_STORAGE permission for my app to see files that were downloaded to the public 'Downloads' folder?
Don't forget to set setAllowFileAccessFromFileURLs(true) if your HTML file needs to load other local files like scripts or images. By default, this is disabled for security reasons.
I agree with Sarah. I spent an entire day wondering why my HTML loaded but my CSS didn't. Enabling setAllowFileAccessFromFileURLs was the missing piece for my offline documentation viewer to render correctly on older Android versions.
Jordan, you should avoid MANAGE_EXTERNAL_STORAGE if possible, as Google Play often rejects apps that use it without a core need. Instead, if your files are in the public 'Downloads' folder, use the Storage Access Framework (SAF) to get a URI. Once you have the URI, you can open an InputStream and feed it to the WebViewAssetLoader via a custom PathHandler. This is the most secure way to handle user-selected files from the SD card without requesting broad, dangerous permissions that scare off users and complicate the app review process.