三星Android14 One UI6及Pixel6设备Media投影权限弹窗重复弹出求助
Android 14(三星One UI 6/Pixel 6)MediaProjection权限弹窗重复弹出问题排查与修复
问题现象
在搭载Android 14 One UI 6的三星设备及Pixel 6(Android 14)设备上,MediaProjection权限弹窗持续重复弹出,干扰正常功能;该问题未在其他设备出现。
期望行为
权限弹窗在用户授权后不应反复弹出。
提供的代码片段
权限请求触发逻辑
private fun setupMediaIntent() { try { if (!screenshotUtil.isMediaProjectionEnabled()) { val mediaProjectionManager = context?.getSystemService(Context.MEDIA_PROJECTION_SERVICE) as MediaProjectionManager startForResult.launch(mediaProjectionManager.createScreenCaptureIntent()) } else { handleNavigation() } } catch (exx: Exception) { exx.printStackTrace() } }
权限结果回调与导航逻辑
private val startForResult = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { activityResult -> try { if (activityResult.resultCode == Activity.RESULT_OK) { screenshotUtil.setResultCode(activityResult.resultCode) screenshotUtil.setMediaProjectionIntent(activityResult.data) ServiceUtils.restartService( requireContext(), ServiceType.AUTO_SCREENSHOTS.value ) handleNavigation() } else { setupMediaIntent() } } catch (exx: Exception) { exx.printStackTrace() } } private fun handleNavigation() { PreferencesUtils.setPreference(requireContext(), SETUP_FINISHED, "true") PreferencesUtils.setRestartVirtualDisplay(requireContext(), "false") if (initialSetup || fromDashboard) { LogUtil.writeLog( requireContext(), "Initial Permission", "Media Projection Permission Enabled" ) findNavController().popBackStack(R.id.mainFragment, false) } else { activity?.finishAffinity() } Constants.finishes = true }
问题排查与修复方案
1. 紧急修复:终止权限拒绝后的无限弹窗循环
当前代码中,当用户**拒绝权限(resultCode != RESULT_OK)**时,会递归调用setupMediaIntent(),直接触发新一轮权限弹窗,形成无限循环。这是导致弹窗反复出现的核心原因之一,尤其是Android 14设备对权限交互的检测更严格,会放大这个问题。
修复代码:
将startForResult的else分支替换为用户提示,而非强制重新请求:
private val startForResult = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { activityResult -> try { if (activityResult.resultCode == Activity.RESULT_OK) { screenshotUtil.setResultCode(activityResult.resultCode) screenshotUtil.setMediaProjectionIntent(activityResult.data) ServiceUtils.restartService( requireContext(), ServiceType.AUTO_SCREENSHOTS.value ) handleNavigation() } else { // 替换为:提示用户需要权限才能使用功能,而非重新弹窗 Toast.makeText(requireContext(), "需要授予屏幕录制权限才能继续", Toast.LENGTH_LONG).show() // 或引导用户到应用设置页开启权限 // findNavController().navigate(R.id.permissionGuideFragment) } } catch (exx: Exception) { exx.printStackTrace() } }
2. 验证isMediaProjectionEnabled()的正确性
检查screenshotUtil中的isMediaProjectionEnabled()方法,确保它能准确判断权限是否已授权:
- 需同时验证保存的resultCode是否为RESULT_OK,以及MediaProjection Intent是否不为null
- 确认权限状态已持久化到SharedPreferences或其他存储,且重启应用后仍能正确读取
- Android 14中,MediaProjection Intent不会永久有效,若系统回收了相关资源,需重新请求,但正常使用场景下无需频繁弹窗
示例正确的判断逻辑:
// 示例:screenshotUtil中的isMediaProjectionEnabled()实现 fun isMediaProjectionEnabled(): Boolean { val resultCode = PreferencesUtils.getInt(context, "media_projection_result_code", Activity.RESULT_CANCELED) val intent = PreferencesUtils.getParcelable<Intent>(context, "media_projection_intent") return resultCode == Activity.RESULT_OK && intent != null }
3. 适配Android 14 MediaProjection权限规则
Android 14对MediaProjection新增了限制:
- 权限请求必须在前台用户交互流程中发起,不能由后台服务或广播触发
- 若应用退到后台后重新请求权限,系统会拦截或强制重新弹窗
检查点:
- 确保
setupMediaIntent()仅在用户主动触发操作(如点击按钮)时调用,而非页面自动加载时触发 - 重启
AUTO_SCREENSHOTS服务时,需复用已保存的MediaProjection实例,而非重新请求权限
4. 设备特定行为排查
- 三星One UI 6:检查应用权限设置中,是否开启了「屏幕录制」权限,部分三星设备会单独管理该权限的持久化状态
- Pixel 6 Android 14:验证是否开启了应用的「后台活动」权限,若后台权限受限,可能导致MediaProjection实例被回收,触发重新请求
总结
- 先修复权限拒绝后的无限循环逻辑,避免强制反复弹窗
- 确保权限状态的持久化与判断逻辑准确
- 严格遵循Android 14的MediaProjection权限交互规则
- 针对三星/Pixel设备的权限特性做适配
内容的提问来源于stack exchange,提问作者Kiruba
相关产品推荐
相关产品推荐

