You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Android 14:已授予MediaProjection屏幕捕获权限却仍被反复请求

Android 14:已授予MediaProjection屏幕捕获权限却仍被反复请求

嗨,我之前也踩过这个坑!Android 14针对MediaProjection的权限机制做了隐私层面的强化调整,这就是你遇到反复弹窗请求权限的核心原因,我给你拆解一下问题和解决方案:

  • Android 14的权限规则变了:在Android 11及更早版本,用户一旦授予屏幕捕获权限,应用后续发起捕获时可以直接复用权限,不用再弹窗确认。但从Android 14开始,系统为了防止应用在用户不知情的情况下偷偷捕获屏幕,强制要求每次发起新的MediaProjection会话时,都必须经过用户再次授权——哪怕之前已经给过权限也没用,这是系统层面的硬限制。

  • 尝试复用有效的MediaProjection会话:如果你的应用现在是每次捕获都重新创建MediaProjection实例,那肯定会每次都弹权限框。你可以在应用的生命周期内(比如用全局单例或者ViewModel)保留MediaProjection实例,只要会话还没被系统终止,就复用它,这样就能避免重复请求。举个简单的示例代码:

private var mediaProjection: MediaProjection? = null
private val projectionCallback = object : MediaProjection.Callback() {
    override fun onStop() {
        // 会话被系统终止时,清空实例,下次需要重新请求
        mediaProjection = null
    }
}

fun startScreenCapture() {
    val projectionManager = getSystemService(MEDIA_PROJECTION_SERVICE) as MediaProjectionManager
    mediaProjection?.let {
        // 复用已有会话,直接启动捕获
        startCaptureWithProjection(it)
        return
    }
    // 没有有效会话,发起权限请求
    startActivityForResult(projectionManager.createScreenCaptureIntent(), REQUEST_CAPTURE_PERM)
}

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    if (requestCode == REQUEST_CAPTURE_PERM && resultCode == RESULT_OK) {
        val projectionManager = getSystemService(MEDIA_PROJECTION_SERVICE) as MediaProjectionManager
        mediaProjection = projectionManager.getMediaProjection(resultCode, data!!).apply {
            registerCallback(projectionCallback, null)
        }
        startCaptureWithProjection(mediaProjection!!)
    }
}

private fun startCaptureWithProjection(projection: MediaProjection) {
    // 这里写你的屏幕捕获逻辑,比如创建VirtualDisplay等
}

不过要注意,当你的应用退到后台超过一定时间,或者系统资源紧张时,MediaProjection会话会被系统强制回收,这时候再次发起捕获还是得重新请求权限,这个是Android 14的隐私保护机制,没办法绕过。

  • 别尝试“保存权限状态”的歪路子:有些开发者可能想通过SharedPreferences保存权限状态,然后跳过系统的Intent请求,这在Android 14上完全行不通——系统根本不认这种自定义的状态,只会强制要求每次新会话都经过用户确认。

备注:内容来源于stack exchange,提问作者Kidus

火山引擎 最新活动