怎样绕开QQ通讯录和360的广播中断
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的广播中断的更多相关文章
- QQ通讯录VS360通讯录对新建信息界面中草稿的处理
在新建信息界面中,对草稿信息的处理. 1. QQ通讯录的处理是: 如果信息编辑框不为空,点击HOME键或者点击BACK键,保存草稿,同时结束新建信息界面. 如果收件人为空,也保存草稿,只是将收件人取名 ...
- qq通讯录
- Android项目--获取系统通讯录列表
----------------- 通讯录列表 ----------------- 按常理来说,获取系统通讯录列表,无非就是将通讯录的数据库打开获取数据,适配,添加即可. Cursor cursor; ...
- iOS开发系列--通讯录、蓝牙、内购、GameCenter、iCloud、Passbook系统服务开发汇总
--系统应用与系统服务 iOS开发过程中有时候难免会使用iOS内置的一些应用软件和服务,例如QQ通讯录.微信电话本会使用iOS的通讯录,一些第三方软件会在应用内发送短信等.今天将和大家一起学习如何使用 ...
- iOS开发系列通讯录、蓝牙、内购、GameCenter、iCloud、Passbook系统服务开
--系统应用与系统服务 iOS开发过程中有时候难免会使用iOS内置的一些应用软件和服务,例如QQ通讯录.微信电话本会使用iOS的通讯录,一些第三方软件会在应用内发送短信等.今天将和大家一起学习如何使用 ...
- iOS开发系列--通讯录、蓝牙、
iOS开发过程中有时候难免会使用iOS内置的一些应用软件和服务,例如QQ通讯录.微信电话本会使用iOS的通讯录,一些第三方软件会在应用内发送短信等.今天将和大家一起学习如何使用系统应用.使用系统服务: ...
- 转--2014年最新810多套android源码2.46GB免费一次性打包下载
转载自:http://www.eoeandroid.com/thread-497046-1-1.html 感谢该博客主人无私奉献~~ 下面的源码是从今年3月份开始不断整理源码区和其他网站上的安卓例子源 ...
- 2014年最新720多套Android源码2.0GB免费一次性打包下载
之前发过一个帖子,但是那个帖子有点问题我就重新发一个吧,下面的源码是我从今年3月份开始不断整理源码区和其他网站上的android源码,目前总共有720套左右,根据实现的功能被我分成了100多个类,总共 ...
- ym——android源代码大放送(实战开发必备)
转载请注明本文出自Cym的博客(http://blog.csdn.net/cym492224103),谢谢支持! 目录 PATH 列表 卷序列号为 000A-8F50 E:. │ javaapk.c ...
随机推荐
- java中的socket编程
Socket,又称为套接字,Socket是计算机网络通信的基本的技术之一.如今大多数基于网络的软件,如浏览器,即时通讯工具甚至是P2P下载都是基于Socket实现的.本文会介绍一下基于TCP/IP的S ...
- 无向连通图求割点(tarjan算法去掉改割点剩下的联通分量数目)
poj2117 Electricity Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 3603 Accepted: 12 ...
- 小技巧------教你释放C盘空间
1.删除休眠文件hiberfil.sys. 该文件在c盘根部目录为隐藏的系统文件,隐藏的这个hiberfil.sys文件大小正好和自己的物理内存是一致的,当你让电脑进入休眠状态时,windows7在关 ...
- 用angular中的ng-repeat和ng-show来实现tab选项卡
虽然我们可以用angular中的路由来做tab选项卡,但是那会让我们建立很多的页面来引入,或者建立 <script type="text/ng-template" id=&q ...
- Oracle数据库类型date
date日期类型 说明 oracle dd-mm-yyyy create table test1(birthday date); timestamp(n) 说明:邮戳的时间类型 于date的区别,邮戳 ...
- tcp/ip三次握手及四次挥手
三次握手Three-way Handshake 一个虚拟连接的建立是通过三次握手来实现的 1. (B) –> [SYN] –> (A) 假如服务器A和客户机B通讯. 当A要和B通信时,B首 ...
- 【Python学习 】Python实现的FTP上传和下载功能
一.背景 最近公司的一些自动化操作需要使用Python来实现FTP的上传和下载功能.因此参考网上的例子,撸了一段代码来实现了该功能,下面做个记录. 二.ftplib介绍 Python中默认安装的ftp ...
- 商铺项目(Logback配置与使用)
<?xml version="1.0" encoding="utf-8"?> <configuration debug="false ...
- mysql 数据类型 枚举类型与集合类型
字段的值只能在给定范围中选择,如单选框,多选框 enum 单选 只能在给定的范围内选一个值,如性别 sex 男male/女female set 多选 在给定的范围内可以选择一个或一个以上的值(爱好 ...
- Yarn之ResourceManager详细分析
一.概述 本文将介绍ResourceManager在Yarn中的功能作用,从更细的粒度分析RM内部组成的各个组件功能和他们相互的交互方式. 二.ResourceManager的交互协议与基本职 ...