Android短信监听器
短信监听器就是当收到信息时获取信息的内容、时间、发件人等信息然后对这些信息进行处理,可以屏蔽用户看到该信息、转发或发送到Web进行处理。Exciting function。。
我们看一下它的实现原理。
其实短信接收是通过Android系统中的广播接收者来实现的,当系统收到短信时,会发出一个广播Intent,Intent的action名称为android.provider.Telephony.SMS_RECEIVED,该Intent存放了系统接受到的短信内容,我们可以使用名称"pdus"即可从Intent中获取到短信内容。
广播可以分为普通广播和有序广播。普通广播是完全异步的,可以在同一时刻(逻辑上)被所有接受者接收到,相对于有序广播消息传递的效率比较高,但缺点是:接受者不能将出黎结果传递给下一个接受者,并且无法终止广播Intent的传播;有序广播是按照接受者声明的优先级别,被接受者依次接受广播。优先级别在<intent-filter>的android:priority属性中声明,数值越大优先级别越高,取值范围为-1000到1000,优先级别也可以调用IntentFilter对象的setPriority()进行设置。有序广播的接受者可以终止Intent的传播,广播Intent的传播一旦终止,后面的接受者就无法接收到广播。另外,有序广播的接受者可以将数据传递给下一个广播。例如A得到广播后,可以往它的结果对象中存入数据,当广播传给B时,B可以从A的结果对象中得到A存入的数据。
Context.sendBroadcast()
发送的是普通广播,所有订阅者都有机会获得并进行处理。
Context.sendOrderedBroadcast()
发送的是有序广播,系统会根据接受者声明的优先级别按顺序逐个执行接受者,前面的接受者有权终止广播(BroadcastReceiver.abortBroadcast()),如果广播被前面的接受者终止,后面的接受者就再也无法获取到广播。对于有序广播,前面的接受者可以将数据通过setResultExtras(Bundle)方法存放进结果对象,然后传给下一个接受者,下一个接受者通过代码:Bundle bundle = getResultExtras(true)可以获取上一个接受者存入在结果对象中的数据。
系统收到短信,发出的广播属于有序广播。如果想阻止用户收到短信,可以通过设置优先级,让自定义的接受者先获取到广播,然后终止广播,这样用户就接受不到短信了。
下面我们通过实例来讲解如何实现这个功能:
首先在配置清单中加入以下权限:
1 <uses-permission android:name="android.permission.RECEIVE_SMS"/><!-- 接收短信权限 --> 2 <!-- 访问internet权限 --> 3 <uses-permission android:name="android.permission.INTERNET"/>
在application中加入我们处理接收信息的receive以及设置其优先级,和Activity不一样,我们加入的是receiver节点,表示广播接受者:
1 <receiver android:name=".SMSBroadcastReceiver"> 2 <intent-filter android:priority="1000"> <!-- 设置优先级为最高 --> 3 <action android:name="android.provider.Telephony.SMS_RECEIVED"/> 4 </intent-filter> 5 </receiver>
在上面我们建立的SMSBroadcastReceiver不是Activity的子类,而是继承自BroadcastReceiver。由于我们是监听器,因此建立项目的时候不要选中Create Activity,不需要创建Activity:
核心代码很简单,只需要在当接收到信息时的onReceiver函数体内获取内容并且对内容进行处理即可:
1 public class SMSBroadcastReceiver extends BroadcastReceiver { 2 3 /* (non-Javadoc) 4 * @see android.content.BroadcastReceiver#onReceive(android.content.Context, android.content.Intent) 5 * 当接收到到信息时执行此方法 6 */ 7 @Override 8 public void onReceive(Context context, Intent intent) { 9 //从Intent中接受信息 10 Object[] pdus = (Object[]) intent.getExtras().get("pdus"); 11 for(Object p : pdus){ 12 byte[] sms = (byte[]) p; 13 SmsMessage message = SmsMessage.createFromPdu(sms); 14 15 //获取短信内容 16 String content = message.getMessageBody(); 17 18 //获取发送时间 19 Date date =new Date(message.getTimestampMillis()); 20 21 //获取发件人号码 22 String number = message.getOriginatingAddress(); 23
//处理数据...
24 //终止广播 25 //abortBroadcast(); 26 } 27 } 28 29 }
上面我们只是获取到了数据,数据处理可以使用之前博客中进行短信转发或放到WebService中处理。
在最后一行代码abortBroadcast()用于终止广播,例如可以判断电话号码如果是黑名单或自己不希望的号码时终止事件传播,此时由于我们的优先级是最高的没停止传播以后就不会在上面的提示栏中的提示信息,手机也就接收不到信息了。