问题回顾:
由于一次系统提交,导致应用调用QQ分享的时候直接闪退,这之间已经存在了好几个系统版本,而且相关改动非常多,回溯代码是一件很头疼的事(不过同事有这么做,持续了好几天时间,最终没有结果),刚好看到网上有人动态调试微信分析“两位数字+15个句号 ”异常,于是拿来学习总结一波
动态调试步骤:
1.将第三方apk通过apktool或者bsksamli进行反编译获取smali文件
2.在AS中新建工程,File –> New – > Import Project
选择smali文件保存目录, 点确定,一路Next到finish:
3.设置smali源码目录。首先把目录视图从‘Android’切换为‘project’:
这样就能看到你导入的smali源码目录,右键此目录:
4.打开调试器。首先用usb连上手机,然后在AS中,点击 Tools – > Android – > Android Device Monitor,这样就打开了DDMS
直接鼠标点击你要调试的进程,会出现一个如上图的端口号,这个是adb进行调试用来端口转发的socket号,记住这个数字,这里是8700。
4)连上调试器。点击Android Studio菜单,Run->Edit Configration:
点击+号,新建Remote类型的配置:
然后把要连接的端口号修改为上面的8700即可:
点击确定之后,Android Studio的工具栏右上角会出现Debug按钮,点击此按钮:
选择需要调试的进程:
下方的控制台就会输出:
这样,整个调试环境已经准备好了;接下来可以进行动态调试。
1.首先分析下需要下断点的位置,通过过滤 start u0关键字,我们可以看出,分享启动的页面
10-25 11:03:38.293 707-5574/system_process I/ActivityManager: START u0 {flg=0x40000 cmp=com.tencent.mobileqq/.activity.ForwardRecentActivity (has extras)} from uid 10142 on display 0,
那么finish的应该是ForwardRecentActivity,然后我们通过jdx查看一下QQ混淆后的代码。
protected boolean a(Bundle bundle) {
this.f171a = ForwardOptionBuilder.a(getIntent(), this.app, this);
this.f168a = (PhoneContactManagerImp) this.app.getManager(10);
if (this.f171a != null) {
this.f171a.a();
if (isFinishing()) {
return false;
}
Intent intent = getIntent();
this.f180d = intent.getBooleanExtra("forward_ability_entrence_show_in_share", false);
try {
this.a = intent.getIntExtra("forward_source_uin_type", 0);
this.f158a = intent.getData();
if (intent.getIntExtra("forward_type", -1) == 11) {
this.f175a = true;
}
this.f173a = intent.getStringExtra("pkg_name");
long longExtra = intent.getLongExtra("req_share_id", 0);
if (longExtra > 0) {
this.f177b = String.valueOf(longExtra);
}
if (QLog.isColorLevel()) {
QLog.d("ForwardOption.ForwardEntranceActivity", 2, "-->doOnCreate_init--isSdkShare = " + this.f175a + ", pkgName = " + this.f173a + ", appid =" + this.f177b);
}
this.f178b = intent.getBooleanExtra("FORWARD_RECENT_TOPAY_LIST", false);
b();
if (this.app.getCurrentAccountUin() == null) {
finish();
}
if (this.f178b) {
a();
} else {
k();
}
this.f171a.c();
c();
} catch (Throwable e) {
if (QLog.isColorLevel()) {
QLog.d("ForwardOption.ForwardEntranceActivity", 2, "exception in ForwardRecentActivity", e);
}
finish();
}
if (QLog.isDevelopLevel()) {
QLog.d("StructingMsgItemBuildertime", 4, "zhuanfa end:" + System.currentTimeMillis());
}
if (this.f178b) {
ReportController.b(this.app, "P_CliOper", "Vip_pay_mywallet", StatConstants.MTA_COOPERATION_TAG, "wallet", "friendpay.selectpage.show", 0, 0, StatConstants.MTA_COOPERATION_TAG, StatConstants.MTA_COOPERATION_TAG, StatConstants.MTA_COOPERATION_TAG, StatConstants.MTA_COOPERATION_TAG);
}
return true;
}
finish();
return false;
}
查看他在什么情况下会进行finish,最终我们定位的点在上面代码第39行处,但是QQ进行了try catch,并且将log开关关闭了,导致我们无法看出是出现了什么异常。
于是我们在调用isColorLevel的地方下断点,修改下他的返回值,使他打印出log具体过程如下
需注意,断点打在调用处,因为QLog.isColorLevel()调用的地方很多,打在里面会一直调,没法跑出来,运行到断点出再单步运行进去查看下状态。
isColorLevel代码如下可以看出此处修改UIN_REPORTLOG_LEVEL值,使他大于_DEFAULT_REPORTLOG_LEVEL就能打印出log
public static boolean isColorLevel() {
return UIN_REPORTLOG_LEVEL > _DEFAULT_REPORTLOG_LEVEL ? true : isDebug;
}
然后运行,这时log就打印出来了
10-25 11:18:38.796 21507-21507/com.tencent.mobileqq D/ForwardOption.ForwardEntranceActivity: exception in ForwardRecentActivity
android.content.res.Resources$NotFoundException: Drawable com.tencent.mobileqq:drawable/name with resource ID #0x7f020cd2
Caused by: java.lang.ClassCastException: com.tencent.theme.SkinnableBitmapDrawable cannot be cast to android.graphics.drawable.BitmapDrawable
at android.app.theme.BitmapUtils.makeMaskIcon(BitmapUtils.java:164)
at android.app.theme.BitmapUtils.createIconBitmap(BitmapUtils.java:109)
at android.content.res.ResourcesImpl.setIconMask(ResourcesImpl.java:1518)
at android.content.res.ResourcesImpl.loadDrawable(ResourcesImpl.java:690)
at android.content.res.ResourcesImpl.loadDrawable(ResourcesImpl.java:549)
at android.content.res.Resources.getDrawable(Resources.java:879)
at android.content.Context.getDrawable(Context.java:530)
at android.view.View.setBackgroundResource(View.java:18443)
at com.tencent.mobileqq.activity.ForwardRecentActivity.d(ProGuard:685)
at com.tencent.mobileqq.activity.ForwardRecentActivity.b(ProGuard:440)
at com.tencent.mobileqq.activity.ForwardRecentActivity.a(ProGuard:274)
at com.tencent.mobileqq.activity.ForwardRecentActivity.doOnCreate(ProGuard:229)
at mqq.app.AppActivity.onCreate(AppActivity.java:66)
at android.app.Activity.performCreate(Activity.java:6666)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2671)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2785)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1526)
at android.os.Handler.dispatchMessage(Handler.java:110)
at android.os.Looper.loop(Looper.java:203)
at android.app.ActivityThread.main(ActivityThread.java:6239)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1063)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:924)
通过这份log就能顺利定位到是哪里的改动导致了异常。