Android4.4如何实现短信拦截

 android4.4对短信引入了一个全新的概念:默认短信应用。即Android用户可以在系统设置里面选择一个默认的短信应用,只有这个应用才能进行手机的基本短信操作。按照google自己的解释这样做的原因是因为很多第三方的APP使用了一些隐藏的API接口,应该是反射调用把,既然是反射调用的非常规接口,因此这些接口就并不会有兼容性即CTS测试,也就不能保证稳定可靠。个人看来,目前市场上第三方短信应用太多了,而且厂商经常把通话,联系人,短信打包放在一起,因此手机上经常有多个短信应用,每个应用都能收短信发短信,有点混乱,尤其有的应用没有处理好,导致收到一条短信显示两条。囧。因此这个默认短信的操作也就是很有必要的。
不过既然接口变了,那么APP这边很多东西也要改变,最典型的类似360云盘这种能恢复短信的应用,应该怎么恢复短信呢?这个稍后会提到google给了一个建议。这里还是先说下接口有了哪些变化把。

        google提供了:SMS_DELIVER_ACTION(sms)&& WAP_PUSH_DELIVER_ACTION(MMS)这两个intent来给默认的短信应用,也就是说只有默认的短信应用才能收到这两个广播,也只有能收到这两个广播的应用才能对短彩信的数据库进行写操作。也就是说只有默认短信应用才能存储短信。其他的非默认短信应用如果想收短信,可以监听:
SMS_RECEIVED_ACTION 当然这些应用也只能显示下短信,并不能存入数据库。因此直接将4.4以前的短信应用拿过来装到4.4上,这些应用仅能在来短信的时候进行查看阅读,因为没有写数据库的权限。google提供了一个控件接口:PackageManager.setComponentEnabledSetting(),可以对控件进行使能操作。这样应用可以做到检测下当前的android的平台,然后判断是否需要关掉这个广播。

        另外在4.4之前, SMS_RECEIVED_ACTION broadcast是一个有序广播,因此一些应用可以在监听到这个广播之后,进行丢弃处理,但是到了4.4之后,丢弃动作是不会生效的,这样就可以保证所有的短信应用都能收到短信。个人认为这是非常合理的……毕竟短信嘛,不能某个应用说拦截就拦截了。

        非系统的短信应用,如果想进行发短信操作的话,可以在申请了SEND_SMS权限之后,调用SmsManager接口进行短信发送操作。只有非系统短信应用在发送短信之后,framework才会将这条短信写入数据库,(系统短信应用会自己写入数据库),笔者感觉这一点非常好,再也不会有应用悄悄的在后台发送短信了……

        因为一个应用如果不是默认的短信应用,其很多设计的东西都不可用的,和成为默认短信应用差别非常大,因此有必要进行一些容错操作。首先,界面resume的时候需要检查下是否是默认的,可以通过查询:Telephony.Sms.getDefaultSmsPackage()来判断自己是不是默认的短信应用。如果不是建议就disable短信发送操作,因为如果用户发送彩信的话,系统不会帮忙写入数据库,应用自己又不能写入数据库,情况就很糟糕了……当然如果不是默认短信应用的话,也可以提示用户选择是否设置下,毕竟愿意点击你的应用,基本都是想用的。

sample如下:

[html]  view plain  copy
 print ?
  1. public class ComposeSmsActivity extends Activity {  
  2.   
  3.     @Override  
  4.     protected void onResume() {  
  5.         super.onResume();  
  6.   
  7.         final String myPackageName = getPackageName();  
  8.         if (!Telephony.Sms.getDefaultSmsPackage(this).equals(myPackageName)) {  
  9.             // App is not default.  
  10.             // Show the "not currently set as the default SMS app" interface  
  11.             View viewGroup = findViewById(R.id.not_default_app);  
  12.             viewGroup.setVisibility(View.VISIBLE);  
  13.   
  14.             // Set up a button that allows the user to change the default SMS app  
  15.             Button button = (Button) findViewById(R.id.change_default_app);  
  16.             button.setOnClickListener(new View.OnClickListener() {  
  17.                 public void onClick(View v) {  
  18.                     Intent intent =  
  19.                             new Intent(Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT);  
  20.                     intent.putExtra(Telephony.Sms.Intents.EXTRA_PACKAGE_NAME,   
  21.                             myPackageName);  
  22.                     startActivity(intent);  
  23.                 }  
  24.             });  
  25.         } else {  
  26.             // App is the default.  
  27.             // Hide the "not currently set as the default SMS app" interface  
  28.             View viewGroup = findViewById(R.id.not_default_app);  
  29.             viewGroup.setVisibility(View.GONE);  
  30.         }  
  31.     }  
  32. }  

      怎么样才能让你的应用成为成为一个合格的默认短信应用呢?首先你需要在androidmanifest.xml文件中进行一些声明,获取对应的权限:
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权限。这样用户就能在来电的时候,用你的应用来发送拒绝短信。

