Android 12及以上版本录屏权限重复请求问题求助
Android 12+ 录屏权限仅请求一次的实现方案
核心逻辑
Android 12及以上版本中,MEDIA_PROJECTION录屏权限默认是单次会话权限,但系统允许开发者保存用户授权后的权限令牌(即授权返回的Intent),后续启动录屏时复用该令牌,无需再次弹出授权弹窗。注意:设备重启后令牌会失效,此时必须重新请求权限,这是系统硬性限制,所有应用都无法绕过。
具体实现步骤
1. 首次授权后保存令牌
当用户首次同意录屏权限后,将授权返回的Intent持久化存储(推荐用SharedPreferences):
Kotlin 代码示例
private const val REQUEST_CODE_SCREEN_CAPTURE = 1001 // 初始化MediaProjectionManager val mediaProjectionManager = getSystemService(MEDIA_PROJECTION_SERVICE) as MediaProjectionManager // 启动权限请求 startActivityForResult(mediaProjectionManager.createScreenCaptureIntent(), REQUEST_CODE_SCREEN_CAPTURE) // 处理授权结果 override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) if (requestCode == REQUEST_CODE_SCREEN_CAPTURE && resultCode == RESULT_OK) { data?.let { // 保存Intent到SharedPreferences val sharedPref = getSharedPreferences("ScreenCapturePrefs", MODE_PRIVATE) sharedPref.edit().putParcelable("media_projection_token", it).apply() // 初始化MediaProjection并启动录屏 val mediaProjection = mediaProjectionManager.getMediaProjection(resultCode, it) startScreenRecording(mediaProjection) } } }
Java 代码示例
private static final int REQUEST_CODE_SCREEN_CAPTURE = 1001; // 初始化MediaProjectionManager MediaProjectionManager mediaProjectionManager = (MediaProjectionManager) getSystemService(MEDIA_PROJECTION_SERVICE); // 启动权限请求 startActivityForResult(mediaProjectionManager.createScreenCaptureIntent(), REQUEST_CODE_SCREEN_CAPTURE); // 处理授权结果 @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == REQUEST_CODE_SCREEN_CAPTURE && resultCode == RESULT_OK) { if (data != null) { // 保存Intent到SharedPreferences SharedPreferences sharedPref = getSharedPreferences("ScreenCapturePrefs", MODE_PRIVATE); SharedPreferences.Editor editor = sharedPref.edit(); editor.putParcelable("media_projection_token", data); editor.apply(); // 初始化MediaProjection并启动录屏 MediaProjection mediaProjection = mediaProjectionManager.getMediaProjection(resultCode, data); startScreenRecording(mediaProjection); } } }
2. 后续启动复用令牌
每次启动录屏前,先读取保存的令牌,若有效则直接复用:
Kotlin 代码示例
val sharedPref = getSharedPreferences("ScreenCapturePrefs", MODE_PRIVATE) val savedToken = sharedPref.getParcelable<Intent>("media_projection_token") if (savedToken != null) { try { val mediaProjection = mediaProjectionManager.getMediaProjection(RESULT_OK, savedToken) mediaProjection?.let { startScreenRecording(it) return } } catch (e: Exception) { // 令牌失效,清除存储并重新请求权限 sharedPref.edit().remove("media_projection_token").apply() } } // 无有效令牌,重新请求权限 startActivityForResult(mediaProjectionManager.createScreenCaptureIntent(), REQUEST_CODE_SCREEN_CAPTURE)
Java 代码示例
SharedPreferences sharedPref = getSharedPreferences("ScreenCapturePrefs", MODE_PRIVATE); Intent savedToken = sharedPref.getParcelable("media_projection_token"); if (savedToken != null) { try { MediaProjection mediaProjection = mediaProjectionManager.getMediaProjection(RESULT_OK, savedToken); if (mediaProjection != null) { startScreenRecording(mediaProjection); return; } } catch (Exception e) { // 令牌失效,清除存储并重新请求权限 SharedPreferences.Editor editor = sharedPref.edit(); editor.remove("media_projection_token"); editor.apply(); } } // 无有效令牌,重新请求权限 startActivityForResult(mediaProjectionManager.createScreenCaptureIntent(), REQUEST_CODE_SCREEN_CAPTURE);
3. 处理令牌失效场景
以下情况令牌会失效,需重新请求权限:
- 设备重启后
- 用户在系统设置中手动撤销了应用的录屏权限
- 应用被清除数据
此时getMediaProjection()会返回null或抛出异常,需捕获并重新引导授权。
关键注意事项
- 必须确保用户明确同意长期使用录屏权限,避免违反Google Play隐私政策。
- 不要尝试绕过系统限制(比如重启后仍免授权),这是Android安全机制的一部分,无法实现。
内容的提问来源于stack exchange,提问作者Kitty Kagaya
相关产品推荐
相关产品推荐

