如何在服务中使用 Jetpack Compose(浮动窗口)

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

我想使用Jetpack Compose来实现浮动窗口UI。但我得到了这个错误:

java.lang.IllegalStateException: ViewTreeLifecycleOwner not found from androidx.compose.ui.platform.ComposeView
这是我的浮窗服务代码:

class FloatingService : Service() {
    private lateinit var windowManager: WindowManager

    private lateinit var contentView: View

    private lateinit var layoutParams: WindowManager.LayoutParams

    // init windowManager, contentView, layoutParams
    override fun onCreate() {
        super.onCreate()

        windowManager = getSystemService<WindowManager>()!!


        contentView = ComposeView(this).apply {
            setContent {
                Text(text = "Hello World")
            }
        }

        layoutParams = WindowManager.LayoutParams().apply {
            type = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
                WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
            else
                WindowManager.LayoutParams.TYPE_PHONE

            width = WindowManager.LayoutParams.WRAP_CONTENT
            height = WindowManager.LayoutParams.WRAP_CONTENT
            flags =
                WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
            x = 0
            y = 200

            format = PixelFormat.RGBA_8888 // give window transparent background

            gravity = Gravity.TOP or Gravity.END // layout right
        }
    }

    // add contentView to windowManager
    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        windowManager.addView(
            contentView,
            layoutParams
        )
        return super.onStartCommand(intent, flags, startId)
    }

    override fun onDestroy() {
        super.onDestroy()
        windowManager.removeView(contentView)
    }

    override fun onBind(intent: Intent?): IBinder? {
        return null
    }
}

我确认当您使用

contentView
初始化
Button(this)
时它可以正常工作。更重要的是,我尝试在
LifecycleService
中使用
implementation("androidx.lifecycle:lifecycle-service:2.5.1")
并使用
ViewTreeLifecycleOwner
来初始化
ViewTreeLifecycleOwner.set(contentView, this)
,结果是我又得到了另一个错误:
java.lang.IllegalStateException: Composed into the View which doesn't propagateViewTreeSavedStateRegistryOwner!

android android-jetpack-compose android-service android-lifecycle
1个回答
2
投票

好的。这是我自己的解决方案

  1. 添加此依赖:
implementation("androidx.lifecycle:lifecycle-service:2.5.1")
  1. 根据我问题中的代码进行以下更改
import android.content.Intent
import android.view.View
import androidx.compose.material3.Text
import androidx.compose.ui.platform.ComposeView
import androidx.lifecycle.LifecycleService
import androidx.savedstate.SavedStateRegistry
import androidx.savedstate.SavedStateRegistryController
import androidx.savedstate.SavedStateRegistryOwner

// you need extends LifecycleService and implement SavedStateRegistryOwner.
class YourService() : LifecycleService(), SavedStateRegistryOwner {

    // create a SavedStateRegistryController to get SavedStateRegistry object.
    private val savedStateRegistryController = SavedStateRegistryController.create(this)

    private lateinit var contentView: View

    override fun onCreate() {
        super.onCreate()
        // init your SavedStateRegistryController
        savedStateRegistryController.performAttach() // you can ignore this line, becase performRestore method will auto call performAttach() first.
        savedStateRegistryController.performRestore(null)

        // configure your ComposeView
        contentView = ComposeView(this).apply {
            setViewTreeSavedStateRegistryOwner(this@YourService)
            setContent {
                Text(text = "Hello World")
            }
        }
        ViewTreeLifecycleOwner.set(contentView, this)

        // init your WindowManager and LayoutParams
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        return super.onStartCommand(intent, flags, startId)
        // add your contentView to windowManager
    }

    override fun onDestroy() {
        super.onDestroy()
        // remove your view from your windowManager
    }

    // override savedStateRegistry property from SavedStateRegistryOwner interface.
    override val savedStateRegistry: SavedStateRegistry
        get() = savedStateRegistryController.savedStateRegistry
}
  1. 注册您的服务并声明
    android.permission.SYSTEM_ALERT_WINDOW
    许可。
© www.soinside.com 2019 - 2024. All rights reserved.