androidsmsdefaulttelephony

How do I set my app as the default SMS app?


I am following this tutorial on setting my app as the default SMS app, but for some reason, my app does not appear in the list of available options. I have tried to research this as much as possible, but everything points back to that same tutorial, or is outdated. Do I need a <receiver> as well? Can someone explain what I am doing wrong?

The code:

@Override
protected void onResume()
{
    super.onResume();
    Log.i("MainAcitvity", "On Resume Called");
    // Only do these checks/changes on KitKat+, the "mSetDefaultSmsLayout" has its visibility
    // set to "gone" in the xml layout so it won't show at all on earlier Android versions.
    final String myPackageName = getPackageName();

    if (Utility.hasKitKat())
    {
        if (Utility.isDefaultSmsApp(this))
        {
            // This app is the default, remove the "make this app the default" layout and
            // enable message sending components.
            mSetDefaultSmsLayout.setVisibility(View.GONE);
        }
        else
        {
            Log.i("MainActivity", "Not Default App");
            // Not the default, show the "make this app the default" layout and disable
            // message sending components.
            mSetDefaultSmsLayout.setVisibility(View.VISIBLE);

            Button button = (Button) findViewById(R.id.set_default_sms_button);
            button.setOnClickListener(new OnClickListener()
            {
                @Override
                public void onClick(View view)
                {                        
                    Log.i("MainActivity", "Button Pushed");
                    //Utility.setDefaultSmsApp(MainActivity.this);
                    Intent intent = new Intent(Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT);
                    intent.putExtra(Telephony.Sms.Intents.EXTRA_PACKAGE_NAME, myPackageName);
                    startActivity(intent);
                }
            });
        }
    }
}

The manifest:

<activity
    android:name=".MainActivity"
    android:label="@string/app_name">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
        <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>

Solution

  • In order for your app to be eligible to be selected as the default messaging app (as far as the system is concerned), its manifest must list each of the four components as described in that blog post, whether those components' classes are actually present and functional, or not. The class names can be whatever valid names you like, but the rest of each component should be pretty much exactly as shown:

    <manifest>
        ...
        <application>
            <!-- BroadcastReceiver that listens for incoming SMS messages -->
            <receiver
                android:name=".SmsReceiver"
                android:permission="android.permission.BROADCAST_SMS">
                <intent-filter>
                    <action android:name="android.provider.Telephony.SMS_DELIVER" />
                </intent-filter>
            </receiver>
    
            <!-- BroadcastReceiver that listens for incoming MMS messages -->
            <receiver
                android:name=".MmsReceiver"
                android:permission="android.permission.BROADCAST_WAP_PUSH">
                <intent-filter>
                    <action android:name="android.provider.Telephony.WAP_PUSH_DELIVER" />
                    <data android:mimeType="application/vnd.wap.mms-message" />
                </intent-filter>
            </receiver>
    
            <!-- Activity that allows the user to send new SMS/MMS messages -->
            <activity android:name=".ComposeSmsActivity">
                <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>
    
            <!-- Service that delivers messages from the phone "quick response" -->
            <service
                android:name=".HeadlessSmsSendService"
                android:exported="true"
                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>
        </application>
    </manifest>
    

    Since the system only inspects an app's manifest to determine if it can act as the default messaging app, you don't actually need any of those classes, though you might have to suppress some warnings/errors, or provide stub classes, to make your IDE happy.

    Obviously, if your app is to act as a user's default messaging client, it should fully implement all of the specified components. However, an incomplete implementation can certainly be useful; e.g., during learning and testing, or in apps that only need partial access temporarily, like message backup and restore apps.

    If you do intend to perform any SMS/MMS-related tasks, you will also need the relevant permissions. Though the system apparently doesn't check for these when determining eligible default app candidates, the following permissions are necessary for their corresponding operations:

    <uses-permission android:name="android.permission.SEND_SMS" />
    <uses-permission android:name="android.permission.RECEIVE_SMS" />
    <uses-permission android:name="android.permission.READ_SMS" />
    <uses-permission android:name="android.permission.WRITE_SMS" />
    <uses-permission android:name="android.permission.RECEIVE_MMS" />
    

    A SecurityException will be thrown if you're missing the relevant permission for a given operation when it happens, though some might be easy to miss; e.g., if the RECEIVE_SMS permission is missing when the system tries to deliver an incoming SMS to a manifest-registered Receiver. Be sure to inspect your logs if you observe unexpected behavior, even if there is no apparent crash.