Android 源码系列之《二十二》从源码的角度深入理解Java的动态代理机制(上)

本文从Android源码出发,探讨在华为Android 9.0上注册BroadcastReceiver超过1000个导致的问题。通过分析源码,提出使用动态代理的方式,通过反射和InvocationHandler实现对注册广播的计数和限制,从而避免应用崩溃。文章介绍了动态代理的基本原理,并预告将在下篇中详细讲解Java动态代理机制。
摘要由CSDN通过智能技术生成

转载请注明出处: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
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值