How do I set my app as the default SMS app?
Asked Answered
H

1

25

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>
Holmium answered 8/5, 2015 at 15:31 Comment(0)
R
49

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.

Redundancy answered 8/5, 2015 at 22:18 Comment(16)
M: is 'HeadlessSmsSendService' is a Android Service class ?Anabel
@VineeshTP Yes. Any component with a <service> element would be a Service subclass.Redundancy
@MikeM. if I dont' do anything else would incoming messages never appear in my normal sms app's inbox? like they would just disappear? Because I want to see the SMSes normally in default app but use my app because I want to implement an SMS gateway.Scammony
@BlackDivine I'm not sure if I understand what you're asking. If your app is the default messaging app, it's responsible for saving incoming SMS. If it doesn't, then yeah, they pretty much disappear.Redundancy
How can I receive selected number from Contacts application when I click to send a message and my SMS applications is default?Monkfish
@alexsamsung Do you mean like this? https://mcmap.net/q/412605/-from-a-contact-view-how-to-send-a-contact-number-to-my-sms-app-to-send-an-sms-to-itRedundancy
@MikeM. why put the chooser dailog in onResume?i wan't need my sending and reciveing sms being saved in the default inbox how to achieve this??Pentaprism
@MikeM. Hi thank you for you post. I have question -> google play block my app because I added "android.permission.READ_CALL_LOG" permission but my app is not SMS default -> so if i put this the google play detect my app as SMS default?Twum
@SergBurlaka I have no idea. Sorry. I've never published any such apps on Google Play, and am unfamiliar with their guidelines and policies for that.Redundancy
Hey Mike it looks like the receiver you defined for listening for new messages should use the smsActionReceived Intent.Dendriform
@Dendriform The SMS_DELIVER broadcast is specific to the default SMS app: developer.android.com/reference/android/provider/….Redundancy
Ahhhh! after six hours of hard effort, I have found your answer! excellent.Tymbal
One additional question, The priority to set as default app, that the app never dies in background even when the app closed , With your approach, can i achieve that ?Tymbal
@NoorHossain I'm not quite sure if I understand what you mean. In standard Android, the default app will be launched if it's not already running when a message arrives, but it isn't constantly running in the background. Also, it is started with an explicit Intent, so even if it's force-stopped, it should still launch when needed. I can only comment on standard Android, though, as I've never had any experience with anything like Xiaomi, Huawei, etc. A lot of those models have extra security and/or permissions stuff that seem to be problematic for developers.Redundancy
@MikeM. thanks for reply, My default SMS app (which I am created with your answer shown), does not launch after some time, when message arrives. But the mobile default SMS app, which comes built-in with the mobile, does. I have used service and broadcast receiver correspondent, but nothing works. Is there any work around that keep service running, or broadcast, that get the message even when app is killed? very necessary for me.Tymbal
@NoorHossain I'm still not sure what your goal is. To clarify, this answer only works if you set your app as the one and only default SMS app for the device. There is only one default SMS app active at any given time. If your app is not set as the default by the user, then it behaves like any other app. If you have been setting it as the default, and it still stops working after some time, then my first guess is that it might be crashing during message receipt. The system will put it into the stopped state after a couple of background crashes, and start using the built-in one again.Redundancy

© 2022 - 2024 — McMap. All rights reserved.