Android 代理拦截系统层代码

有时我们的项目会遇见如下所示的崩溃堆栈:

android.app.RemoteServiceException: Context.startForegroundService() did not then call Service.startForeground()
	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2101)
	at android.os.Handler.dispatchMessage(Handler.java:108)
	at android.os.Looper.loop(Looper.java:166)
	at android.app.ActivityThread.main(ActivityThread.java:7425)
	at java.lang.reflect.Method.invoke(Native Method)
	at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:245)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:921)

这种堆栈没有我们业务层代码的信息,所以我们一时间会不知所措,想try-catch捕获都捕获不了,因为都是系统层的崩溃。

那么这就引出一个问题,我们能不能捕获系统层的代码异常或普通逻辑呢?答案是可以的,我们可以用代理的方法来实现。

一.手动代理

1.溯源

这里我们以上述代码为例,尝试捕获系统层的主线程Handler抛出的异常。

首先我们根据崩溃堆栈来看系统层的实现。

public final class ActivityThread extends ClientTransactionHandler {
   

	final H mH = new H();
	
	class H extends Handler {
   
		//...
	}
}

一个app进程的入口就在ActivityThread中,这个类中有一个叫做H,继承自Handler的类,且在ActivityThread中,创建了一个该对象叫做mH,这个Handler对象,就是上面堆栈中的那个handleMessage()方法的调用者。

再来看Handler里是如何调用handleMessage()方法的。

public void dispatchMessage(Message msg) {
   
    if (msg.callback != null) {
   //Runnable
        handleCallback(msg);
    } else {
   
        if (mCallback != null) {
   //Handler的callback对象
            if (mCallback.handleMessage(msg)) {
   
                return;
            }
        }
        handleMessage(msg);//重写该方法
    }
}

当Looper将Message对象,传递到Handler的dispatchMessage()方法中时,首先会看Message的callback对象是否存在,存在的话直接回调,这个callback其实是Runnable对象,是我们经常使用的handler.post({})等方法传入的回调参数,在这里由于堆栈显示,走的是Handler的handleMessage()方法,所以显然这里的callback为null,走else分支。

在else分支里,还有一个处理优先级较高的mCallback,如果该mCallback处理结果为true则直接结束处理,否则交由Handler自身的dispatchMessage()方法处理。

public class Handler {
   
	final Callback mCallback;
	public Handler() {
   
        this(null, false);
    }
	public Handler(Callback callback, boolean async) {
   
        //...
        mCallback = callback;
    }
}

可见,Handler的callback,是构造函数构造时传入的,而ActivityThread中创建mH时,是直接走的默认构造函数,所以这个mCallback为null,所以上面说的else分支里,会直接调用Handler的dispatchMessage()方法,我们再来看dispatchMessage()方法。

class H extends Handler {
   
	public void
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值