Android 13+已设为默认短信应用但代码识别失败问题
Android 13+ 默认短信应用检测异常问题修复
问题现象
应用在Android 12及以下版本可正常设置为默认短信应用,日志打印✅ Successfully became default SMS app.;但在Android 13+版本中,即使系统设置显示已设为默认,日志仍打印❌ Failed to become default SMS app.,导致发送短信时抛出"应用不是默认短信应用"异常,仅接收短信功能正常。
核心原因
- 系统角色变更异步延迟:Android 13+中设置默认短信应用后,系统需要时间同步状态,过早调用
Telephony.Sms.getDefaultSmsPackage()会获取到旧值。 - 重试机制不足:当前仅重试1次,无法覆盖系统同步的时间差。
- 未利用RoleManager返回结果:Android Q及以上版本,
startActivityForResult的resultCode可直接判断用户是否同意授予短信角色,无需完全依赖延迟的getDefaultSmsPackageAPI。
修复方案
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
相关产品推荐
相关产品推荐

