单步调试+Android SDK源码定位Api28变更问题
背景
XX Android App使用WebView+JavaScript的方式构建应用。最近项目工程升级了打包SDK版本至Api28,出现一个奇怪的问题:使用应用管理杀掉App后,再次启动App,进入Web页面后,按后退键,本来应该返回上一个Web页面,但是直接却退出了。
初步分析,应该和Android SDK的Api28的变更有关系。参考Android开发者网站的Api28变更说明(https://developer.android.com/about/versions/pie/android-9.0-changes-28),但是没有找到确切的原因。
经过多次测试发现:
异常场景:安装App->启动App->杀掉App进程->启动App->进入Web页面->进入另一个Web页面->按后退键->App直接退出;
正常场景:安装App->启动App->进入Web页面->进入另一个Web页面->按后退键->App后退至上一个Web页面。
因此打算使用Android Studio进行单步调试
1. 正常情况下,Activity收到的按钮事件能够正常传递到WebView事件处理方法中,异常情况下,Activity收到的按钮事件无法传递到WebView的时间处理方法中;
2. 按钮事件从Activity到WebView需要经过SDK的处理逻辑,需要走读SDK源码,查看可能的原因;
3. SDK代码复杂,单步调试容易跟丢;
4. 单步调试定位到的行号和SDK源码的行号有差别,无法对上,加大单步调试的难度。
这时,想到有正常情况和异常情况作对比,是不是可以通过正常情况下方法调用栈信息,来指导异常情况的单步调试?
第一步:在正常情况下,单步调试至WebView的按钮事件处理方法,此时方法调用栈信息如下图所示,其中按钮事件从CordovaViewActivity->SystemWebView。
第二步:在异常情况下,从CordovaViewActivity类的dispatchKeyEvent方法,一步一步按照上面的方法调用栈的行号,到达对应行号后,进入方法。例如当单步调试到dispatchKeyEvent:557,AppCompatActivity时,按F8进入下一行558,这时dispatchKeyEvent:558,AppCompatActivity在上面的堆栈中有,此时按F7进入函数dispatchKeyEvent:xxx,CompatActivity中。
第三步:按照第二步的方法,直到发现与调用栈不一致的执行顺序。在这里,我们发现程序从DecorView:529走到ViewGroup类dispatchKeyEvent方法1903行时,直接跳至1910行,因此可以初步判断程序在这里未按预期执行。
第四步:通过查看ViewGroup类dispatchKeyEvent方法(代码行稍微有些偏移),结合内存变量mFocused的值为null,可知是mFocused的值为空导致异常。
到这里,我们就发现了这个mFocused值是问题的关键。经过上网查看资料,这个mFocused的值指向当前焦点的View。结合Android Api28的一个变更:不会再轻触模式下隐式分配初始焦点,基本可以确定就是焦点的问题了。
解决方法
在SystemWebView中增加请求焦点的代码requestFoucus(),问题解决。
- 点赞
- 收藏
- 关注作者
评论(0)