Android4.4短信接收拦截,黑白名单(framework修改)

Android4.4,关于短信部分的结构做了比较大的变化,之前的版本可以直接编写一个apk通过拦截有序广播的方法来拦截短信,但到了4.4后改成另外一个广播SMS_DELIVER_ACTION,而且只有默认短信应用能接受到该广播,原来的广播也能接受到但不能实现拦截。如果普通的应用想拦截短信就必须设置为默认短信应用。

但如果你想拦截一些短信,而且不想限制用户选择自己喜欢的短信应用。我们只能在framework层的广播发送前拦截住。如果你还想实现动态的黑白名单,那就涉及进程间的通信。拦截某段代码还要涉及到如何保存恢复数据。

进程间的通信有2种,aidl和broadcast。选用改动少的broadcast。如果用aidl的还要加server,非常麻烦。

数据我们要随bradcast发送出去,所以要序列化。这样子白名单就可以正常。


目前网络上关于新结构的分析很少,所有我们要自己分析找到地方,直接在源码里搜索SMS_DELIVER_ACTION找到frameworks/opt/telephony/src/java/com/android/internal/telephony/InboundSmsHandler.java,广播就是从这段代码开始发出。

boolean processMessagePart(InboundSmsTracker tracker) {
        //(省略前面一段代码)
        Intent intent;
        if (destPort == -1) {
            intent = new Intent(Intents.SMS_DELIVER_ACTION);

            // Direct the intent to only the default SMS app. If we can't find a default SMS app
            // then sent it to all broadcast receivers.
            ComponentName componentName = SmsApplication.getDefaultSmsApplication(mContext, true);
            if (componentName != null) {
                // Deliver SMS message only to this receiver
                intent.setComponent(componentName);
                log("Delivering SMS to: " + componentName.getPackageName() +
                        " " + componentName.getClassName());
            }
        } else {
            Uri uri = Uri.parse("sms://localhost:" + destPort);
            intent = new Intent(Intents.DATA_SMS_RECEIVED_ACTION, uri);
        }

        intent.putExtra("pdus", pdus);
        intent.putExtra("format", tracker.getFormat());
        dispatchIntent(intent, android.Manifest.permission.RECEIVE_SMS,
                AppOpsManager.OP_RECEIVE_SMS, resultReceiver);
}


分析调用这个方法的代码,以及从方法名和传入参数可以知道,InboundSmsTracker这个类是专门用于封装短信的所有相关信息包含短信内容,发送人号码。而且processMessagePart方法除了发送短信广播,还将原来过长的短信在发送时被分开,在这里将合并一起。

接下来就很简单了,注释以上代码,将InboundSmsTracker序列化(因为进程间通信的数据必须序列化),使用广播发送出去。

Intent smsIntent = new Intent("com.sms.SMS_RECEIVED_ACTION");
        SmsMessage mSmsMessage = SmsMessage.createFromPdu(tracker.getPdu());
        String sender=mSmsMessage.getOriginatingAddress();
        smsIntent.putExtra("sender", sender);
        smsIntent.putExtra("InboundSmsTracker", tracker);
        smsIntent.putExtra("pdus", pdus);
        if("CdmaInboundSmsHandler".equals(InboundSmsHandler.this.getName())){
            smsIntent.putExtra("action", "com.flyaudio.sms.SMS_CDMA_INTERCEPTER");
        }else if("GsmInboundSmsHandler".equals(InboundSmsHandler.this.getName())){
            smsIntent.putExtra("action", "com.flyaudio.sms.SMS_GSM_INTERCEPTER");
        }
        mContext.sendBroadcast(smsIntent);


为了使白名单能正常接收,另外创建一个广播继续执行发送广播的代码

        mBroadcast = new SmsIntercepterBroadcastReceiver();
        IntentFilter filter = new IntentFilter();
        if("CdmaInboundSmsHandler".equals(name)){
            filter.addAction("com.sms.SMS_CDMA_INTERCEPTER");
        }else if("GsmInboundSmsHandler".equals(name)){
            filter.addAction("com.sms.SMS_GSM_INTERCEPTER");
        }
        mContext.registerReceiver(mBroadcast, filter);

在构造器里注册广播就可以了,这里有个地方要稍微注意一下。

这个InboundSmsHandler.java本身是个抽象类,从它的子类GsmInboundSmsHandler,CdmaInboundSmsHandler

以及打logcat测试时发现,不同的网络GSM和CDMA会使用不同的类处理。将其区分开,在黑白名单的应用里面判断一下网络类型再发送到适当的处理类。


广播里就是执行发送广播的代码,这里不再重复给出了。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值