原文:http://www.bangchui.org/simple/?t32709.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
代码后面的就是发送广播了。
相关推荐
在Android应用开发中,Intent是连接应用程序组件之间通信的关键机制。Intent-filter的配置对于正确地启动和接收...在Android系统中,Intent-filter是组件间通信的关键组成部分,它决定了哪些组件能响应用户的特定操作。
总的来说,要在QQ通讯录之前拦截短信,你需要创建一个高优先级的BroadcastReceiver,监听SMS_RECEIVED行动,并在接收到短信后进行处理。但要注意Android版本和权限的影响,确保你的应用能够在适当的情况下正常工作。
在Android系统中,拦截短信是一项常见的功能,尤其对于开发者来说,可能需要在特定的应用程序(如QQ通讯录)之前获取并处理短信。本教程将详细解释如何实现这一目标,包括理解Android的消息处理机制、注册短信广播...
当我们说到 "Activity_intent-filter" 时,我们实际上是在讨论如何通过设置 `intent-filter` 来使一个 `Activity` 对特定的 `Intent` 响应。 `Intent` 是Android中的一个消息传递对象,用于在组件之间传递请求或...
- 匹配过程中,还会考虑优先级(Intent-filter的 `<priority>` 属性)和权限(Intent的权限声明)。 2. PackageParser.matchIntent(): - 这个方法会比较Intent的Action、Data和Category与ActivityInfo的Intent-...
在<intent-filter>中添加<category android:name="android.intent.category.CATEGORY_NAME"/>即可。 3. **Data**: Data部分用于指定Intent操作的数据类型,包括数据URI(Uniform Resource Identifier)和MIME类型...
IntentIntent-Filter思维导图
本资源是一个针对Android平台的完整通讯录应用的源码,非常适合计算机科学与技术专业的学生进行毕业设计学习。这个项目不仅提供了实现一个功能完备的通讯录应用的实际代码,还能帮助学习者深入理解Android应用开发的...
</intent-filter> <intent-filter> <action android:name="android.intent.action.SEND" /> <category android:name="android.intent.category.DEFAULT" /> <data android:mimeType="image/*" /> </intent-...
android intent和intent action大全
在<intent-filter>标签中,至少应该包含一个&action子标签,否则任何Intent请求都不能和该<intent-filter>匹配。如果Intent请求的Action和<intent-filter>中的任意一个&action子标签匹配,那么该Intent就可以激活该...
在本项目中,我们关注的是一个基于Android平台的通讯录应用的源码开发。这个应用是为毕业设计学习而创建的,因此它提供了一个实践性的平台,帮助学生深入理解Android应用开发的基本概念和技术。让我们详细探讨一下这...
最后,需要注意的是,由于安全和隐私考虑,Android系统对拦截短信的行为进行了限制。默认情况下,只有系统的默认短信应用能够阻止短信的传递。如果用户将你的应用设为默认短信应用,那么你的拦截功能才能生效。因此...
Android Intent 是 Android 组件之间的信使,负责在 Android 三大核心组件(Activity、Service、Broadcast Receiver)之间传递信息。Intent 是一个将要执行的动作的抽象描述,通常作为参数来使用,由 Intent 来协助...
在Android开发领域,Android Studio是首选的集成开发环境(IDE),它为开发者提供了高效、便捷的工具来构建高质量的应用程序。本项目以“Android studio 安卓通讯录开发”为主题,旨在帮助初学者掌握Android应用的...
在本次课设中,我们将会探讨如何使用Android Studio开发一个基于SQLite数据库的简易通讯录应用。这个应用包含两个主要界面:启动页和主页面。在主页面上,用户可以进行联系人的增删改查操作,同时还能读取系统的联系...
《绿豆通讯录》是Android移动开发领域的一个经典实践项目,主要针对初学者设计,旨在帮助他们更好地理解和掌握Android Studio的使用以及Android应用的基本构建过程。这个项目覆盖了多个关键知识点,下面将对这些核心...
参考...,讲解的很好 1.什么是Intent(定义) Intent这个单词的意思就是”意图,目的,意向”,Intent是一种运行时绑定(runtime binding)机制,它能在程序运行的过程中连接两个不同的组件。 个