Android默认短信应用选择器不显示,如何配置使应用入选?
问题描述
我正在开发一款短信应用,希望弹出默认短信应用选择器,让用户将我的应用设为默认(配图如下):
以下是我的Manifest代码:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="android.permission.SEND_SMS" /> <application android:name=".App" android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme" android:usesCleartextTraffic="true" tools:ignore="GoogleAppIndexingWarning"> <provider android:name="androidx.core.content.FileProvider" android:authorities="${applicationId}.provider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/provider_paths" /> </provider> <!-- <service android:name=".BackgroundService" />--> <!-- Service that delivers messages from the phone "quick response" --> <service android:name=".BackgroundService" android:exported="false" android:permission="android.permission.SEND_RESPOND_VIA_MESSAGE"> <intent-filter> <action android:name="android.intent.action.RESPOND_VIA_MESSAGE" /> <category android:name="android.intent.category.DEFAULT" /> <data android:scheme="sms" /> <data android:scheme="smsto" /> <data android:scheme="mms" /> <data android:scheme="mmsto" /> </intent-filter> </service> <activity android:name=".MainActivity" android:label="@string/app_name" android:theme="@style/AppTheme.NoActionBar" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <intent-filter> <action android:name="android.intent.action.SEND" /> <action android:name="android.intent.action.SENDTO" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="sms" /> <data android:scheme="smsto" /> <data android:scheme="mms" /> <data android:scheme="mmsto" /> </intent-filter> </activity> <receiver android:name=".SmsReceiver" android:permission="android.permission.BROADCAST_SMS" android:exported="false"> <intent-filter> <action android:name="android.provider.Telephony.SMS_DELIVER" /> </intent-filter> </receiver> <receiver android:name=".MmsReceiver" android:permission="android.permission.BROADCAST_WAP_PUSH" android:exported="false"> <intent-filter> <action android:name="android.provider.Telephony.WAP_PUSH_DELIVER" /> <data android:mimeType="application/vnd.wap.mms-message" /> </intent-filter> </receiver> </application>
以及我的MainActivity代码:
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if (!isDefaultSmsApp(this)) setDefaultSmsApp(); } private void setDefaultSmsApp() { Toast.makeText(this, "Setting default....", Toast.LENGTH_SHORT).show(); Intent intent = new Intent(Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT); intent.putExtra(Telephony.Sms.Intents.EXTRA_PACKAGE_NAME, getPackageName()); startActivity(intent); } public boolean isDefaultSmsApp(Context context) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { return context.getPackageName().equals(Telephony.Sms.getDefaultSmsPackage(context)); } return true; } public void requestSmsPermission() { if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.SEND_SMS)) { new AlertDialog.Builder(this) .setTitle("Permission Needed") .setMessage("This permission is needed to send messages") .setPositiveButton("Ok", (dialogInterface, i) -> ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.SEND_SMS}, ACCESS_SMS_CODE)) .setNegativeButton("Cancel", (dialogInterface, i) -> { dialogInterface.dismiss(); finish(); }) .create() .show(); } else { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.SEND_SMS}, ACCESS_SMS_CODE); } }
我尝试过使用intent.createChooser但未生效,且已在Manifest中注册相关组件,请问我遗漏了什么?
解决方案
你遗漏了几个关键配置和逻辑细节,以下是修复要点:
修正广播接收器的
exported属性
系统需要向短信、MMS广播接收器发送系统广播,当前设置的android:exported="false"会导致系统无法访问这些组件,必须改为true:<receiver android:name=".SmsReceiver" android:permission="android.permission.BROADCAST_SMS" android:exported="true"> <intent-filter> <action android:name="android.provider.Telephony.SMS_DELIVER" /> </intent-filter> </receiver> <receiver android:name=".MmsReceiver" android:permission="android.permission.BROADCAST_WAP_PUSH" android:exported="true"> <intent-filter> <action android:name="android.provider.Telephony.WAP_PUSH_DELIVER" /> <data android:mimeType="application/vnd.wap.mms-message" /> </intent-filter> </receiver>添加必要的短信权限
除了SEND_SMS,还需要添加接收短信和MMS的权限,否则系统不会将你的应用纳入默认候选:<uses-permission android:name="android.permission.RECEIVE_SMS" /> <uses-permission android:name="android.permission.RECEIVE_MMS" />完善Activity的Intent Filter
补充VIEW动作,确保系统能识别你的应用为短信类应用的候选:<intent-filter> <action android:name="android.intent.action.SEND" /> <action android:name="android.intent.action.SENDTO" /> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="sms" /> <data android:scheme="smsto" /> <data android:scheme="mms" /> <data android:scheme="mmsto" /> </intent-filter>调整权限请求与默认设置的逻辑顺序
Android 6.0+(API 23)及以上版本中,必须先获取危险权限,再触发默认应用设置跳转。修改onCreate方法:protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 先检查并请求必要权限 if (ContextCompat.checkSelfPermission(this, Manifest.permission.SEND_SMS) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this, Manifest.permission.RECEIVE_SMS) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this, Manifest.permission.RECEIVE_MMS) != PackageManager.PERMISSION_GRANTED) { requestSmsPermission(); } else { // 权限已获取,检查是否为默认应用 if (!isDefaultSmsApp(this)) { setDefaultSmsApp(); } } }更新权限请求方法,包含所有必要权限:
public void requestSmsPermission() { String[] permissions = {Manifest.permission.SEND_SMS, Manifest.permission.RECEIVE_SMS, Manifest.permission.RECEIVE_MMS}; if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.SEND_SMS)) { new AlertDialog.Builder(this) .setTitle("Permission Needed") .setMessage("This permission is needed to send and receive messages") .setPositiveButton("Ok", (dialogInterface, i) -> ActivityCompat.requestPermissions(MainActivity.this, permissions, ACCESS_SMS_CODE)) .setNegativeButton("Cancel", (dialogInterface, i) -> { dialogInterface.dismiss(); finish(); }) .create() .show(); } else { ActivityCompat.requestPermissions(this, permissions, ACCESS_SMS_CODE); } }重写权限回调方法,在权限通过后触发默认设置:
@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == ACCESS_SMS_CODE) { boolean allGranted = true; for (int result : grantResults) { if (result != PackageManager.PERMISSION_GRANTED) { allGranted = false; break; } } if (allGranted) { if (!isDefaultSmsApp(this)) { setDefaultSmsApp(); } } else { Toast.makeText(this, "Permissions are required to use this app", Toast.LENGTH_SHORT).show(); finish(); } } }关于
createChooser无效的说明ACTION_CHANGE_DEFAULT本身就是系统提供的默认应用选择界面,不需要用createChooser包裹,之前无效是因为组件配置和权限问题导致系统未将你的应用纳入候选列表,修复上述问题后即可正常弹出选择器。
内容的提问来源于stack exchange,提问作者Qasim Malik
相关产品推荐
相关产品推荐

