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

Android Kotlin 悬浮View/Service中无法启动相机预览问题求助

核心问题排查与修复方案

代码存在的问题:

  • ViewBinding未初始化:你声明了lateinit var binding: OverlayLayoutBinding但没有做绑定操作,inflate出mFloatingView后需要补充binding = OverlayLayoutBinding.bind(mFloatingView),否则访问binding.viewFinder会直接抛出异常,相机预览无法关联到对应控件。
  • 生命周期所有者参数非法:你定义的全局context变量默认值为null,将其强转为LifecycleOwner传入CameraX绑定逻辑必然崩溃。同时普通Service没有实现LifecycleOwner接口,无法直接为CameraX提供生命周期支持,需要改为继承LifecycleService。
  • 重复初始化相机:onCreate中连续两次调用startCamera,会导致相机资源抢占,触发初始化失败。
  • 前台服务逻辑缺失:startMyOwnForeground方法未实现,Android 8.0及以上系统要求前台服务必须创建合法通知渠道并展示有效通知,否则服务会被系统直接杀死。
  • 权限配置不全:该功能需要悬浮窗权限、相机权限、Android 12+的相机前台服务权限,缺少任意权限都会导致功能失效。

修改后的核心代码:

// 继承LifecycleService获取生命周期能力
class FloatingViewService : LifecycleService() {
    private var mWindowManager: WindowManager? = null
    private lateinit var binding: OverlayLayoutBinding
    private var imageCapture: ImageCapture? = null
    private var mFloatingView: View? = null
    private var params: WindowManager.LayoutParams? = null

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

    @SuppressLint("ClickableViewAccessibility")
    override fun onCreate() {
        super.onCreate()
        // 补全前台服务逻辑
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val channelId = "floating_camera_channel"
            val channel = NotificationChannel(channelId, "悬浮相机服务", NotificationManager.IMPORTANCE_LOW)
            getSystemService(NotificationManager::class.java).createNotificationChannel(channel)
            val notification = Notification.Builder(this, channelId)
                .setContentTitle("悬浮相机运行中")
                .setSmallIcon(R.drawable.ic_launcher_foreground)
                .build()
            startForeground(1, notification)
        } else {
            startForeground(1, Notification())
        }
        // 加载布局并初始化binding
        mFloatingView = LayoutInflater.from(this).inflate(R.layout.overlay_layout, null)
        binding = OverlayLayoutBinding.bind(mFloatingView!!)

        val LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
        params = WindowManager.LayoutParams(
            WindowManager.LayoutParams.WRAP_CONTENT,
            WindowManager.LayoutParams.WRAP_CONTENT,
            LAYOUT_FLAG,
            WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
            PixelFormat.TRANSLUCENT
        )

        mWindowManager = getSystemService(WINDOW_SERVICE) as WindowManager
        mWindowManager!!.addView(mFloatingView, params)

        // 只调用一次相机初始化,且在binding初始化之后执行
        startCamera()
    }

    private fun startCamera() {
        val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
        cameraProviderFuture.addListener({
            val cameraProvider = cameraProviderFuture.get()
            val preview = Preview.Builder()
                .build()
                .also {
                    it.setSurfaceProvider(binding.viewFinder.surfaceProvider)
                }
            imageCapture = ImageCapture.Builder().build()
            val cameraSelector = CameraSelector.DEFAULT_FRONT_CAMERA
            try {
                cameraProvider.unbindAll()
                // 直接传当前LifecycleService作为生命周期所有者
                cameraProvider.bindToLifecycle(this, cameraSelector, preview, imageCapture)
            } catch (e: Exception) {
                Log.d(Constants.TAG, "相机启动失败", e)
            }
        }, ContextCompat.getMainExecutor(this))
    }
}

清单文件配置补充:

<!-- 权限声明 -->
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_CAMERA" />

<!-- 服务注册 -->
<service
    android:name=".FloatingViewService"
    android:foregroundServiceType="camera"
    android:exported="false" />

额外注意事项

需要提前向用户动态申请悬浮窗权限和相机权限,用户同意后再启动服务。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 04:45:04