Android 4.4以上第三方应用不能插入短信的解决办法

来源:互联网 发布:以纯网络授权 编辑:程序博客网 时间:2024/05/22 21:36

Android4.4及其以上版本限制了第三方短信App的插入数据库的功能,只有默认短信程序才可以进行插入操作,系统也提供了设置界面,用来设置默认短信应用。这样的话,我们的备份应用如果还盲目地getContentResolver().insert的话,就会发现代码成功执行,但是短信里啥都没有。所以解决办法是,要先把自己的应用设置成默认短信应用,然后再进行插入操作,然后记得把默认短信应用恢复回来。当然这里最主要的步骤就是设置成默认短信应用,因为这需要打开系统界面让用户点了才行。

这里记录一下我所做的过程,关于备份和恢复短信的具体代码这里就不赘述了。


下面分步说明:

  • 第一步,注册2个receiver,1个activity,1个service:
        <!-- BroadcastReceiver that listens for incoming SMS messages -->        <receiver            android:name=".sms.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=".sms.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=".sms.ComposeSmsActivity"            android:configChanges="orientation|keyboardHidden|screenSize"            android:screenOrientation="portrait" >            <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=".sms.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>

为啥要注册这些?这几个东西能干啥?
这些是收发短信用的,既然你都成为了这个手机的默认短信app了,那你肯定要负责手机的短信相关事务啊,不能光想拿钱不想干活是不是?上面的代码不用做修改,直接放到manifest里面即可,还有一些相关的权限也不用加,因为我们只是稍稍用那么一小会儿,并不打算真的充当一个默认短信应用。

  • 第二步,把上面声明的几个类都给写成java类:
    啥也不说,alt+enter,按提示都给整出来,一句多的都不用加,看下代码:
public class ComposeSmsActivity extends Activity {}public class HeadlessSmsSendService extends Service {    @Nullable    @Override    public IBinder onBind(Intent intent) {        return null;    }}public class MmsReceiver extends BroadcastReceiver {    @Override    public void onReceive(Context context, Intent intent) {    }}public class SmsReceiver extends BroadcastReceiver {    @Override    public void onReceive(Context context, Intent intent) {    }}

上面两步做完后,你才能调起系统的设置界面。

  • 第三步,在用户点击“恢复”按钮时给个警告说明:

这里写图片描述

  • 第四步,在点完确定后,打开系统设置界面:
    /**     * 系统默认的短信应用保存一下,方便后面还原     */    private String defaultSmsApp;
//点击"恢复"以后执行的代码//是否是4.4版本以上,如果不是直接执行恢复代码if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {    //获得自己app的包名    String myPackageName = getPackageName();    //获得系统默认短信应用的包名    defaultSmsApp = Telephony.Sms.getDefaultSmsPackage(XXXActivity.this);    //如果自己的app不是默认app的话,就打开设置的界面,否则就直接执行恢复代码    if (!defaultSmsApp.equals(myPackageName)) {        Intent intent = new Intent(Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT);        intent.putExtra(Telephony.Sms.Intents.EXTRA_PACKAGE_NAME,myPackageName);        //这里加ForResult是为了加一个检验是否设置成功的时机        startActivityForResult(intent,101);        //一旦走了这里,就不能执行恢复代码了        return;    }}//执行恢复代码recoverySms();

下面是onActivityResult中的代码

 @Override    protected void onActivityResult(int requestCode, int resultCode, Intent data) {        super.onActivityResult(requestCode, resultCode, data);        if(requestCode == 101){            //设置默认短信成功            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {                final String myPackageName = getPackageName();                if (Telephony.Sms.getDefaultSmsPackage(XXXActivity.this)                .equals(myPackageName)) {                    //继续执行恢复代码                    recoverySms();                }            }        }    }

这样,就能在用户同意之后继续执行恢复代码了

  • 第五步,在恢复结束后,不论成功与否,都应该将默认短信应用还原
    下面是恢复结束的代码:
//恢复结束,将默认短信还原if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {    String myPackageName = getPackageName();    if (Telephony.Sms.getDefaultSmsPackage(XXXActivity.this)                .equals(myPackageName)) {         Intent intent = new Intent(Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT);         //这里的defaultSmsApp是前面保存的         intent.putExtra(Telephony.Sms.Intents.EXTRA_PACKAGE_NAME, defaultSmsApp);         startActivity(intent);    }}

Over,问题解决了。