Android 默认短信应用查询技术文档
2026/6/26 6:40:38 网站建设 项目流程

Android 默认短信应用查询技术文档

1. 需求背景

开发一个功能,用于获取 Android 系统中当前默认短信应用的包名,并查询所有具备成为默认短信应用资格的应用列表。

2. 初始实现

2.1 基础方法

fungetDefaultSmsAppPackageName(context:Context):String?{returnTelephony.Sms.getDefaultSmsPackage(context)}

这是 Android 官方提供的 API,用于获取当前默认短信应用的包名。

3. 遇到的问题

3.1 Java 版本兼容性问题

问题:

Android Gradle Plugin 8.5.1 requires Java 17 to run. You are currently using Java 11.

解决方案:

  • 降级 Android Gradle Plugin 到 7.4.2(支持 Java 11)
  • 或在gradle.properties中设置org.gradle.java.home指向 Java 17+ 的路径

3.2 PackagingOptions DSL 兼容性

问题:

Unresolved reference: packaging

AGP 7.4.2 不支持新的packaging {}DSL 语法。

解决方案:

// 旧版本语法packagingOptions{resources{excludes+="/META-INF/{AL2.0,LGPL2.1}"}}

3.3 Settings.Secure 返回 null

问题:

From Settings.Secure: null From Telephony.Sms: com.android.mms

Settings.Secure 中的sms_default_application键返回 null,但 Telephony.Sms API 能返回值。

原因:

  • 某些 ROM 可能没有正确保存设置到 Settings.Secure
  • 或者使用了不同的存储机制

解决方案:
同时使用两种方式,优先使用 Settings.Secure 的值:

fungetDefaultSmsAppPackageName(context:Context):String?{valfromSettings=Settings.Secure.getString(context.contentResolver,"sms_default_application")valfromTelephony=Telephony.Sms.getDefaultSmsPackage(context)returnfromSettings?.takeIf{it.isNotEmpty()}?:fromTelephony}

3.4 切换默认应用后值不更新

问题:
使用remember { mutableStateOf(...) }缓存了初始值,切换默认应用后显示的还是旧值。

解决方案:
使用remember(key)方式,当 key 改变时重新获取:

varrefreshCounterbyremember{mutableIntStateOf(0)}valdefaultSmsPackage=remember(refreshCounter){SmsUtils.getDefaultSmsAppPackageName(context)}

3.5 无法查询到所有短信应用 ⭐核心问题

问题:
系统设置中有 2 个短信应用(短信、测试短信),但只能查询到 1 个。

具备资格的应用: - com.vivo.easyshare (互传) - com.android.mms (信息)

缺少com.test.mms

原因分析:

通过dumpsys package可以看到这些应用确实注册了sms:scheme:

sms: 1b41c51 com.test.mms/...ComposeSmsActivity 1189e3d com.android.mms/.ui.ComposeMessageActivity 8e016f1 com.vivo.easyshare/.activity.DefaultSmsActivity

queryIntentActivities无法查询到它们。

根本原因:缺少 QUERY_ALL_PACKAGES 权限

在 Android 11(API 30)+ 中,引入了包可见性过滤。默认情况下,应用只能查询到以下内容:

  1. 自己
  2. 通过<queries>声明的应用
  3. 具有相同签名的应用

解决方案:

AndroidManifest.xml中添加:

<uses-permissionandroid:name="android.permission.QUERY_ALL_PACKAGES"tools:ignore="QueryAllPackagesPermission"/>

这个权限是特殊权限,不需要用户授权,但需要在 Google Play 审核时提供正当理由。

3.6 Intent 查询方式的限制

尝试了多种 Intent 查询方式:

// 方式1: 使用 ACTION_VIEW + sms: schemeIntent(Intent.ACTION_VIEW).apply{data=Uri.parse("sms:")addCategory(Intent.CATEGORY_DEFAULT)}// 方式2: 使用 ACTION_SENDTO + sms: schemeIntent(Intent.ACTION_SENDTO).apply{data=Uri.parse("sms:")addCategory(Intent.CATEGORY_DEFAULT)}// 方式3: 不指定 action,只用 schemeIntent().apply{data=Uri.parse("sms:")addCategory(Intent.CATEGORY_DEFAULT)}

即使添加了各种 category 组合,仍然无法查询到所有应用。

这说明某些应用的 intent-filter 配置可能比较特殊,或者使用了非标准的注册方式。

4. 最终实现

4.1 AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?><manifestxmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"><!-- 查询所有应用的权限 (Android 11+) --><uses-permissionandroid:name="android.permission.QUERY_ALL_PACKAGES"tools:ignore="QueryAllPackagesPermission"/><application...></application></manifest>

4.2 SmsUtils.kt

