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