sample如下:

[html]  view plain  copy
 print ?
  1. <manifest>  
  2.     ...  
  3.     <application>  
  4.           
  5.         <receiver android:name=".SmsReceiver"  
  6.                 android:permission="android.permission.BROADCAST_SMS">  
  7.             <intent-filter>  
  8.                 <action android:name="android.provider.Telephony.SMS_DELIVER" />  
  9.             intent-filter>  
  10.         receiver>  
  11.   
  12.           
  13.         <receiver android:name=".MmsReceiver"  
  14.             android:permission="android.permission.BROADCAST_WAP_PUSH">  
  15.             <intent-filter>  
  16.                 <action android:name="android.provider.Telephony.WAP_PUSH_DELIVER" />  
  17.                 <data android:mimeType="application/vnd.wap.mms-message" />  
  18.             intent-filter>  
  19.         receiver>  
  20.   
  21.           
  22.         <activity android:name=".ComposeSmsActivity" >  
  23.             <intent-filter>  
  24.                 <action android:name="android.intent.action.SEND" />                  
  25.                 <action android:name="android.intent.action.SENDTO" />  
  26.                 <category android:name="android.intent.category.DEFAULT" />  
  27.                 <category android:name="android.intent.category.BROWSABLE" />  
  28.                 <data android:scheme="sms" />  
  29.                 <data android:scheme="smsto" />  
  30.                 <data android:scheme="mms" />  
  31.                 <data android:scheme="mmsto" />  
  32.             intent-filter>  
  33.         activity>  
  34.   
  35.           
  36.         <service android:name=".HeadlessSmsSendService"  
  37.                  android:permission="android.permission.SEND_RESPOND_VIA_MESSAGE"  
  38.                  android:exported="true" >  
  39.             <intent-filter>  
  40.                 <action android:name="android.intent.action.RESPOND_VIA_MESSAGE" />  
  41.                 <category android:name="android.intent.category.DEFAULT" />  
  42.                 <data android:scheme="sms" />  
  43.                 <data android:scheme="smsto" />  
  44.                 <data android:scheme="mms" />  
  45.                 <data android:scheme="mmsto" />  
  46.             intent-filter>  
  47.         service>  
  48.     application>  
  49. manifest>  

     没有写权限,备份应用应该如何写入短信数据库呢?google提供了这样一个建议:
1.先查询下并且记录下当前的默认短信应用:

[java]  view plain  copy
 print ?
  1. String defaultSmsApp = Telephony.Sms.getDefaultSmsPackage(context);  

2.让用户设置你的应用成为默认短信应用,如何设置前面也有sample,成为默认短信应用之后,就可以恢复短信了:

[java]  view plain  copy
 print ?
  1. Intent intent = new Intent(context, Sms.Intents.ACTION_CHANGE_DEFAULT);  
  2. intent.putExtra(Sms.Intents.EXTRA_PACKAGE_NAME, context.getPackageName());  
  3. startActivity(intent);  

3.最后恢复完成短信之后,可以在将默认短信应用还原到步骤1中记录的短信应用:

[java]  view plain  copy
 print ?
  1. Intent intent = new Intent(context, Sms.Intents.ACTION_CHANGE_DEFAULT);  
  2. intent.putExtra(Sms.Intents.EXTRA_PACKAGE_NAME, defaultSmsApp);  
  3. startActivity(intent);  

     最后笔者总结下:4.4上短信真的严格了,从此再也没有应用能够悄悄的发短信了,也不会有应用能够自行拦截短信了。各种管家,安全软件的拦截骚扰短信的功能该怎么办呢?

    声明:本文章取自作者对google官方博客的学习,并非直接翻译过来。

    原文链接:http://blog.csdn.net/maybe_windleave/article/details/17740345

你可能感兴趣的:(问题记录-Android)