栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

如何绕过Google针对非 SDK 接口的反射限制

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

如何绕过Google针对非 SDK 接口的反射限制

前言

从 Android 9(API 级别 28)开始,Android 平台对应用能使用的非 SDK 接口实施了限制。只要应用引用非 SDK 接口或尝试使用反射或 JNI 来获取其句柄,这些限制就适用。

这些限制旨在帮助提升用户体验和开发者体验,为用户降低应用发生崩溃的风险,同时为开发者降低紧急发布的风险。

但!对开发者来说不一定是一件好事。

谷歌通过维护几个名单来进行对非SDK接口的限制

解决方案

既然谷歌通过维护这样几个名单来限制sdk的使用,那么我们只要通过修改名单就可以实现解除对应限制。

参考谷歌源代码中的测试项目

在Android 10谷歌的测试代码中

https://android.googlesource.com/platform/art/+/refs/heads/android10-release/test/674-hiddenapi/src-art/Main.java#120

最终都是通过调用

VMRuntime.getRuntime().setHiddenApiExemptions(new String[]{"L"}); 

Set exemptions to "L" (matches all classes) if we are testing whitelisting.← 谷歌注释

    private void disableHideApi() {
        try {
            getDeclaredMethod = Class.class.getDeclaredMethod("getDeclaredMethod", String.class, Class[].class);
            getMethod = Class.class.getDeclaredMethod("getMethod", String.class, Class[].class);

            getDeclaredField = Class.class.getDeclaredMethod("getDeclaredField", String.class);
            getField = Class.class.getDeclaredMethod("getField", String.class);

            getDeclaredConstructor = Class.class.getDeclaredMethod("getDeclaredConstructor", Class[].class);
            getConstructor = Class.class.getDeclaredMethod("getConstructor", Class[].class);
            newInstance = Constructor.class.getDeclaredMethod("newInstance", Object[].class);
            if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O) {
                Class clazz_VMRuntime = (Class) forName.invoke(null, "dalvik.system.VMRuntime");
                Method getRuntime = (Method) getDeclaredMethod.invoke(clazz_VMRuntime, "getRuntime", null);
                Method setHiddenApiExemptions = (Method) getDeclaredMethod.invoke(clazz_VMRuntime, "setHiddenApiExemptions", new Class[]{String[].class});
                Object vmRuntime = getRuntime.invoke(null);
                // Set exemptions to "L" (matches all classes) if we are testing whitelisting.
                setHiddenApiExemptions.invoke(vmRuntime, new Object[]{new String[]{"L"}});
            }
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
disableHideApi();
try {

    Class clz = mActivityCustomErrorBinding.etError.getClass();
    while (clz != TextView.class) {
        clz = clz.getSuperclass();
    }
    Field field_mEditor = (Field) getDeclaredField.invoke(clz, "mEditor");
    field_mEditor.setAccessible(true);

    Object mEditor = field_mEditor.get(mActivityCustomErrorBinding.etError);
    Class clz_Editor = Class.forName("android.widget.Editor");
    Method showError = (Method) getDeclaredMethod.invoke(clz_Editor, "showError", null);
    Method hideError = (Method) getDeclaredMethod.invoke(clz_Editor, "hideError", null);
    Log.e(TAG, mEditor.getClass().getName());

    Field field = (Field) getDeclaredField.invoke(clz_Editor, "mErrorPopup");
    field.setAccessible(true);

} catch (ClassNotFoundException | IllegalAccessException | InvocationTargetException e) {
    e.printStackTrace();
}
  

在需要进行反射的地方前面调用disableHideApi()。使用完毕后调用 setHiddenApiExemptions.invoke(sVmRuntime,newObject[]{newString[0]});重置列表即可。

实际上! 通过反射获取的getDeclaredMethod等反射方法进行反射工作,也可以直接绕过对非SDK接口的限制(上面例子其实不用调用disableHideApi()也可以通过)

例如Method setHiddenApiExemptions = (Method)getDeclaredMethod.invoke(vmRuntimeClass,"setHiddenApiExemptions",newClass[]{String[].class});

上面例子中的setHiddenApiExemptions 本来就是属于限制使用的非SDK接口。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/978732.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号