最新在做app一些列合规问题,针对我在合规中的问题处理做了下记录,方便后续遇到问题的朋友们一些参考,当然也真是我的处理方案,如果有更好的解决方案也希望能分享分享。
接到app检测报告时,我有点懵,曝出了10多个sdk在获取wifi信息
腾讯TBSSDK通过GetConnectionInfo获取Wifi信息,MAC地址
函数名:
GetConnectionInfo
详情:
result:{'WifiInfo':'SSID:,BSSID:02:00:00:00:00:00,MAC:02:00:00:00:00:00,Supplicantstate:COMPLETED,RSSI:-55,Linkspeed:468Mbps,Frequency:5785MHz,NetID:3,Meteredhint:false,score:60'}
stackTrace:[{'methodName':'getConnectionInfo','level':0,'fileName':'WifiManager.java','className':'android.net.wifi.WifiManager','lineNumber':1676},
okhttpSDK通过GetConnectionInfo获取Wifi信息,MAC地址,bssid
函数名:
GetConnectionInfo
详情:
result:{'WifiInfo':'SSID:HUAWEI-CVQG4R_5G,BSSID:74:c1:4f:a4:b1:78,MAC:02:00:00:00:00:00,Supplicantstate:COMPLETED,RSSI:-54,Linkspeed:468Mbps,Frequency:5785MHz,NetID:3,Meteredhint:false,score:60'}
stackTrace:[{'methodName':'getConnectionInfo','level':0,'fileName':'WifiManager.java','className':'android.net.wifi.WifiManager','lineNumber':1676},{'methodName':'c','level':0,'fileName':'NetworkUtils.java','className':'com.tencent.msdk.dns.base.e.d','lineNumber':81},{'methodName':'','level':0,'fileName':'StatisticsMerge.java','className':'com.tencent.msdk.dns.core.stat.StatisticsMerge','lineNu
腾讯灯塔SDK通过GetConnectionInfo获取Wifi信息,MAC地址,bssid
函数名:
GetConnectionInfo
详情:
result:{'WifiInfo':'SSID:HUAWEI-CVQG4R_5G,BSSID:74:c1:4f:a4:b1:78,MAC:02:00:00:00:00:00,Supplicantstate:COMPLETED,RSSI:-56,Linkspeed:468Mbps,Frequency:5785MHz,NetID:3,Meteredhint:false,score:60'}
stackTrace:[{'methodName':'getConnectionInfo','level':0,'fileName':'WifiManager.java','className':'android.net.wifi.WifiManager','lineNumber':1676},{'methodName':'h','level':0,'fileName':'DeviceInfo.java','className':'com.tencent.beacon.core.b.e','lineNumber':309},{'methodName':'a','level':0,'fileName':'LifecycleCallbacks.java','className':'com.tencent.beacon.core.a.e','lineNumber':157},{'methodName':'a','level':0,'fileName':'LifecycleCallbacks.java','className':'com.tencent.beacon.core.a.e','lineNumber':124},{'methodName':'onActivityResumed','level':0,'fileName':'LifecycleCallbacks.java','className':'com.tencent.beacon.core.a.e','lineNumber':73},{'methodName':'dispatchActivityResumed','level':0,'fileName':'Application.java','className':'android.app.Application','lineNumber':312},
我就不一一列举了,反正就是很多sdk都获取了
在同意隐私协议后的一瞬间,多个sdk会同时进行初始化,这些信息应该对于每个sdk都是必要的吧,我猜想的。
对此类问题的解决方案有
- 找到对应的sdk方 问问能不能让它提供一个接口,我去实现这样的接口来返回它需求的设备信息。(这个应该是最完好的方案)
- 我hook系统方法,当多个sdk来获取设备信息时,我先获取一次,然后把这个信息存储起来。后续别的地方要获取时直接取缓存的。
由于第三方sdk太多,且由于有的sdk甚至都找不到到底是什么,且他们是否愿意支持这样的修改也是一个未知数,所以采取了hook的方式
但使用hook的注意点有
- 对与不可变的信息可以只获取一次比如androidID,IEMI,等
- 对于会变的信息如位置信息,wifi信息等,需要设置缓存失效时间
- hook是否被系统禁止,异常等
下面是关于获取Wi-Fi信息getConnectionInfo的一个hook方案
/**
* File description.
* hook wifi信息获取 合规
*
* @author lihongjun
* @date 2021/7/15
*/
public class HookUtils {
private static volatile WifiInfo wifiInfo = null;
private static volatile long initTime = 0; // 初始化时间
private static final int TIME_DIS = 10 * 1000; // 每10秒失效 主要针对首次启动 很多sdk初始化时都在获取
/**
* hook wifi信息 合规
*
* @param context
*/
public static void hookNet(Context context) {
Field serviceField = null;
Class iWifiManager = null;
try {
iWifiManager = Class.forName("android.net.wifi.IWifiManager");
serviceField = WifiManager.class.getDeclaredField("mService");
serviceField.setAccessible(true);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
try {
if (serviceField == null || iWifiManager == null) {
return;
}
WifiManager wifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
Object realIwm = serviceField.get(wifi);
serviceField.set(wifi,
Proxy.newProxyInstance(iWifiManager.getClassLoader(), new Class[]{iWifiManager},
new IWMInvocationHandler(realIwm)));
MFLogUtils.e("HookUtils", "wifiManager hook success");
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 动态代理getConnectionInfo方法 缓存时间1分钟
*/
private static class IWMInvocationHandler implements InvocationHandler {
private Object real;
public IWMInvocationHandler(Object real) {
this.real = real;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 如果是获取wifi信息
if (method.getName().equals("getConnectionInfo")) {
long currentTime = SystemClock.elapsedRealtime();
if (currentTime - initTime > TIME_DIS || wifiInfo == null) {
Object result = method.invoke(real, args);
wifiInfo = (WifiInfo) result;
initTime = currentTime;
MFLogUtils.e("HookUtils", "通过系统获取" + "获取信息:" + method.getName());
} else {
MFLogUtils.e("HookUtils","使用缓存"+ "获取信息:" + method.getName());
}
return wifiInfo;
}
Object result = method.invoke(real, args);
MFLogUtils.e("HookUtils", "method invoke " + method.getName() + " data:" + result);
return result;
}
}
}
次处只处理了 wifi信息相关的,其它高频率获取用类似方法处理就行了