英文:
how to use Jetpack Compose in Service
问题
I want to use Jetpack Compose to implement the floating window UI. But I got this error: java.lang.IllegalStateException: ViewTreeLifecycleOwner not found from androidx.compose.ui.platform.ComposeView
Here are my floating window service code:
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
}
}
I am confirming it can work well when you initialize contentView
by using Button(this)
. Furthermore, I have tried using LifecycleService
which is in implementation("androidx.lifecycle:lifecycle-service:2.5.1")
and initializing ViewTreeLifecycleOwner
by using ViewTreeLifecycleOwner.set(contentView, this)
, but the result is that I got another error: java.lang.IllegalStateException: Composed into the View which doesn't propagate ViewTreeSavedStateRegistryOwner!
.
英文:
I want to use Jetpack Compose to implement the floting window UI. But I got this error:java.lang.IllegalStateException: ViewTreeLifecycleOwner not found from androidx.compose.ui.platform.ComposeView
Here are my floating window service code:
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
}
}
I am confirm it can work good when you init contentView
by using Button(this)
. What's more, I have tried using LifecycleService
which in implementation("androidx.lifecycle:lifecycle-service:2.5.1")
and init ViewTreeLifecycleOwner
by using ViewTreeLifecycleOwner.set(contentView, this)
, the result is that I got another error: java.lang.IllegalStateException: Composed into the View which doesn't propagateViewTreeSavedStateRegistryOwner!
.
答案1
得分: 1
以下是您提供的翻译:
- 添加此依赖项:
implementation("androidx.lifecycle:lifecycle-service:2.5.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
// 您需要扩展 LifecycleService 并实现 SavedStateRegistryOwner。
class YourService() : LifecycleService(), SavedStateRegistryOwner {
// 创建 SavedStateRegistryController 以获取 SavedStateRegistry 对象。
private val savedStateRegistryController = SavedStateRegistryController.create(this)
private lateinit var contentView: View
override fun onCreate() {
super.onCreate()
// 初始化您的 SavedStateRegistryController
savedStateRegistryController.performAttach() // 您可以忽略此行,因为 performRestore 方法将自动调用 performAttach()。
savedStateRegistryController.performRestore(null)
// 配置您的 ComposeView
contentView = ComposeView(this).apply {
setViewTreeSavedStateRegistryOwner(this@YourService)
setContent {
Text(text = "Hello World")
}
}
ViewTreeLifecycleOwner.set(contentView, this)
// 初始化您的 WindowManager 和 LayoutParams
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
return super.onStartCommand(intent, flags, startId)
// 将您的 contentView 添加到 WindowManager
}
override fun onDestroy() {
super.onDestroy()
// 从 WindowManager 中删除您的视图
}
// 从 SavedStateRegistryOwner 接口重写 savedStateRegistry 属性。
override val savedStateRegistry: SavedStateRegistry
get() = savedStateRegistryController.savedStateRegistry
}
- 注册您的服务并声明
android.permission.SYSTEM_ALERT_WINDOW
权限。
英文:
OK. Here is my own solution
- add this dependence:
implementation("androidx.lifecycle:lifecycle-service:2.5.1")
- make the following changes based on the code in my question
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
}
- register you service and declare
android.permission.SYSTEM_ALERT_WINDOW
permission.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论