While using Google Messenger, I noticed it has a “set as default SMS app” feature. Here’s how it works.

Starting from Android 4.4 KitKat, Google introduced the default SMS app mechanism. The official reasoning:

Some of you have built SMS apps using hidden APIs — a practice we discourage because hidden APIs may be changed or removed and new devices are not tested against them for compatibility. So, to provide you with a fully supported set of APIs for building SMS apps.

In short, if you build well and have enough users, Google takes notice and provides official support.

API Overview

Two new intents were introduced in Android 4.4:

  • SMS_DELIVER_ACTION — for SMS
  • WAP_PUSH_DELIVER_ACTION — for MMS

Making Your App the Default

1
2
3
Intent intent = new Intent(Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT);
intent.putExtra(Telephony.Sms.Intents.EXTRA_PACKAGE_NAME, getPackageName());
startActivity(intent);

Complete Implementation: Register and Unregister

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// Check if we are the default SMS app
currentPackageName = getPackageName();
String defaultSmsApp = Telephony.Sms.getDefaultSmsPackage(this);
if (currentPackageName != null && !currentPackageName.equals(defaultSmsApp)) {
    SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
    SharedPreferences.Editor editor = sharedPreferences.edit();
    editor.putString(DEDAULTSMS, defaultSmsApp);
    editor.apply();
}

// Register as default
register.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Intent intent = new Intent(Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT);
        intent.putExtra(Telephony.Sms.Intents.EXTRA_PACKAGE_NAME, getPackageName());
        startActivity(intent);
    }
});

// Restore the previous default
unregister.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        SharedPreferences sharedPreferences = PreferenceManager
                .getDefaultSharedPreferences(getApplicationContext());
        String defaultSmsApp = sharedPreferences.getString(DEDAULTSMS, null);
        if (defaultSmsApp != null) {
            Intent intent = new Intent(Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT);
            intent.putExtra(Telephony.Sms.Intents.EXTRA_PACKAGE_NAME, defaultSmsApp);
            startActivity(intent);
        } else {
            Toast.makeText(getApplicationContext(), "failed unregister", Toast.LENGTH_SHORT).show();
        }
    }
});

Key Logic

  1. On startup, save the current default SMS app’s package name to SharedPreferences
  2. When the user clicks “register”, set the current app as default
  3. When the user clicks “unregister”, restore the previously saved default app

Note for Android Q (10) and above: Google introduced the RoleManager API. Use RoleManager.createRequestRoleIntent(RoleManager.ROLE_SMS) instead of ACTION_CHANGE_DEFAULT for newer versions. The above implementation still works across most Android versions.

References