截获系统广播,读取消息,若联系人存在于通信录中,则让消息继续传播;若属于陌生号码,则中断消息,同时把信息显示在自己的程序中。

拦截器代码如下:

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>