前段时间研究短信拦截.涉及广播动态注册这一快.
一点心得,记录下来.
短信拦截原理: android系统在接收到短信后,会进行判读有没有应用监听着短信接收广播,有的话则先传给用户应用进行处理,应用处理完后再传给系统短信,如果谁都不监听的话,则把短信调用系统本身的短信APP.
广播注册一共有两种形式 : 一个是静态注册广播, 一个是动态注册广播.
两者及其接收广播的区别:
1.动态注册的广播永远要快于静态注册的广播,不管静态注册的优先级设置的多高,不管动态注册的优先级有多低>
2.动态注册广播不是常驻型广播,也就是说广播跟随activity的生命周期。注意: 在activity结束前,移除广播接收器。
静态注册是常驻型,也就是说当应用程序关闭后,如果有信息广播来,程序也会被系统调用自动运行。
3.在同一个优先级下,谁先启动的快,谁将先接收到广播.
//----------------------------------------------------------------------
这么, 在做短信拦截这一块,要想比来电通360拦截短信的快, 我们就要注册动态的广播,要注册动态的广播,我们的程序就要先跑起来.这就要开一个服务,还有开机就要启动
步骤:
1: 注册一个静态的开机自启动广播接收器,开机后接收广播
2.广播接收方法内 立马启动一个服务
3.服务内立马动态注册一个广播接收,用于拦截短信
大概的操作就是这样,下面上代码
------------------------------------------------------------------------
>>>>> 首先我们需要注册一个静态开机广播接收器
这又要考虑到 即使开机启动,我们也要跑的最快,所以需要监听很多的活动,下面有代码,有注释,我不废话了, 监听这些广播后, 将会在一开机最先启动,比360快, (在没有root权限下)
- <!-- 用于开机监听 广播接收器 -->
- <receiver android:name="src.com.BootReceiver">
- <intent-filter>
- <!-- 开机广播 -->
- <action android:name="android.intent.action.BOOT_COMPLETED" />
- <!-- WIFI开关改变 -->
- <action android:name="android.net.wifi.WIFI_STATE_CHANGED" />
- <!-- WIFI连接改变 -->
- <action android:name="android.net.wifi.STATE_CHANGE" />
- <!-- SIM卡状态改变 -->
- <action android:name="android.intent.action.SIM_STATE_CHANGED" />
- <!-- 网络状态改变 -->
- <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
- <!-- 本地连接改变 -->
- <action android:name="android.intent.action.ANY_DATA_STATE" />
- <!-- 蓝牙状态改变 -->
- <action android:name="android.bluetooth.adapter.action.STATE_CHANGED" />
- <!-- 电源连接状态 -->
- <action android:name="android.intent.action.ACTION_POWER_CONNECTED" />
- <!-- 电源断开状态 -->
- <action android:name="android.intent.action.ACTION_POWER_DISCONNECTED" />
- <!-- 用户解锁状态 -->
- <action android:name="android.intent.action.USER_PRESENT" />
- <!-- 新的拨号状态 -->
- <action android:name="android.intent.action.NEW_OUTGOING_CALL" />
- <!-- 手机状态改变 -->
- <action android:name="android.intent.action.PHONE_STATE" />
- <!-- 时间改变广播 -->
- <action android:name="android.intent.action.TIME_CHANGED" />
- <!-- 日期改变广播 -->
- <action android:name="android.intent.action.DATE_CHANGED" />
- <!-- 时区改变广播 -->
- <action android:name="android.intent.action.TIMEZONE_CHANGED" />
- <!-- 扩展卡插入拔出 -->
- <action android:name="android.intent.action.ACTION_MEDIA_EJECT" />
- <!-- 扩展卡未挂载 -->
- <action android:name="android.intent.action.MEDIA_UNMOUNTED" />
- <!-- 扩展卡被移除 -->
- <action android:name="android.intent.action.MEDIA_REMOVED" />
- <!-- 扩展卡检查状态 -->
- <action android:name="android.intent.action.MEDIA_CHECKING" />
- <!-- 用户想要移除扩展卡 -->
- <action android:name="android.intent.action.MEDIA_EJECT" />
- <!-- 新增APP程序包名 -->
- <action android:name="android.intent.action.ACTION_PACKAGE_ADDED" />
- <!-- 屏幕开启监听 -->
- <action android:name="android.intent.action.SCREEN_ON" />
- <!-- 屏幕关闭监听 -->
- <action android:name="android.intent.action.SCREEN_OFF" />
- <!-- 第一个启动的ACtivity -->
- <action android:name="android.intent.action.MAIN" />
- </intent-filter>
- </receiver>
>>>>> 只要一开机,我们就能第一时间接收到广播,在广播接收onReceive() 方法里面 里面启动一个服务 ,为了开启动态注册.
- /***
- * 开机启动广播接收
- *
- * @author Administrator
- *
- */
- public class BootReceiver extends BroadcastReceiver {
- /** 广播接收 */
- public void onReceive(Context context, Intent intent) {
- // 接收到系统开机信息时 启动服务
- Intent in = new Intent();
- in.setAction("src.com.MyService");
- context.startService(in);
- Toast.makeText(context, intent.getAction(), Toast.LENGTH_LONG).show();
- System.out.println("启动项目 : " + intent.getAction());
- }
- }
>>>>> 启动服务以后 ,在服务里面立马注册一个动态广播接收 监听收发短信
- /** 开始 */
- public void onStart(Intent intent, int startId) {
- super.onStart(intent, startId);
- // 判断服务一开启便注册一个SMS广播接收器
- Receiver mReceiver = null; // 广播接收类 对象
- IntentFilter iFilter = null; // 意图过滤对象
- mReceiver = new Receiver(); // 广播接收类初始化
- iFilter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED"); // 意图过滤初始化
- iFilter.setPriority(Integer.MAX_VALUE); // 设置优先级
- registerReceiver(mReceiver, iFilter); // 注册广播接
- }
>>>>>在短信拦截广播里面进行判断就好了,根据自己的需求进行拦截,或者是转发,上传服务器等等. 这里我判断的是拦截187的号码发来的短信,删除短信
- /***
- * 广播接收
- *
- * @author Administrator
- *
- */
- public class Receiver extends BroadcastReceiver {
- /** 接收 */
- public void onReceive(Context context, Intent intent) {
- // 返回OBJ对象
- Object[] pdus = (Object[]) intent.getExtras().get("pdus");
- // for循环判断
- for (Object p : pdus) {
- byte[] pdu = (byte[]) p;
- // 信息对象 初始化 = 信息对象.创建来来自(OBJ对象)
- SmsMessage message = SmsMessage.createFromPdu(pdu);
- // 返回信息来源号码
- String senderNumber = message.getOriginatingAddress();
- // 判断号码(XXXXXXX) 将终止系统广播,删除短信
- if (senderNumber.lastIndexOf("187") != -1) {
- abortBroadcast();// 终止广播
- }
- }
- Toast.makeText(context, "判断是否拦截", Toast.LENGTH_LONG).show();
- }
- }
结束: 最后有几点问题说一下 ,
有些改了内核的手机是拦截不了短信的,
比如小米,乐phone之类的,
都是系统应用APP接收到短信,处理完毕后 再传给第三方应用. 根本起不到拦截作用