http://www.eoeandroid.com/thread-148381-1-1.html

最近在网上搜索怎样绕开QQ通讯录和360的广播中断,在它们之前拿到短信,结果很遗憾没有搜索到什么东西,反而搜索到一些炫耀的帖子,只说自己解决了,不给别个分享解决方案的。

我只好自己来弄一下这个东东。

本来以为腾讯是拦截ril层的消息,然后阻断广播的发送,但是这种方式要修改framework才可能实现。

反编译QQ通讯录代码,没有看到特殊的设置,反编译360,发现了其中的奥秘。

这要从广播特别是有序广播的分发机制说起,底层的代码还有待我们的研究。

我没怎么看底层代码,只有测试实践。

经过我多次测试发现:

广播分2种,无序广播和有序广播。可以理解为散列和队列广播。



首先无序广播,不能中断,分发机制有点类似散列发送。这种广播的的发送为:context.sendBroadcast

这种广播是不能中断的,请看API说明。

其次为有序广播,可以中断。

这种广播,以我的理解可能存在很大的BUG,短信这块广播的发送BUG现在被QQ和360利用,可能在以后的版本中会修订。

它是一个按一种优先级顺序发送,即按某种messagequere队列发送,其中队列中的任何广播接收者都可以终端该广播,导致它之后的成员不能接收到广播。

我们首先看这个队列是怎么形成的:(以下是假想+测试验证,有待代码验证)

假设我们广播优先级别都设成:2147483647(注:最大int形整数)



首先动态注册优先级别最高

其次静态注册



在动态注册中

最早动态注册优先级别最高



在静态注册中

最早安装的程序,静态注册优先级别最高(注:安装APK会解析af.xml,把其加入队列)

注意这里安装 是指adb install xxx.apk或者手机上安装应用。

然后才是adb push到其他目录的应用

可能的原因是手机查询应用的时候会先去特定目录解析应用,所以广播注册会出现这种差别。adb push 到system/app下会比安装的优先级高吗?这有待你的验证,我还没验证。



然后都是安装的应用中

首先安装的优先等级最高



OK 以上就是我分析的有序广播的优先级别问题。



反编译360源码会发现,他首先静态注册的广播接收器里面设置的优先数量级为2147483647,然后在广播中启动一个service,在service中注册了一个优先数量级为2147483647的同样的广播接收器。

就这么简单就实现了没有同种实现的应用的情况下拦截短信。



OK,我们现在以同样的方式来做一个实验:

首先写一个应用,注册一个开机完成广播接收者。

<receiver android:name=".MyBrocast" android:permission="android.permission.BROADCAST_SMS">

            <intent-filter android:priority="2147483647">

                <action android:name="android.provider.Telephony.SMS_RECEIVED" />

            </intent-filter>

            <intent-filter android:priority="2147483647">

                <action android:name="android.intent.action.BOOT_COMPLETED" />

            </intent-filter>

        </receiver>



然后在这个广播接收者接收到信息之后马上启动一个service

public void onReceive(Context context, Intent intent) {

                Log.v("MyBrocast.onReceive", "testtttttttttttt");

                if(intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)){

                        Intent service=new Intent(context, MyService.class);

                        context.startService(service);

                }

然后在service重新注册一个接收短信的广播接收者,优先级2147483647

IntentFilter localIntentFilter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");

            localIntentFilter.setPriority(2147483647);

            myService = new MyBrocast();

            MyBrocast localMessageReceiver = myService;

            Log.v("MyBrocast.onReceive", "onCreate");

            Intent localIntent = registerReceiver(localMessageReceiver, localIntentFilter);



这种重启手机就OK了,你也可以让360,QQ郁闷的。







当然这里分享这个信息主要是想和大家一起提高,360和QQ的android版还是做的相当好的,有许多我们借鉴的地方。

其实我们也可以认为这是telephone模块的一个BUG,据说以前的版本是无序广播,不知是否出于拦截短信的机制修改了,反正我觉得有被第3方应用滥用的可能。



测试源码很简单,这里就不贴了

这里测试代码有很多不完善,比如服务被杀或者没有启动什么的。我们可以考虑把服务进程挂载到重要进程上去。



<-----------------------------------------------更新分割线----------------------------------------------------->

前面理解可能有点偏差,下面是我研究了一下代码部分验证了我的推论,能力有限还没能完全验证。

