You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jetpack Compose前台服务悬浮窗异常:启动服务后应用崩溃

前台服务悬浮窗崩溃问题排查与解决

项目结构

  • MyActivity.kt(主Activity):包含启动和停止服务的两个按钮
  • App.kt(通知通道应用):继承Application类,用于创建通知通道
  • Foreground.kt(前台服务):继承Service类

代码实现

class Foreground : Service() {
   private lateinit var windowManager:WindowManager
   private lateinit var  floatingView : ComposeView
   
   @SuppressLint("ForegroundServiceType")
   override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
      when (intent?.action){
         "Start" -> startForeground(1,notification())
          "Stop" -> stopSelf()
      }
      return START_NOT_STICKY
   }
   
   @SuppressLint("InflateParams")
   override fun onCreate() {
      super.onCreate()
      windowManager = getSystemService(Context.WINDOW_SERVICE) as WindowManager
      floatingView = ComposeView(this)
      floatingView.setContent {
      myCanvas()
      }
      
      val params = WindowManager.LayoutParams(
         WindowManager.LayoutParams.WRAP_CONTENT,
         WindowManager.LayoutParams.WRAP_CONTENT,
         WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
         WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
         PixelFormat.TRANSLUCENT
      )
      
      windowManager.addView(floatingView, params)
   }
   
   override fun onDestroy() {
      super.onDestroy()
      windowManager.removeView(floatingView)
   }
   
   private fun notification(): Notification {
      return NotificationCompat.Builder(this, "notification")
         .setSmallIcon(R.drawable.ic_launcher_foreground)
         .setContentTitle("Title")
         .setContentText("Text")
         .build()
   }
   
   override fun onBind(p0: Intent?): IBinder? = null
}

@Composable
fun myCanvas() {
   Canvas(
      modifier = Modifier
         .fillMaxSize()
         .background(Color.Transparent)
   ) {
      drawRect(
         color = Color.Red,
         topLeft = center,
         size = Size(200.dp.toPx(), 200.dp.toPx())
      )
   }
}

需求

启动服务时,显示一个覆盖在应用上方的透明悬浮窗,展示myCanvas()的内容。

问题现象

启动应用并点击“启动服务”按钮后,应用直接崩溃关闭,无悬浮窗显示,Android Studio Logcat出现报错。已在Manifest中声明服务,服务可正常显示通知;使用Android Studio HedgeHog 2023.1.1金丝雀版本,依赖为新项目默认配置。

已尝试方案

将myCanvas()移至MainActivity中调用,或放到继承AppCompatActivity/ComponentActivity的新类中,问题依旧。


问题原因及解决方案

1. 缺失悬浮窗权限

Android 6.0+ 中,悬浮窗需要SYSTEM_ALERT_WINDOW权限,该权限无法通过常规权限申请流程获取,必须引导用户手动开启:

// 在MyActivity的启动按钮点击事件中添加权限检查
if (!Settings.canDrawOverlays(this)) {
    val intent = Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:$packageName"))
    startActivityForResult(intent, 1001)
} else {
    // 权限已获取,启动前台服务
    val intent = Intent(this, Foreground::class.java).apply { action = "Start" }
    startForegroundService(intent)
}

2. ComposeView 上下文适配问题

Service 上下文无法直接兼容 Compose 视图系统,且dp.toPx()调用需要依赖正确的密度上下文,修改myCanvas():

@Composable
fun myCanvas() {
    val density = LocalDensity.current
    Canvas(
        modifier = Modifier
            .size(200.dp)
            .background(Color.Transparent)
    ) {
        drawRect(
            color = Color.Red,
            topLeft = center,
            size = Size(with(density) { 200.dp.toPx() }, with(density) { 200.dp.toPx() })
        )
    }
}

3. 前台服务类型声明(Android 12+)

Android 12及以上版本,前台服务需指定类型,在Manifest中修改服务声明:

<service
    android:name=".Foreground"
    android:foregroundServiceType="systemExtras" />

同时移除onStartCommand上的@SuppressLint("ForegroundServiceType")注解。

4. 悬浮窗布局参数兼容

适配低版本系统的悬浮窗类型,并明确初始位置避免视图不可见:

val params = WindowManager.LayoutParams(
    WindowManager.LayoutParams.WRAP_CONTENT,
    WindowManager.LayoutParams.WRAP_CONTENT,
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
    } else {
        WindowManager.LayoutParams.TYPE_SYSTEM_ALERT
    },
    WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
    PixelFormat.TRANSLUCENT
).apply {
    gravity = Gravity.TOP or Gravity.START
    x = 100
    y = 100
}

内容的提问来源于stack exchange,提问作者Blitz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 20:22:47