Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
115 views
in Technique[技术] by (71.8m points)

android - 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>
Question&Answers:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...