在前台的Activity和WindowManager之间共享WebView对象

问题描述 投票:0回答:1

我试图在前台显示带有浮动视图的WebView,我从活动的伴随对象中获取WebView,并通过删除WebView的父级将其添加到浮动视图中,并且它可以工作并显示WebView,而不会丢失当前加载的页面。

问题是当用户想要返回应用程序时我想将此网络视图返回到活动中。 同样的方法(从前台获取 webview 并删除 webview 的父级并赋予它组成 AndroidView 小部件)不起作用,并且活动不显示 webview,并且如果我之后切换到浮动小部件,它也不会显示在前台

前景中的浮动视图:

class OverlayWebViewScreen(
    private val context: Context, 
    private val webView: WebView, 
    val lifecycleService: ForegroundComposeLifeCycle
) {

    private lateinit var windowManager: WindowManager
    private lateinit var layoutParams: WindowManager.LayoutParams
    fun open() {
        PermissionManager.askForDisplayOverApps(context)
        context.run {
            windowManager = getSystemService(Context.WINDOW_SERVICE) as WindowManager
            layoutParams = WindowManager.LayoutParams(
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
                PixelFormat.TRANSLUCENT
            )

            val parentView = webView.parent as? ViewGroup
            parentView?.removeView(webView)
            val composableView = ComposeView(context)
            lifecycleService.attachToDecorView(composableView)
            lifecycleService.onResume()
            composableView.setViewTreeLifecycleOwner(lifecycleService)


            composableView.setContent {
                var offsetX by remember { mutableFloatStateOf(0f) }
                var offsetY by remember { mutableFloatStateOf(0f) }
                Column(modifier = Modifier.size(300.dp)) 
                {
                    Row {
                        Icon(
                            modifier = Modifier
                                .background(color = Color.Magenta)
                                .pointerInput(Unit) {
                                    detectDragGestures { change, dragAmount ->
                                        offsetX += dragAmount.x
                                        offsetY -= dragAmount.y
                                        layoutParams.x = offsetX.toInt()
                                        layoutParams.y = offsetY.toInt()
                                        windowManager.updateViewLayout(composableView, layoutParams)
                                    }
                                },
                            imageVector = Icons.Default.DragHandle, contentDescription = null
                        )
                        IconButton(onClick = {
                            windowManager.removeView(composableView)
                            ServiceManager.restartActivityWhenKilled(context)
                        }) {
                            Icon(
                                modifier = Modifier
                                    .background(color = Color.Magenta)
                                    ,
                                imageVector = Icons.Default.OpenInFull, contentDescription = null
                            )
                        }
                    }

                    AndroidView(
                        modifier = Modifier.size(200.dp),
                        factory = {
                            webView 
                        }
                    )
                    AdsManager.BannerAdView(modifier = Modifier)
                }
            }

            // Set the position of the WebView at the bottom of the screen
            layoutParams.gravity = Gravity.BOTTOM or Gravity.START

            windowManager.addView(composableView,layoutParams)
        }
    }

    fun close(){
        ServiceManager.restartActivityWhenKilled(context)
    }

}

Activity 的 onStart 方法是 Compose,我从前台服务获取 webview

override fun onStart() {
        val backPressedCallback = onBackPressedCallbackOverride()
        logger("onStart")
        if (ServiceManager.isServiceActive()){
            val parentView = webView.parent as? ViewGroup
            parentView?.removeView(webView)
            webView = AutoRefreshService.getWebView()
            webViewChanged.value = webViewChanged.value.not()
            logger(webView.toString())
        }
        setContent {
            val context = LocalContext.current
            val activity = context as? ComponentActivity
            activity?.onBackPressedDispatcher?.addCallback(this, backPressedCallback)
            InitVariables()
            AutoRefreshWebPageTheme {
                Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background) {
                    Scaffold(
                        modifier = Modifier.fillMaxSize(),
                    ) { paddingValues ->
                        Column(modifier = Modifier.padding(paddingValues)) {

                            AndroidView(
                                modifier = Modifier.weight(1f),
                                update = {
                                    if (webViewChanged.value)
                                        webView.bringToFront()
                                },
                                factory = { webView },
                            )
                            AdsManager.BannerAdView(modifier = Modifier)
                        }
                    }
                    if (autoRefreshDialog.value) {
                        AutoRefreshDialog()
                    }

                }
            }
        }
        if (preferences.getAutoRefreshStatus()){
            if (ServiceManager.isServiceActive().not()) {
                startPageReloading(this)
            }
        }
        super.onStart()
    }

我尝试使用 compainion 对象来跨应用程序共享 webview,它在探查器中仅占用 200mb 的内存。 我从 Activity 中获取了 WebView 并将其应用于前台,它甚至显示了带有加载屏幕的 WebView。但相反的方法(将 webview 从前台带到 Activity 不起作用) 视频:here is situation

我的期望是通过加载的 webview 屏幕返回到活动

android-activity service webview foreground jetpack
1个回答
0
投票

经过几次尝试,我找到了解决方案: 解决方案是我没有将 webview 附加到 jetpack compose 中的 androidView,因为我不知道该怎么做,但我发现:

附加到AndroidView父组将是这样的:

AndroidView(
modifier = Modifier.weight(1f),
update = { view ->
    val viewGroup = view.parent as? ViewGroup
    viewGroup?.let {
        // I used webViewGroup variable to keep view's parent in case it's 
        //changed unexpectedly
        if (::webViewGroup.isInitialized.not()){
            webViewGroup = viewGroup 
            // removing webview's current parent and attach to activity's 
            //parent
            val parentView = webView.parent as? ViewGroup
            parentView?.removeView(webView)
            webViewGroup.addView(webView)
        }
    }
},
factory = { webView },
© www.soinside.com 2019 - 2024. All rights reserved.