这个方法说明,如果我们的优先级设置为最大int形整数是能够排在最前面的。



到这里我们发现,优先级设置最高的会排在前面,如果优先级相同则按默认的排序不动,那么现在默认的排序是怎么样的呢?



我们发现大部分广播发送者都是只传送一个action,所以我们关注:

if (resolvedType == null && scheme == null && intent.getAction() != null) {

            firstTypeCut = mActionToFilter.get(intent.getAction());

            if (debug) Slog.v(TAG, "Action list: " + firstTypeCut);

        }

mActionToFilter内部list的排序决定了同样优先级情况下的排序问题

首先我们跟踪比较容易跟踪的

1.动态注册

AMS中的registerReceiver方法中有对变量mReceiverResolver的操作

如下:

BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);

            rl.add(bf);

            if (!bf.debugCheck()) {

                Slog.w(TAG, "==> For Dynamic broadast");

            }

            mReceiverResolver.addFilter(bf);



这里验证了同样优先级的情况下先动态注册的排在后来动态注册的广播接收者的前面。------------------1OK



2.静态注册

我们首先跟踪到PackageManagerService中的queryIntentReceivers方法

ComponentName comp = intent.getComponent();一般为空,略过。

因为广播一般不会发送给某个指定的包,所以最终一般会调用

if (pkgName == null) {

                return (List<ResolveInfo>)mReceivers.queryIntent(intent,

                        resolvedType, flags);

            }



这里会调用到IntentResolver的public List<R> queryIntent(Intent intent, String resolvedType, boolean defaultOnly) 方法

这里同样是找mActionToFilter中的值,说明这个对象里面可以动态赋值给它(动态注册AMS中的registerReceiver方法中有对变量mReceiverResolver)

也可以静态赋值,那么我们现在关注的就是mf.xml中的赋值顺序。但是到这里跟踪不下去了,感觉是安装的时候packageManageservice做了某种特殊的设置,adb install和adb push也做了不同的操作,

我还没有研究PMS,希望高手能解释下



-------------2 not ok



继续回来看AMS的broadcastIntentLocked方法

