最近在用compose重构公司的主要APP,由于compose的一些独特设计理念,开发中也遇到很多问题,大多数甚至网上找不到相关资料,只好自己查阅有些晦涩难懂的官方文档,摸索着解决,并记录下来,有需要可以提供参考。

以前实现webView文件选择都是用Activity.startActivityForResultonActivityResult回调,但是这两个方法由于存在安全问题,现在官方准备弃用,不推荐使用了,推荐使用registerForActivityResult 和 ActivityResultLauncher.lauch()方法实现

一、compose使用webView

这部分内容不是本篇文章重点,就不展开介绍了,可以参考网上其他文章,例如:Jetpack Compose – WebView 使用方法,或者直接看wanAndroid大佬的composewanAndroid源码文章地址Compose+MVI+Navigation实现wanAndroid客户端结构非常清楚

二、配置webSettings

注意要开启javaScriptEnabled

	@SuppressLint("SetJavaScriptEnabled")
    private fun setWebSettings() {
        val webSettings = webView.settings
        //如果访问页面中要与Javascript交互,则webview必须设置支持Javascript
        webSettings.javaScriptEnabled = true
        //设置适应屏幕,两者合用
        webSettings.useWideViewPort = true //将图片调整到适合webview大小
        webSettings.loadWithOverviewMode = true // 缩放屏幕大小
        //缩放操作
        webSettings.setSupportZoom(true) //支持缩放默认为true。是下面那个的前提。
        webSettings.builtInZoomControls = true //设置内置的缩放控件。若为false,则该WebView不可缩放
        webSettings.displayZoomControls = false //隐藏原生的缩放控件

        webSettings.domStorageEnabled = true // 开启 DOM storage API 功能

        //其他细节操作
        webSettings.cacheMode = WebSettings.LOAD_CACHE_ELSE_NETWORK //关闭webview缓存
        webSettings.allowFileAccess = true //设置可以访问文件
        webSettings.javaScriptCanOpenWindowsAutomatically = true //支持通过JS打开窗口
        webSettings.loadsImagesAutomatically = true //支持自动加载图片
        webSettings.defaultTextEncodingName = "UTF-8"//设置编码格式
    }

三、配置WebViewChromeClient

注意:重写onShowFileChooser()方法,该方法在Android5.0以前还有两个老版本,但是我项目minSDK > 23所以就重写一个版本就好了

	private var uploadMessageAboveL: ValueCallback<Array<Uri>>? = null
	
	inner class ProgressWebViewChromeClient : WebChromeClient() {
        override fun onProgressChanged(view: WebView?, newProgress: Int) {
            super.onProgressChanged(view, newProgress)
            progressBar.progress = newProgress
        }

        override fun onReceivedTitle(view: WebView?, title: String?) {
            super.onReceivedTitle(view, title)
        }

        override fun onShowFileChooser(
            webView: WebView?,
            filePathCallback: ValueCallback<Array<Uri>>?,
            fileChooserParams: FileChooserParams?
        ): Boolean {
            uploadMessageAboveL = filePathCallback
            MyApp.imageResultLauncher.launch("image/*")
            return true
        }
    }

四、注册ResultLauncher

我是在Application中创建和持有,在Activity的onCreate中注册

由于框架结构性能等原因,compose推荐只有一个Activity,我的项目中因为需要集成微信登陆,所以只有一个WxEntryActivity作为主Activity

@HiltAndroidApp
class MyApp: Application() {

    companion object {
        @SuppressLint("StaticFieldLeak")
        lateinit var CONTEXT: Context

        //创建ActivityResultLauncher,用于接收onActivityResult的回调信息
        lateinit var imageResultLauncher: ActivityResultLauncher<String>

        //将ActivityResultLauncher的回调信息传递给MutableLiveData,并在web组件监听该LiveData
        val imageResult: MutableLiveData<List<Uri>> = MutableLiveData()

    }

    override fun onCreate() {
        super.onCreate()
        CONTEXT = this
    }
}
@AndroidEntryPoint
class WXEntryActivity : ComponentActivity() {

    companion object {
        const val TAG = "WXEntryActivity"

        //因为只有这一个Activity,所以可以作为全局lifeCycleOwner
        lateinit var instant: WXEntryActivity
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            ...
        }
        instant = this

        //注册图片选择器
        imageResultLauncher = registerForActivityResult(ActivityResultContracts.GetMultipleContents()) {
            //获取到了图片,传递给LiveData
            LogUtils.i("WXEntryActivity", "resultLauncher: $it")
            imageResult.value = it
        }
    }
}

五、创建result的LiveData或者flow设置发送)和观察(接受)数据

在上一步代码可以看到,我也是在Application中创建和持有imageResult这个LiveData

然后注册的图片选择器结果回调中更新数据

最后在webViewCtrl监听数据变化,并调用uploadMessageAboveL 的 onReceiveValue 回调。其中uploadMessageAboveL 是啥不清楚的见第三步,在onShowFileChooser中将filePathCallBack引用给它

	private fun initObserver() {
        LogUtils.d("WebViewCtrl", "initObserver")
        MyApp.imageResult.observe(WXEntryActivity.instant){
            LogUtils.d("WebViewCtrl", "observe: $it")
            uploadMessageAboveL?.onReceiveValue(it.toTypedArray())
        }
    }

原文地址:https://blog.csdn.net/LiePy/article/details/125797893

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。

如若转载,请注明出处:http://www.7code.cn/show_8175.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注