怎样绕开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 ...
随机推荐
- 【转载】网络安全---Strurts2漏洞介绍
Apache Struts2 作为世界上最流行的 Java Web 服务器框架之一,3 月 7 日带来了本年度第一个高危漏洞——CVE编号 CVE-2017-5638 .其原因是由于 Apache S ...
- python使用MySqlDB
下载安装MySQLdb <1>linux版本 http://sourceforge.net/projects/mysql-python/ 下载,在安装是要先安装setuptools,然后在 ...
- PL/SQL编程基础(一):PL/SQL语法简介(匿名PL/SQL块)
PL/SQL PL/SQL是Oracle在关系数据库结构化查询语言SQL基础上扩展得到的一种过程化查询语言. SQL与编程语言之间的不同在于,SQL没有变量,SQL没有流程控制(分支,循环).而PL/ ...
- html 中 div 盒子并排展示
在项目中,遇到一个前端问题,觉得小问题就别去找前端工程师解决了,还是自己动动手吧. 相信不管小问题,大问题 都应该先自己尝试解决,google .度娘查查资料,这绝对是增加理解和记忆的好机会. ##问 ...
- scrapy爬虫系列之六--模拟登录
功能点:如何发送携带cookie访问登录后的页面,如何发送post请求登录 爬取网站:bilibili.github 完整代码:https://files.cnblogs.com/files/book ...
- Python开发【数据结构】:排序练习
排序练习 问题一: 现在有一个列表,列表中的数范围都在0到100之间,列表长度大约为100万.设计算法在O(n)时间复杂度内将列表进行排序. import random data = [random. ...
- django的restfulapi
Django Rest framework 的流程大概是这样的 建立 Models 依靠 Serialiers 将数据库取出的数据 Parse 为 API 的数据(可用于返回给客户端,也可用于浏览器显 ...
- android读取通讯录和使用系统通讯录
第一步:注册权限 <uses-permission android:name="android.permission.WRITE_CONTACTS" /> <us ...
- 3.1 Templates -- Handlerbars Basics(Handlerbars基础知识)
一.简介 Ember.js使用Handlerbars模板库来强化应用程序的用户界面.它就像普通的HTML,但也给你嵌入表达式去改变现实的内容. Ember使用Handlerbars并且用许多新特性去扩 ...
- 028-B+树(一)
B+ 树 这部分主要学习:什么是B+树? 了解了 B 树后再来了解下它的变形版:B+ 树,它比 B 树的查询性能更高. 一棵 B+ 树需要满足以下条件: 节点的子树数和关键字数相同(B 树是关键字数比 ...