在片段中绑定 MediaProjection 服务会导致配置更改的安全异常

问题描述

我们正在使用媒体投影前台服务。这是清单标签

 <service
            android:name=".OurService"
            android:enabled="true"
            android:exported="true"
            android:foregroundServiceType="mediaProjection" />

我们有一个名为 HostActivity 的活动,它绑定和解除绑定服务,如下所示:

override fun onStart() {
        super.onStart()
        // Bind to LocalService
        Intent(this,OurService::class.java).also { intent ->
            bindService(intent,connection,Context.BIND_AUTO_CREATE)
        }
    }

这里是连接定义:

private val connection = object : ServiceConnection {
        override fun onServiceConnected(className: ComponentName,service: IBinder) {
            Timber.d(" :$LOG_APP_NAME: HostActivity: :onServiceConnected: ")
            val binder = service as OurService.LocalBinder
            mService = binder.getService()
            mBound = true
            onServiceConnected()
        }

        override fun onServicedisconnected(arg0: ComponentName) {
            Timber.d(" :$LOG_APP_NAME: HostActivity: :onServicedisconnected: ")
            mBound = false
        }
    }

以下是我们解除服务绑定的方式:

override fun onStop() {
        Timber.d(" :$LOG_APP_NAME: HostActivity: :onStop: ")
        unbindService(connection)
        mBound = false
        super.onStop()
    }

HostActivity一个 GuestFragment(通过 NavigationControllerNavigationGraph),它也使用相同的服务下面:

这是我们使用导航通过GuestActivity显示GuestFragment的方式,GuestActivity也是一个活动HostActivity:

访客活动:

  override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val navHostFragment =
            supportFragmentManager.findFragmentById(R.id.nav_guest_fragment) as NavHostFragment
        navController = navHostFragment.navController
        val bundle = intent?.extras
        if (bundle != null) {
            navController.setGraph(R.navigation.guest_navigation,bundle)
        }
    }

这是 GuestFragment 绑定服务的方式:

override fun onStart() {
        super.onStart()
        Timber.d(" :$LOG_APP_NAME: GuestFragment: :onStart: ")
        Intent(appContext,OurService::class.java).also { intent ->
            appContext.bindService(intent,Context.BIND_AUTO_CREATE)
        }
    }

与我们在 HostActivity 中相同的 connection 定义也在这里

以下是我们在 GuestFragment 中解除绑定服务的方法

override fun onStop() {
        appContext.unbindService(connection)
        mBound = false
        super.onStop()
    }

现在,有一个 ChildActivity,其父活动是 HostActivityChildActivity 也通过 HostActivity 使用相同的 OurService

但是,ChildActivity 正在停止服务,如下所示:

stopForeground(true)
stopSelf(startId)

startId一个静态的 id,每当我们从任何视图启动服务时它都是 -1,这样我们就可以停止它,而无需等待每个视图先解除绑定。>

ChildActivity处于竖屏模式,我们启动服务,开始录屏,结束录屏,停止服务,回到GuestFragment也是竖屏的模式,它工作正常。 没问题。

但是,当ChildActivity处于横向模式时,我们启动服务,开始录屏,结束录屏,停止服务,返回处于纵向模式的 GuestFragment,我们收到了安全异常

 java.lang.SecurityException: Media projections require a foreground service of type ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION
        at android.os.Parcel.createExceptionorNull(Parcel.java:2385)
        at android.os.Parcel.createException(Parcel.java:2369)
        at android.os.Parcel.readException(Parcel.java:2352)
        at android.os.Parcel.readException(Parcel.java:2294)
        at android.media.projection.IMediaProjection$Stub$Proxy.start(IMediaProjection.java:231)
        at android.media.projection.MediaProjection.<init>(MediaProjection.java:68)
        at android.media.projection.mediaprojectionmanager.getMediaProjection(mediaprojectionmanager.java:162)

----

Caused by: android.os.remoteexception: Remote stack trace:
        at com.android.server.media.projection.mediaprojectionmanagerService$MediaProjection.start(mediaprojectionmanagerService.java:564)
        at android.media.projection.IMediaProjection$Stub.onTransact(IMediaProjection.java:135)
        at android.os.Binder.execTransactInternal(Binder.java:1190)
        at android.os.Binder.execTransact(Binder.java:1159)

我们怀疑它正在发生,因为:

  1. 导航未保留片段。
  2. HostActivity 通过具有静态 ID 的 ChildActivity 停止服务。

但是当 ChildActivity 停止服务处于纵向模式时,为什么它不会导致问题而且我们既不确定也不知道解决方案。非常感谢任何帮助、解释和相关链接

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)