之前在写通讯录应用时,将整体的代码写完后,自测时发现非常非常多的问题,其中一个非常重要严重的就是可以发出短信,但收不到任何的短信息,这搞的我好捉鸡啊!后来调试发现是由于没有收到短信的消息导致的,然后将自己手机中的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. import android.app.Service;
  3. import android.content.BroadcastReceiver;
  4. import android.content.Context;
  5. import android.content.Intent;
  6. import android.os.Vibrator;
  7. import android.util.Log;
  8. public class MyReceiver extends BroadcastReceiver{
  9. @Override
  10. public void onReceive(Context context, Intent intent) {
  11. if(intent.getAction().equals("android.intent.action.BOOT_COMPLETED"))
  12. {
  13. Intent i =new Intent(context, MyService.class);
  14. context.startService(i);
  15. }
  16. if(intent.getAction().equals("android.provider.Telephony.SMS_RECEIVED")){
  17. Log.v("huahua", "MyReceiver收到短信发来的消息");
  18. }
  19. }
  20. }

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

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

MainActivity.java

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

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

好了,现在将测试程序安装到手机中再重启机器.会发现刚开机就会震动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

最新文章

  1. 理解HTTP和HTTPS的区别
  2. 查看旧版jexus命令
  3. github的注册过程
  4. log4j日志的打印
  5. Sublime Text 快捷键
  6. Linux守护进程详解(init.d和xinetd) [转]
  7. jquery.validate.js
  8. Google面试题及答案
  9. [置顶] 浏览器模式和标准对于javascript的影响
  10. yum 命令
  11. 【rabbitmq】安装卸载
  12. OSC Source Code Innovation Salon(2018.10.20)
  13. MySQL中的insert ignore into, replace into用法总结
  14. java 中使用ajax调用后台方法注意事项
  15. linux 文件 md5校验
  16. iOS 图片加载速度极限优化—FastImageCache解析
  17. nmon 命令(转)
  18. Elasticsearch-PHP 索引操作
  19. 牛客网提高组模拟赛第五场 T1同余方程(异或)(位运算)
  20. iOS开发改变字符串中指定字符颜色,大小等等

热门文章

  1. PHP解惑(一)
  2. sizeof and strlen 的区别
  3. oracle的备份方式
  4. 【BZOJ2818】Gcd(莫比乌斯反演,欧拉函数)
  5. codevs2597 团伙
  6. [bzoj3513][MUTC2013]idiots_FFT
  7. codevs——6221 数的统计
  8. 权限框架之Shiro详解(非原创)
  9. 原想着mysql里放些文件什么的,查完资料还是算了
  10. centos7更新、更新、每天更新、每天自动更新