安卓app合规-获取频繁获取wifi信息

本文记录了作者在处理应用中因多个SDK频繁获取WiFi信息导致的合规问题,提出了两种解决方案:一是寻求SDK供应商接口定制,二是使用hook技术管理信息获取。同时强调了处理不可变信息和设置缓存策略的重要性,并给出了hook代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最新在做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都是必要的吧,我猜想的。
对此类问题的解决方案有

  1. 找到对应的sdk方 问问能不能让它提供一个接口,我去实现这样的接口来返回它需求的设备信息。(这个应该是最完好的方案)
  2. 我hook系统方法,当多个sdk来获取设备信息时,我先获取一次,然后把这个信息存储起来。后续别的地方要获取时直接取缓存的。

由于第三方sdk太多,且由于有的sdk甚至都找不到到底是什么,且他们是否愿意支持这样的修改也是一个未知数,所以采取了hook的方式
但使用hook的注意点有

  1. 对与不可变的信息可以只获取一次比如androidID,IEMI,等
  2. 对于会变的信息如位置信息,wifi信息等,需要设置缓存失效时间
  3. 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信息相关的,其它高频率获取用类似方法处理就行了

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值