if (!ordered && NR > 0) {

如果不是队列广播这里会先立即给动态注册的广播接收者发送消息 ------------------------------------3OK一部分

并且这里还说明了一个问题:就是非ordered的广播基本都是动态注册优先接收到信息,无论动态注册的优先级多低(有的情况也不是这样的,具体见源代码)

继续

if (receivers != null) {

这里只要有静态注册的一般不为空

int NT = receivers != null ? receivers.size() : 0;

            int it = 0;

            ResolveInfo curt = null;

            BroadcastFilter curr = null;

            while (it < NT && ir < NR) {

                if (curt == null) {

                    curt = (ResolveInfo)receivers.get(it);

                }

                if (curr == null) {

                    curr = registeredReceivers.get(ir);

                }

                if (curr.getPriority() >= curt.priority) {

                    // Insert this broadcast record into the final list.

                    receivers.add(it, curr);

                    ir++;

                    curr = null;

                    it++;

                    NT++;

                } else {

                    // Skip to the next ResolveInfo in the final list.

                    it++;

                    curt = null;

                }

            }

这一段仅仅是把动态注册的优先级一样的广播加在了静态注册的前面,这里完全验证了动态注册优先静态注册----------------------3OK



代码后面的就是发送广播了。



现在的代码验证情况就是静态注册先安装的先获得广播还没能验证。希望高手能现场解释下。邮箱minzhang4891@sina.com

怎样绕开QQ通讯录和360的广播中断的更多相关文章

  1. QQ通讯录VS360通讯录对新建信息界面中草稿的处理

    在新建信息界面中,对草稿信息的处理. 1. QQ通讯录的处理是: 如果信息编辑框不为空,点击HOME键或者点击BACK键,保存草稿,同时结束新建信息界面. 如果收件人为空,也保存草稿,只是将收件人取名 ...

  2. qq通讯录

  3. Android项目--获取系统通讯录列表

    ----------------- 通讯录列表 ----------------- 按常理来说,获取系统通讯录列表,无非就是将通讯录的数据库打开获取数据,适配,添加即可. Cursor cursor; ...

  4. iOS开发系列--通讯录、蓝牙、内购、GameCenter、iCloud、Passbook系统服务开发汇总

    --系统应用与系统服务 iOS开发过程中有时候难免会使用iOS内置的一些应用软件和服务,例如QQ通讯录.微信电话本会使用iOS的通讯录,一些第三方软件会在应用内发送短信等.今天将和大家一起学习如何使用 ...

  5. iOS开发系列通讯录、蓝牙、内购、GameCenter、iCloud、Passbook系统服务开

    --系统应用与系统服务 iOS开发过程中有时候难免会使用iOS内置的一些应用软件和服务,例如QQ通讯录.微信电话本会使用iOS的通讯录,一些第三方软件会在应用内发送短信等.今天将和大家一起学习如何使用 ...

  6. iOS开发系列--通讯录、蓝牙、

    iOS开发过程中有时候难免会使用iOS内置的一些应用软件和服务,例如QQ通讯录.微信电话本会使用iOS的通讯录,一些第三方软件会在应用内发送短信等.今天将和大家一起学习如何使用系统应用.使用系统服务: ...

  7. 转--2014年最新810多套android源码2.46GB免费一次性打包下载

    转载自:http://www.eoeandroid.com/thread-497046-1-1.html 感谢该博客主人无私奉献~~ 下面的源码是从今年3月份开始不断整理源码区和其他网站上的安卓例子源 ...

  8. 2014年最新720多套Android源码2.0GB免费一次性打包下载

    之前发过一个帖子,但是那个帖子有点问题我就重新发一个吧,下面的源码是我从今年3月份开始不断整理源码区和其他网站上的android源码,目前总共有720套左右,根据实现的功能被我分成了100多个类,总共 ...

  9. ym——android源代码大放送(实战开发必备)

    转载请注明本文出自Cym的博客(http://blog.csdn.net/cym492224103),谢谢支持! 目录 PATH 列表 卷序列号为 000A-8F50 E:. │  javaapk.c ...

随机推荐

  1. 日志记录---log4j详解

    Apache官方项目地址 通常的日志记录的缺点是会减慢程序的运行速度,如果用普通的System.out的话影响视觉效果,另外解耦度也不好,而log4j的设计则使得日志记录变得可靠快速和可拓展性好. l ...

  2. JS复制制定内容到剪贴板怎么做?

    可以使用input也可以使用textare文本域来做(而且这个input/textarea不能够被隐藏): <a href="javascript:;" onclick=&q ...

  3. pta 习题集 5-14 求n以内最大的k个素数以及它们的和

    本题要求计算并输出不超过n的最大的k个素数以及它们的和. 输入格式: 输入在一行中给出n(10≤≤n≤≤10000)和k(1≤≤k≤≤10)的值. 输出格式: 在一行中按下列格式输出: 素数1+素数2 ...

  4. 括号匹配问题(区间dp)

    简单的检查括号是否配对正确使用的是栈模拟,这个不必再说,现在将这个问题改变一下:如果给出一个括号序列,问需要把他补全成合法最少需要多少步? 这是一个区间dp问题,我们可以利用区间dp来解决,直接看代码 ...

  5. Jscript运行时错误:没有权限

    问题:我在页面A中放了一个iframe ,然后在iframe 的子页面中调用主页面中的JavaScript函数,结果报错Jscript运行时错误:没有权限 原因有2: 1. 是逻辑错误,比如先关闭了i ...

  6. linux软件源配置

     实操(虚拟机安装): 下载VMware,然后按照如下教程安装虚拟机: https://jingyan.baidu.com/article/c275f6ba07e269e33d756714.html ...

  7. Worst Performing Queries

    WITH TMP AS ( SELECT TOP 100 CAST(SUM(s.total_elapsed_time) / 1000000.0 AS DECIMAL(10, 2)) AS [Total ...

  8. SQL Server 2012 AlwaysON 同步延迟时间

    SELECT availability_mode_desc , role_desc , replica_server_name , last_redone_time , GETDATE() now , ...

  9. poi根据模板导出word文档

    POI结构与常用类 Apache POI是Apache软件基金会的开源项目,POI提供API给Java程序对Microsoft Office格式档案读和写的功能. .NET的开发人员则可以利用NPOI ...

  10. Django model中数据批量导入bulk_create()

    在Django中需要向数据库中插入多条数据(list).使用如下方法,每次save()的时候都会访问一次数据库.导致性能问题: for i in resultlist: p = Account(nam ...