Android Webview使用WebViewAssetLoader加载离线资源

1,130 阅读1分钟

参考链接:Loading in-app content  |  Android Developers (google.cn)

需要添加依赖:implementation 'androidx.webkit:webkit:1.4.0'

使用WebViewAssetLoader加载离线资源可以避免直接通过file://xxx 协议加载本地资源请求接口产生的跨域问题,以及使用file协议可能产生的安全问题,WebViewAssetLoader也是google官方推荐加载离线资源的方式

WebViewAssetLoader内置了三个对象来帮助开发者加载离线资源

内置对象作用
InternalStoragePathHandlerdata/data/${applicationId}/下面的资源
AssetsPathHandlerapk里面assets中的资源
ResourcesPathHandlerapk里面res中的资源

下面一InternalStoragePathHandler为例展示离线加载data/data/${applicationId}/files/webApp/中的内容

class DemoActivity : AppCompatActivity() {
    private val TAG: String = "DemoActivity"
    lateinit var webView: WebView
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_demo)
        val webContainer = findViewById<FrameLayout>(R.id.webContainer)
        webView = WebView(this)
        webContainer.addView(
            webView,
            FrameLayout.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT
            )
        )
        initWebView()
        //加载页面
        webView.loadUrl("https://www.baidu.com/index.html")
    }

    private fun initWebView() {
        WebView.setWebContentsDebuggingEnabled(true)
        //离线资源路径
        val publicDir = File(filesDir, "webApp")
        Log.d(TAG, "filesDir:${filesDir.absolutePath}")
        val webViewAssetLoader = WebViewAssetLoader.Builder()
            .setDomain("www.baidu.com")//设置域名,在该域名优先适用离线资源,离线资源不可以用时再使用在线资源
            .addPathHandler("/", WebViewAssetLoader.InternalStoragePathHandler(this, publicDir))//对所有资源优先检查离线资源
            .build()

        webView.webViewClient = OffLineWebViewClient(webViewAssetLoader)
        webView.isClickable = true
        //webView的一些常见设置
        webView.setOnTouchListener { v: View?, event: MotionEvent? -> false }
        val webSetting = webView.settings
        webSetting.javaScriptEnabled = true
        webSetting.javaScriptCanOpenWindowsAutomatically = true
        webSetting.domStorageEnabled = true
    }

    override fun onBackPressed() {
        if (webView.canGoBack()) {
            webView.goBack()
            return
        }
        super.onBackPressed()
    }

    override fun onDestroy() {
        super.onDestroy()
        webView.destroy()
    }
}

OffLineWebViewClient

class OffLineWebViewClient(private val assetLoader: WebViewAssetLoader) : WebViewClientCompat() {


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

离线资源index.html

<html>

<body>
    <div style="font-size: 18px;">helle world</div>
</body>

</html>

离线资源目录data/data/${applicationId}/files/webApp/index.html 离线文件可以通过下载从静态资源zip包,然后解压到对应目录。

20221121162152.jpg

运行效果(即使没有网络的情况下也能正常加载离线资源)

20221121162213.jpg