Android抢先截获短信(附源码)

之前在写通讯录应用时,将整体的代码写完后,自测时发现非常非常多的问题,其中一个非常重要严重的就是可以发出短信,但收不到任何的短信息,这搞的我好捉鸡啊!后来调试发现是由于没有收到短信的消息导致的,然后将自己手机中的QQ通讯录尝试着卸载掉,这时就可以收到了.

后来有时间了在网上查找相关资料,并且按照网上的理论编写了代码测试,解决了这个问题,在这里通过博客把解决的方法记录下来.

 

首先要知道广播分为无序,有序,sticky三种广播

无序广播应该最常用的,就是普通的广播,任何BroadcastReceiver都可以收到的广播,但是多个BroadcastReceiver在接受无序广播时也是有顺序前后之分的,也就是说每个BroadcastReceiver都会排队来接受无序广播,至于前后的顺序是怎么样的可以通过优先级等来设置.

有序广播也就是说最先收到有序广播的BroadcastReceiver在截获到这个广播后,可以选择继续下发此广播,或者中断此广播的发送,如果中断此有序广播的话,那么后面排队等待的BroadcastReceiver将接受不到此广播了,比如android系统在接受到短信息时所发送的广播"android.provider.Telephony.SMS_RECEIVED"就是有序广播

sticky广播由于暂时没有使用到,所以还不了解,等需要的时候再做研究

 

BroadcastReceiver广播接收器可以分为静态和动态的两种

静态接收器就是在AndroidManifest.xml注册的

动态接收器则是在代码中注册的

要了解很重要的一点:在相同优先级的情况下,动态接收器接受到广播的优先级会比静态接收器接受到广播的优先级高!

 

在了解上面的理论知识后,就开始实践下如何最先截获短信

首先在测试程序中静态注册广播接收器,并且将接受短信广播消息优先级设置为最高(一般第三方程序都会设置成最高)

AndroidManifest.xml

 

  1. <receiver    
  2.     android:name="huahua.interceptsms.MyReceiver">    
  3.     <intent-filter android:priority="2147483647">    
  4.         <action android:name="android.provider.Telephony.SMS_RECEIVED" />    
  5.         <action android:name="android.intent.action.BOOT_COMPLETED" />  
  6.     </intent-filter>    
  7. </receiver>    

 

 

MyReceiver.java

 

  1. package huahua.interceptsms;  
  2.   
  3. import android.app.Service;  
  4. import android.content.BroadcastReceiver;  
  5. import android.content.Context;  
  6. import android.content.Intent;  
  7. import android.os.Vibrator;  
  8. import android.util.Log;  
  9.   
  10. public class MyReceiver extends BroadcastReceiver{  
  11.   
  12.     @Override  
  13.     public void onReceive(Context context, Intent intent) {  
  14.         if(intent.getAction().equals("android.intent.action.BOOT_COMPLETED"))  
  15.         {  
  16.             Intent i =new Intent(context, MyService.class);  
  17.             context.startService(i);  
  18.         }  
  19.         if(intent.getAction().equals("android.provider.Telephony.SMS_RECEIVED")){    
  20.             Log.v("huahua", "MyReceiver收到短信发来的消息");    
  21.               
  22.         }    
  23.           
  24.     }  
  25.   
  26. }  

这样就可以了很简单.然后给10086发短信, 10086回复短信后发现QQ通讯录收到短信了,但是"MyReceiver收到短信发来的消息"Log消息却没有打印,说明没收到.

 

这时我们就要采用动态注册的方法了

MainActivity.java

 

  1. package huahua.interceptsms;  
  2.   
  3. import android.os.Bundle;  
  4. import android.app.Activity;  
  5. import android.content.BroadcastReceiver;  
  6. import android.content.Context;  
  7. import android.content.Intent;  
  8. import android.content.IntentFilter;  
  9. import android.util.Log;  
  10.   
  11. public class MainActivity extends Activity {  
  12.     private SmsReceiver smsReceiver;   
  13.     @Override  
  14.     protected void onCreate(Bundle savedInstanceState) {  
  15.         super.onCreate(savedInstanceState);  
  16.         setContentView(R.layout.activity_main);  
  17.           
  18.         //动态注册接受短信消息  
  19.         IntentFilter localIntentFilter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");  
  20.         //设置优先级  
  21.         localIntentFilter.setPriority(Integer.MAX_VALUE);  
  22.         smsReceiver = new SmsReceiver();  
  23.         registerReceiver(smsReceiver, localIntentFilter);  
  24.     }  
  25.       
  26.     private class SmsReceiver extends BroadcastReceiver{  
  27.   
  28.         @Override  
  29.         public void onReceive(Context context, Intent intent) {  
  30.             // TODO Auto-generated method stub  
  31.             if(intent.getAction().equals("android.provider.Telephony.SMS_RECEIVED")){    
  32.                 Log.v("huahua", "MainActivity收到短信发来的消息");    
  33.                   
  34.             }    
  35.         }  
  36.           
  37.     }  
  38.   
  39.     @Override  
  40.     protected void onDestroy() {  
  41.         // TODO Auto-generated method stub  
  42.         super.onDestroy();  
  43.         unregisterReceiver(smsReceiver);  
  44.     }  
  45.   
  46. }  

在主Activity中,将广播的优先级同样设置为最高,然后启动程序,继续刚才的操作.发现还是被QQ通讯录收到短信了,Log信息"MainActivity收到短信发来的消息"也没打印出来

 

 

