经验谈@IT·互联网Android知识

Android4.4以后第三方应用无法删除短信的解决方案

2017-05-31  本文已影响338人  wenzhiming

一、概述

最近测试提交了一个bug:用我们的应用删除Android5.0手机上的短信失败。

二、原因分析

在google查阅后得知:Android为了防止第三方软件拦截短信和偷发短信吸费,在android4.4之后,只有默认的短信应用才有权限操作短信数据库。

Android4.4短信机制的改变:
Getting Your SMS Apps Ready for KitKat

4.4 之前:

4.4 及之后:

简单来说,第三方非默认短信应用:

  1. 可以收短信、发短信并接收短信回执,但是不能删除短信
  2. 可以查询短信数据库,但是不能新增、删除、修改短信数据库
  3. 无法拦截短信

但是!极少数国产手机厂商会修改这个机制,实际测试中发现小米就修改了这个机制!小米4,android6.0系统,miui稳定版8.2,运行非默认应用,居然还是可以删除短信。但是别的小米手机又是不行的。非常奇怪。

三、如何解决

提示用户设置自己的app为default SMS app

为了使我们的应用出现在系统设置的Default SMS app中,我们需要在Manifest中做一些声明,获取对应的权限:

  1. 声明一个 broadcast receiver控件,对SMS_DELIVER_ACTION广播进行监听,当然这个receiver也要声明BROADCAST_SMS权限。
  2. 声明一个 broadcast receiver控件,对WAP_PUSH_DELIVER_ACTION广播进行监听,当然这个receiver也要声明BROADCAST_WAP_PUSH权限。
  3. 在短信发送界面,需要监听 ACTION_SENDTO,同时配置上sms:, smsto:, mms:, and mmsto这四个概要,这样别的应用如果想发送短信,你的这个activity就能知道。
  4. 需要有一个service,能够监听ACTION_RESPONSE_VIA_MESSAGE,同时也要配置上sms:, smsto:, mms:, and mmsto这四个概要,并且要声明SEND_RESPOND_VIA_MESSAGE权限。这样用户就能在来电的时候,用你的应用来发送拒绝短信。
<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=“.MainActivity" >  
            <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:permission="android.permission.SEND_RESPOND_VIA_MESSAGE"  
                 android:exported="true" >  
            <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>  

通过 Telephony.Sms.getDefaultSmsPackage()方法来判断自己的应用是否为Default SMS app。如果不是,可以通过startActivity() 方法启动类似如下的Dialog。

public class  MainActivity extends Activity {

    @Override
    protected void onResume() {
        super.onResume();
        final String myPackageName = getPackageName();
        if (!Telephony.Sms.getDefaultSmsPackage(this).equals(myPackageName)) {
            // App is not default.
            // Show the "not currently set as the default SMS app" interface
            View viewGroup = findViewById(R.id.ll_not_default_app);
            viewGroup.setVisibility(View.VISIBLE);

            // Set up a button that allows the user to change the default SMS app
            View button = findViewById(R.id.btn_change_default_app);
            button.setOnClickListener(new View.OnClickListener() {
                public void onClick(View v) {
                    Intent intent = new Intent(Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT);
                    intent.putExtra(Telephony.Sms.Intents.EXTRA_PACKAGE_NAME, myPackageName);
                    startActivity(intent);
                }
            });
        } else {
            // App is the default.
            // Hide the "not currently set as the default SMS app" interface
            View viewGroup = findViewById(R.id.ll_not_default_app);
            viewGroup.setVisibility(View.GONE);
        }
    }
短信列表-检测到非默认应用.png 长按删除短信.png 更换默认短信应用.png 设置-选择默认应用.png

四、源码下载:

https://github.com/wenzhiming/520sms

五、参考资料

上一篇下一篇

猜你喜欢

热点阅读