20210306 问题小记

最近对某些第三方Android库做简单的逆向分析。遇到两个问题,记录之。

Variables debug info not available

Android Studio 中断点调试某些第三方 Android 库提示 Variables debug info not available,无法查看局部变量信息。

找到以下资料 来源

Java classes which are part of the JDK are compiled without debug info for the size and performance reasons.

简单来说是提到出于大小和性能因素考虑,JDK 中的类是不带 debug 信息的。

类似地,很多第三方 Android 库使用 proguard 等工具混淆和优化后也去掉了 debug 信息,所以调试时无法查看局部变量信息(不过可以查看成员变量信息)。

无法创建 ScanResult 实例

通常来说,我们会使用 Android 系统 API 获取 android.net.wifi.ScanResult 的实例。示例:

1
List<ScanResult> list = wifiManager.getScanResults();

有时出于某些原因,需要创建 android.net.wifi.ScanResult 实例。一开始,我以为这很简单。

思路一,直接调用构造方法创建实例不就可以了吗?

1
2
3
ScanResult sr = new ScanResult();

ScanResult sr2 = new ScanResult(sr);

但实际上在 Android SDK 30 (Android 11) 之前,没有这两个构造方法。

在低版本 Android 设备上直接调用 ScanResult 构造方法会报 java.lang.NoSuchMethodError 错误:

1
2
3
4
2021-03-06 11:15:48.458 22161-22161/? E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.amaploc.demo, PID: 22161
java.lang.NoSuchMethodError: No direct method <init>()V in class Landroid/net/wifi/ScanResult; or its super classes
(declaration of 'android.net.wifi.ScanResult' appears in /system/framework/framework.jar!classes2.dex)

思路二,直接调用 ScanResult 构造方法行不通(低版本兼容问题),那使用反射方式调用呢?但同样遇到兼容性问题:

  1. 不同版本的 SDK 上非公开的构造方法参数不同
  2. 某些厂商可能修改了 ScanResult 构造方法

思路三,考虑到 ScanResult 实现了 Parcelable 接口,所以可以借助 Parcel 来序列化/反序列化已有的 ScanResult 来生成新的 ScanResult 实例。

-w709

代码如下:

1
2
3
4
5
6
7
8
9
public ScanResult scanResultInstance() {
ScanResult parent = sCopyInstance;

Parcel p = Parcel.obtain();
parent.writeToParcel(p, 0);
p.setDataPosition(0);

return ScanResult.CREATOR.createFromParcel(p);
}

简单又完美地创建 ScanResult 实例

参考