这是因为在相同优先级,同样都是动态注册的BroadcastReceiver在接受有序广播时,哪个BroadcastReceiver先注册,则哪个BroadcastReceiver可以先截获有序广播!

 

 
下面来证明这个理论
如何让自己最先注册到动态BroadcastReceiver呢? 我们可以在刚开机时,去创建一个Service,然后在Service中动态注册BroadcastReceiver.由于"android.intent.action.BOOT_COMPLETED"开机消息是个无序广播,那么每个应用都能收到,至于收到这个消息的顺序可以通过设置优先级.这里我在AndroidManifest.xml将开机广播优先级设置为最高,已保证第一个去注册动态BroadcastReceiver.
 

MyService.Java

 

  1. package huahua.interceptsms;  
  2.   
  3. import android.app.Service;  
  4. import android.content.BroadcastReceiver;  
  5. import android.content.Context;  
  6. import android.content.Intent;  
  7. import android.content.IntentFilter;  
  8. import android.os.IBinder;  
  9. import android.os.Vibrator;  
  10. import android.util.Log;  
  11. import android.widget.Toast;  
  12.   
  13. public class MyService extends Service{  
  14.     private SmsReceiver smsReceiver;   
  15.     @Override  
  16.     public IBinder onBind(Intent arg0) {  
  17.         // TODO Auto-generated method stub  
  18.         return null;  
  19.     }  
  20.   
  21.     @Override  
  22.     public void onCreate() {  
  23.         // TODO Auto-generated method stub  
  24.         super.onCreate();  
  25.           
  26.         //动态注册接受短信消息  
  27.         IntentFilter localIntentFilter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");  
  28.         //设置优先级  
  29.         localIntentFilter.setPriority(Integer.MAX_VALUE);  
  30.         smsReceiver = new SmsReceiver();  
  31.         registerReceiver(smsReceiver, localIntentFilter);  
  32.           
  33.         //这里震动一秒钟,用来感受下刚开机是否马上收到开机消息,并启动Service  
  34.         Vibrator vib = (Vibrator)MyService.this.getSystemService(Service.VIBRATOR_SERVICE);  
  35.         vib.vibrate(1000);  
  36.           
  37.         Log.v("huahua", "MyService启动"+ System.currentTimeMillis());    
  38.         Toast.makeText(MyService.this, "MyService启动", Toast.LENGTH_SHORT).show();  
  39.     }  
  40.       
  41.     private class SmsReceiver extends BroadcastReceiver{  
  42.   
  43.         @Override  
  44.         public void onReceive(Context context, Intent intent) {  
  45.             // TODO Auto-generated method stub  
  46.             if(intent.getAction().equals("android.provider.Telephony.SMS_RECEIVED")){    
  47.                 Log.v("huahua", "MyService收到短信发来的消息");    
  48.                   
  49.                 Vibrator vib = (Vibrator)MyService.this.getSystemService(Service.VIBRATOR_SERVICE);  
  50.                 vib.vibrate(1000);  
  51.                   
  52.                 //不将此短信消息下发给其他程序,如QQ通讯录等应用将收不到信息了  
  53.                 abortBroadcast();  
  54.             }    
  55.         }  
  56.           
  57.     }  
  58.   
  59.     @Override  
  60.     public void onDestroy() {  
  61.         // TODO Auto-generated method stub  
  62.         super.onDestroy();  
  63.         unregisterReceiver(smsReceiver);  
  64.     }  
  65.   
  66. }  



好了,现在将测试程序安装到手机中再重启机器.会发现刚开机就会震动1秒钟并且有打印信息,表示已经动态注册了

BroadcastReceiver,然后接受短信.这时终于可以看到Log信息"MyService收到短信发来的消息"打印出来了,并且QQ通讯录收不到任何短信了

 

记得还要在AndroidManifest.xml加入相应的权限

 

  1. <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />  
  2. <uses-permission android:name="android.permission.RECEIVE_SMS"/>  
  3. <uses-permission android:name="android.permission.VIBRATE" />   



 

 

也许还有疑问:如果都把自己程序的"android.intent.action.BOOT_COMPLETED"开机消息设置为优先级最高,那谁会最先收到开机消息呢?

 

我这里做了个小实验,在自己的通讯录程序中和测试程序中都同样的设置最高优先级开机广播,然后打印信息发现

技术分享

技术分享

通讯录中的Serivce先启动,测试程序的Service后启动,那么很显然通讯录程序是先接受到开机广播的,那么也将会优先接收到有序广播

"android.provider.Telephony.SMS_RECEIVED"

 

关于哪个应用先收到这个开机消息,网上有大牛说跟apk的文件名有所关系.由于某些原因我没有测试

还有关于更多详细解释广播优先级问题,有兴趣的朋友可以自己看看这篇博客,讲解的很清楚

android安全问题(四) 抢先开机启动 - 结果篇

 

之前有听说别人投诉10086说自己智能机收不到短信了,很有可能一个原因就是自己手机下载了病毒或者不友善软件,其软件使用此方法来让其他程序都收不到短信消息

建议大家也自己写代码测试一下,这样更能加深体会

源码下载地址 :http://download.csdn.net/download/zhangxuebing2/6557371

来自:http://blog.csdn.net/huahuadashen/article/details/16337407

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。