截获系统广播,读取消息,若联系人存在于通信录中,则让消息继续传播;若属于陌生号码,则中断消息,同时把信息显示在自己的程序中。
拦截器代码如下:
public class SMSInterceptReceiver extends BroadcastReceiver {
final String ACTION_SMS_RECEIVED="android.provider.Telephony.SMS_RECEIVED";
//有新短信时系统发出的广播,有序,可拦截。
public SMSInterceptReceiver() {
}
@Override
public void onReceive(Context context, Intent intent) {
// TODO: This method is called when the BroadcastReceiver is receiving
// an Intent broadcast.
String contact;
//发送短信的号码
Boolean intercept=false;
//布尔变量,表示是否拦截
if(intent.getAction().equals(ACTION_SMS_RECEIVED)){
StringBuilder builder=new StringBuilder();
Bundle bundle=intent.getExtras();
if(bundle!=null){
Object[] pdus=(Object[])bundle.get("pdus");
//从Intent中获取bundle对象,此对象包含了所有的信息,短信是以“pdus”字段存储的。得到的是一个object数组,每个object都包含一条短信,(可能会获取到多条信息)。
SmsMessage[]messages=new SmsMessage[pdus.length];
//新建SmsMessage数组对象存储短信,每个SmsMessage对应一条短信类。
for(int i=0;i<messages.length;i++){
messages[i]=SmsMessage.createFromPdu((byte[])pdus[i]);
}
contact=messages[pdus.length-1].getDisplayOriginatingAddress();
//获取得到的最末端短信的联系人地址,赋值给contact
if(!context.getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,null,"data1=?",new String[]{contact},null).moveToFirst()){
intercept=true;
abortBroadcast();
//从系统通信录读取联系人,条件为data1=contact,“data1”是ContactsContract.CommonDataKinds.Phone.NUMBER对应的字符串;对得到的cursor对象如果莫veToFirst()为false,说明没有该联系人,因此intercept为真,然后中断广播传播。
}
builder.append("发送人:" + contact + "\n" + "内容:");
builder.append(messages[pdus.length-1].getDisplayMessageBody());
//读取短信内容,getDisplayMessageBody()是获取正文消息。
Intent intent1=new Intent(context,MultimediaActivity.class);
intent1.putExtra("SMS", builder.toString());
intent1.putExtra("intercept",intercept);
//新建intent,然后将短信内容和interceput传入对应的bundle中,当有活动或者服务相应时便可读取数据。 intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//因为这是静态注册的监听器,应用程序很可能就没有启动,Intent.FLAG_ACTIVITY_NEW_TASK表示活动开始在新的栈中。(具体可参考android四种活动模式)
PendingIntent pi=PendingIntent.getActivity(context,0,intent1,0);
Notification.Builder builder1=new Notification.Builder(context);
//在API14以后,setLatestEventInfo()函数被废弃,因此要想新建通知栏消息,就需要借助Notification的内部类Builder,该构造方法接收一个参数Context。 builder1.setSmallIcon(R.mipmap.ic_launcher).setContentTitle("您有一条新信息").
setContentText("点击查看");
//设置通知图标,设置通知标题,设置通知内容,这三个部分必须设置,否则通知栏不显示或者直接闪退。
builder1.setAutoCancel(true);
//设置点击后自动消失,否则需要代码取消通知栏消息。
builder1.setContentIntent(pi);
//设置点击通知栏后的“意图”。
builder1.setTicker("new message");
//设置消息来临时在最上方显示的内容,会闪一下,然后消失。
builder1.setVibrate(new long[]{0, 1000, 1000, 2000});
//设置震动,参数为long数组(还可以有第二个参数),第一个元素表示暂停时间,第二个元素表示震动时间,第三个位置表示暂停时间……,第二个参数是一个int型,为-1表示不重复,为0或者正数表示从相应位置元素开始重复震动。
NotificationManager manager=(NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification=builder1.build();
notification.flags=Notification.FLAG_AUTO_CANCEL;
manager.notify(2, notification);
//从上下文获取通知栏管理对象,然后注册这个消息。
Toast.makeText(context,"new Message",Toast.LENGTH_SHORT).show();
}
}else {
throw new UnsupportedOperationException("Not yet implemented");
}
}
}
静态注册监听器:
<uses-permission android:name="android.permission.READ_SMS" />
//申明权限,允许读取短信。
<uses-permission android:name="android.permission.RECEIVE_SMS" />
//允许接收短信。
<receiver
android:name="这里是拦截器实际包全名"
android:enabled="true"
android:exported="true" >
<intent-filter android:priority="1000" >
//设置级别为1000(安卓内置级别为100-1000),可以保证最新得到广播消息。
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
//指明具体拦截的广播
</intent-filter>
</receiver>