You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

三星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实例被回收,触发重新请求

总结

  1. 先修复权限拒绝后的无限循环逻辑,避免强制反复弹窗
  2. 确保权限状态的持久化与判断逻辑准确
  3. 严格遵循Android 14的MediaProjection权限交互规则
  4. 针对三星/Pixel设备的权限特性做适配

内容的提问来源于stack exchange,提问作者Kiruba

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 10:12:08