转载请注明出处:https://blog.csdn.net/llew2011/article/details/85923036
在上篇文章:Android 源码系列之<二十>通过反射解决在HuaWei手机出现Register too many Broadcast Receivers的crash 的文章中,我们分析了在HuaWei手机Android 8.1及以下版本中动态注册BroadcastReceiver的数量超过500个会引发应用crash的原因,然后又通过反射技术解决了该问题(不清楚原因的小伙伴可以看下上篇文章)。后来有小伙伴反馈说在HuaWei手机Android 9.0版本上使用反射技术也会抛出新的异常:Too many receivers, total of 1000......
收到小伙伴的反馈信息后,我在云测上对HuaWei Android 9.0的手机远程真机调试,结果也是出现了Too many receivers,total of 1000的异常,结合上篇文章的解决方案来看猜测是HuaWei在Android 9.0上对注册BroadcasterReceiver的数量做了更为严格的限制:即使应用添加进了白名单也不允许其注册超过1000个广播接收器。为了验证这个猜测我把上篇文章中用到的Demo的包名改成了微信的包名在HuaWei手机9.0上跑了一下,果然抛出最多只能注册1000个BroadcastReceiver的异常......
既然在HuaWei手机Android 9.0版本上不能注册超过1000个BroadcastReceiver,那么在HuaWei手机系统中可能有个类A,它的职责之一就是校验当前应用注册BroadcastReceiver的数量是否超过阀值a,如果超过阀值a则类A就抛出一个异常。我顺着这个思路并根据异常日志开始尝试寻找这个类A,如果找到了类A并且类A里恰好定义了阀值a那么我们就可以通过反射修改这个类A里阀值a的值,然而我尝试了多次都没有找到~~~~(>_<)~~~~
由于目前没办法找到类A,我们只能换一种思路来解决这个问题。既然在9.0版本上不能注册超过1000个BroadcastReceiver,那么我们可以拦截注册广播接收器的函数registerReceiver()和反注册广播接收器的函数unregisterReceiver()来做一个计数器,如果注册一个BroadcastReceiver就把计数器累加1,反注册一个BroadcastReceiver我们就把计数器减去1;要是计数器超过了1000就不再执行注册BroadcastReceiver的操作并给调用者一个回调来通知调用者注册的广播接收器已经达到上限了……
要拦截registerReceiver()和unregisterReceiver()方法最简单的方式是定义基类,在基类中做计数器功能,然后把这些基类开放给开发者继承,考虑到开发者的应用可能有的是继承第三方的基类等各种情况,定义基类这种做法是不妥当的,为了能找到一种更好的解决方案,我们先从源码分析一下注册BroadcastReceiver的流程,看看从方法调用链上能不能找到Hook点,测试代码如下:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(com.llew.huawei.verifier.demo.R.layout.activity_main);
}
public void register(View view) {
for (int i = 1; i <= 2000; i++) {
IntentFilter filter = new IntentFilter();
filter.addAction("hook index : " + i);
registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
}
}, filter);
Log.e(getClass().getName(), "index:" + i);
}
}
}
在MainActivity中我们直接调用了registerReceiver()方法,该方法是Context中定义的并在Context的子类ContextWrapper中做了实现,知道Activity继承关系的小伙伴都清楚Activity也是间接继承了ContextWrapper,所以我们直接去ContextWrapper类里看看registerReceiver()方法的具体实现,源码如下:
@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
return mBase.registerReceiver(receiver, filter);
}
ContextWrapper类中的registerReceiver()方法中直接调用mBase的registerReceiver()方法,mBase是ContextWrapper的大管家,它也是Context类型,它负责ContextWrapper的所有方法的实现。因此我们可以认为Activity的registerReceiver()方法最终委托给了大管家mBase,把任务都交给mBase去完成,自己只接收mBase的执行结果就行了(这种模式熟悉不?(*^__^*) ……),mBase的具体实现类是ContextImpl其registerReceiver()方法源码如下:
@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
return registerReceiver(receiver, filter, null, null);
}
@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
int flags) {
return registerReceiver(receiver, filter, null, null, flags);
}
@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
String broadcastPermission, Handler scheduler) {
return registerReceiverInternal(receiver, getUserId(),
filter, broadcastPermission, scheduler, getOuterContext(), 0);
}
@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
String broadcastPermission, Handler scheduler, int flags) {
retur