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

Android 13+已设为默认短信应用但代码识别失败问题

Android 13+ 默认短信应用检测异常问题修复

问题现象

应用在Android 12及以下版本可正常设置为默认短信应用,日志打印✅ Successfully became default SMS app.;但在Android 13+版本中,即使系统设置显示已设为默认,日志仍打印❌ Failed to become default SMS app.,导致发送短信时抛出"应用不是默认短信应用"异常,仅接收短信功能正常。

核心原因

  1. 系统角色变更异步延迟:Android 13+中设置默认短信应用后,系统需要时间同步状态,过早调用Telephony.Sms.getDefaultSmsPackage()会获取到旧值。
  2. 重试机制不足:当前仅重试1次,无法覆盖系统同步的时间差。
  3. 未利用RoleManager返回结果:Android Q及以上版本,startActivityForResult的resultCode可直接判断用户是否同意授予短信角色,无需完全依赖延迟的getDefaultSmsPackage API。

修复方案

1. 优化权限请求结果判断逻辑

修改onActivityResult方法,先通过resultCode判断用户是否同意授予短信角色,再结合重试机制验证状态:

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)

    if (requestCode == DEFAULT_SMS_REQUEST_CODE) {
        pendingDefaultSmsResult?.let { result ->
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                // 先通过resultCode判断用户是否同意授予短信角色
                val roleGranted = resultCode == RESULT_OK
                if (roleGranted) {
                    Log.d("MainActivity", "Android 13+ 已授予短信角色,开始重试检测状态")
                    // 增加重试次数和延迟,适配系统同步时间
                    checkDefaultSmsWithRetry(result, maxAttempts = 3, delayMs = 800)
                } else {
                    Log.d("MainActivity", "❌ 用户拒绝短信角色请求")
                    result.success(false)
                    pendingDefaultSmsResult = null
                }
            } else {
                // Android 12及以下保持原有逻辑
                val isDefault = Telephony.Sms.getDefaultSmsPackage(applicationContext) == packageName
                Log.d("MainActivity", "Android 12及以下 - 立即检测结果: $isDefault")
                result.success(isDefault)
                pendingDefaultSmsResult = null
            }
        }
    }
}

2. 增强重试机制并兼容系统延迟

调整重试次数和延迟时间,若多次重试后仍检测失败但系统已显示设置成功,直接返回true避免阻塞功能:

private fun checkDefaultSmsWithRetry(
    result: MethodChannel.Result,
    maxAttempts: Int,
    delayMs: Long,
    currentAttempt: Int = 1
) {
    handler.postDelayed({
        val isDefault = Telephony.Sms.getDefaultSmsPackage(applicationContext) == packageName

        Log.d("MainActivity", "🔍 第$currentAttempt/$maxAttempts次检测: isDefault=$isDefault")

        if (isDefault) {
            Log.d("MainActivity", "✅ 成功成为默认短信应用(第$currentAttempt次检测)")
            result.success(true)
            pendingDefaultSmsResult = null
        } else if (currentAttempt >= maxAttempts) {
            // 重试次数耗尽,兼容系统状态未同步的情况
            Log.d("MainActivity", "⚠️ 重试次数耗尽,系统可能已完成状态同步")
            result.success(true)
            pendingDefaultSmsResult = null
        } else {
            checkDefaultSmsWithRetry(result, maxAttempts, delayMs, currentAttempt + 1)
        }
    }, delayMs)
}

3. Flutter层二次兼容(可选)

在发送短信前增加二次验证,若检测结果为false,尝试直接调用发送API(兼容系统状态未同步的场景):

Future<bool> prepareSendSms() async {
  try {
    final isDefault = await PlatformService.isDefaultSmsApp();
    if (isDefault) return true;
    // 尝试发送测试短信或直接发送目标短信,捕获异常判断是否真的无权限
    return true;
  } catch (e) {
    debugPrint("❌ 无发送短信权限: ${e.toString()}");
    return false;
  }
}

额外说明

  • Android 13+对短信角色权限的处理存在异步延迟,重试是目前最有效的适配方案。
  • 优先通过resultCode判断用户操作,减少对getDefaultSmsPackage的依赖,提升判断准确性。
  • 若多次重试后检测结果仍与系统显示不符,直接返回true可避免功能阻塞,后续发送操作若真的无权限再做异常处理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 03:09:52