浅谈短、彩信的拦截

关于Android平台上短、彩信的拦截,网上已经有不少介绍性的文章。那些文章大多是介绍具体的实现方法,其提供的方法并不一定能够成功拦截。今天我们就来详深入地介绍一下拦截短、彩信的内部原理,并分析一下拦截方法的优劣。

Android接收短、彩信的原理

正常的短信在到达手机后,根据不同的制式GSMCDMA被解析并封装成SmsMessage对象该对象会被SMSDispatcher进一步解析并分发。系统会将短信的formatpdu放到actionandroid.provider.Telephony.SMS_RECEIVEDIntent之后系统会将Intent以有序广播Orderd Broadcast的形式发出去。监听这两个广播的app收到广播后,通过对pdu的解析,就可以得到短信的具体内容。

彩信的情况与短信类似,只不过运营商首先会发一条WapPush短信。这类短信不包含彩信的具体内容,而是包含一条指向真实内容的URL地址。系统会将WapPush短信解析,提取“pduTypeheaderpduformat等信息放到actionandroid.provider.Telephony.WAP_PUSH_RECEIVEDIntent中。同样,系统会以有序广播的形式将Intent发出去。收到广播的appintent解析,并提取其中的URL。之后访问该URL地址并下载实际的彩信内容。

有序广播的原理

经过以上的分析,拦截短、彩信的关键就是拦截action为“android.provider.Telephony.SMS_RECEIVED”和“android.provider.Telephony.WAP_PUSH_RECEIVED”的广播。由于该广播是有序广播,所有Receiver 是按照顺序接受广播的。先收到广播的Receiver有权利终止该广播的传播。因此只要一个Receiver能够第一个收到广播并终止继续传播,那么就可以实现短、彩信的拦截。

这里简单介绍一下有序广播的传播方式。BroadcastReceiver 有静态和动态两种方式注册。

1. 静态注册:

静态注册是指在AndroidManifest.xml 中注册。方法如下: 

<receiver android:name=“.XXXMessageReceiver”>
    <intent-filter android:priority=“1000”>
          <action android:name=“android.provider.Telephony.SMS_RECEIVED” />
    </intent-filter>
</receiver>

2. 动态注册:

动态注册是通过调用Context类的register方法来注册。方法如下:

registerReceiver(BroadcastReceiver receiver,IntentFilter filter);
registerReceiver(BroadcastReceiver receiver, IntentFilter filter, 
                 String broadcastPermission, Handler scheduler);

 

注意,动态注册Receiver 的优先级是通过IntentFilter.setPriority(int)方法来设置的。当一个广播发生时,系统会将静态和动态的Receiver 按优先级(priority)进行排序,优先级越高越早处理。对于优先级相同的Receiver ,先处理动态的。

第三方解决方案

网上的通常解决方案是采用静态注册的方式注册BroadcastReceiver ,并设置一个较高的优先级,例如,10009999等。经过以上对于广播原理的分析,可以看出,这种方式其实并不能够保证接受者会第一时间被触发。比较好的实现方法需要注意两点:

1. 采用动态方式而非静态方式注册。监听系统开机广播,系统启动之后采用动态方式注册BroadcastReceiver 。这样可以保证在第一时间将需要的BroadcastReceiver注册成功;

2.  并将优先级设为最高。注意,系统的最高优先级不是网上所说的10009999,而是2147483647。这是int类型能够表示的最大数值。

做到这两点可以大大增加拦截的成功率。由于第三方app本身的局限性,即使采用优化过的方法,第三方app还是不能够保证拦截的成功率。例如,如果有两个app都采用动态注册的方式,都设置其优先级为最高。那么其中一个就会被另一个拦截。

系统级拦截方案

拦截短、彩信的根本方法还是需要在系统层面来解决。需要在系统提供一个专用的Service(类似于ActivityManagerServicePackageManagerService),用于判断收到的短信是否需要拦截。接口如下: 

boolean needToBlockMsg(Intent intent);

系统在收到短信后,将短信内容组装到需要广播的Intent中。然后调用该接口判断是否需要拦截。如果需要拦截,则抛弃该短信,或者将其保存到特定的数据库中;如果不需要拦截,那么就照常发送广播。这样可以一劳永逸地解决短、彩信的拦截问题。

由于需要修改“/system/framework/framework.jar”之类的系统文件,第三方app是无法实现的,因此需要设备生产厂商的支持。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值