objectSmsUtils{privateconstvalTAG="SmsUtils"/** * 获取当前默认短信应用的包名 */fungetDefaultSmsAppPackageName(context:Context):String?{// 方式1: Settings.SecurevalfromSettings=Settings.Secure.getString(context.contentResolver,"sms_default_application")Log.d(TAG,"From Settings.Secure:$fromSettings")// 方式2: Telephony.Sms APIvalfromTelephony=Telephony.Sms.getDefaultSmsPackage(context)Log.d(TAG,"From Telephony.Sms:$fromTelephony")// 优先使用 Settings.Secure 的值valresult=fromSettings?.takeIf{it.isNotEmpty()}?:fromTelephony Log.d(TAG,"Final result:$result")returnresult}/** * 获取所有具备资格成为默认短信应用的应用列表 */fungetEligibleSmsApps(context:Context):List<AppInfo>{valapps=mutableListOf<AppInfo>()valpackageManager=context.packageManagervalseenPackages=mutableSetOf<String>()try{valintents=listOf(Intent(Intent.ACTION_VIEW).apply{data=Uri.parse("sms:")addCategory(Intent.CATEGORY_DEFAULT)addCategory(Intent.CATEGORY_BROWSABLE)},Intent(Intent.ACTION_SENDTO).apply{data=Uri.parse("sms:")addCategory(Intent.CATEGORY_DEFAULT)})for(intentinintents){valresolveInfos=packageManager.queryIntentActivities(intent,PackageManager.MATCH_DEFAULT_ONLY)for(resolveInfoinresolveInfos){valpackageName=resolveInfo.activityInfo.packageNameif(!seenPackages.contains(packageName)){seenPackages.add(packageName)valappName=resolveInfo.loadLabel(packageManager).toString()apps.add(AppInfo(packageName,appName))}}}}catch(e:Exception){Log.e(TAG,"Error:${e.message}")}returnapps.sortedBy{it.name}}/** * 打开系统默认短信应用设置页面 */funopenDefaultSmsAppSettings(context:Context){try{valintent=Intent("android.settings.DEFAULT_APP_SETTINGS")context.startActivity(intent)}catch(e:Exception){valintent=Intent("android.settings.SETTINGS")context.startActivity(intent)}}dataclassAppInfo(valpackageName:String,valname:String)}

4.3 MainActivity.kt

@ComposablefunSmsInfoScreen(modifier:Modifier=Modifier){valcontext=LocalContext.currentvarrefreshCounterbyremember{mutableIntStateOf(0)}varshowDiagnosisbyremember{mutableStateOf(false)}valdefaultSmsPackage=remember(refreshCounter){SmsUtils.getDefaultSmsAppPackageName(context)}valisDefaultApp=remember(refreshCounter){SmsUtils.isDefaultSmsApp(context)}valdiagnosis=remember(refreshCounter){SmsUtils.diagnoseDefaultSmsApp(context)}Column(modifier=modifier.fillMaxSize().padding(16.dp)){Text("默认短信应用:${defaultSmsPackage?:"未设置"}")Row{Button(onClick={SmsUtils.openDefaultSmsAppSettings(context)}){Text("打开设置")}Button(onClick={refreshCounter++}){Text("刷新")}Button(onClick={showDiagnosis=!showDiagnosis}){Text(if(showDiagnosis)"隐藏诊断"else"显示诊断")}}if(showDiagnosis){Text(diagnosis,style=MaterialTheme.typography.bodySmall)}}}

5. 关键注意事项

5.1 QUERY_ALL_PACKAGES 权限

  • 作用:允许应用查询设备上所有已安装的应用
  • 适用版本:Android 11 (API 30) 及以上
  • 授权方式:特殊权限,不需要用户运行时授权
  • Google Play 政策:使用此权限需要提供正当的使用理由

5.2 默认短信应用的条件

一个应用要成为默认短信应用,必须满足:

  1. 必需权限

    • SEND_SMS
    • RECEIVE_SMS
    • READ_SMS
    • RECEIVE_MMS
    • RECEIVE_WAP_PUSH
  2. 必需组件

    • BroadcastReceiver 处理SMS_DELIVERaction
    • BroadcastReceiver 处理WAP_PUSH_DELIVERaction
    • Service 处理RESPOND_VIA_MESSAGEaction
  3. Intent Filter

    • 处理ACTION_SENDTOsms:smsto:scheme

5.3 调试命令

# 查看所有处理短信的应用adb shell dumpsys package|grep-A5"sms:"# 查看指定应用的权限adb shell dumpsys package<package_name>|grep-ipermission

6. 总结

  1. Android 11+ 的包可见性限制是需要特别注意的问题
  2. QUERY_ALL_PACKAGES权限是解决查询不到应用的关键
  3. Settings.SecureTelephony.Sms两种方式获取默认应用各有优缺点,建议结合使用
  4. remember的使用方式会影响数据的实时更新,需要配合状态管理

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询