Android P 显示 API 兼容性错误消息

Android P displaying API compatibility error message

运行 在 Android P 上针对 SDK 级别 27 构建的应用程序有点不可预测地显示以下对话框(对话框标题是应用程序的名称):

Detected problems with API compatibility (visit g.co/dev/appcompat for more info)

URL 导致 this page about restrictions on non-SDK interfaces。我的应用程序本身不使用反射,但它使用 Gson。

Logcat 中没有立即明显的日志消息,除了可能的消息,例如:

Accessing hidden field Landroid/widget/AbsListView;->mIsChildViewEnabled:Z (light greylist, reflection)

原来我的一个 Gson 模型暴露了一个返回 File 的 getter。 Gson 使用反射递归检查 类 的字段,这样做违反了不允许的 SDK 接口的反射。

阅读问题中链接的限制文档让我仔细查看了日志消息,果然,一条引起了我的注意:

Accessing hidden field [...] (dark greylist, reflection)

我不记得确切的消息,但这里的重点是它在 灰名单中。

我通过针对 SDK 级别 28 并启用新的 StrictMode 功能发现了这一点 detectNonSdkApiUsage(),在该功能上我的应用程序将崩溃并显示堆栈跟踪:

if (BuildConfig.DEBUG && Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
    StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
            .detectNonSdkApiUsage()
            .penaltyLog()
            .build());
}

堆栈跟踪并不能立即提供深刻的见解,但它为我指明了正确的方向。

在您的应用程序中 class 在 onCreate() 方法中初始化此方法可以关闭此对话框。

private void closeAndroidPDialog(){
    try {
        Class aClass = Class.forName("android.content.pm.PackageParser$Package");
        Constructor declaredConstructor = aClass.getDeclaredConstructor(String.class);
        declaredConstructor.setAccessible(true);
    } catch (Exception e) {
        e.printStackTrace();
    }
    try {
        Class cls = Class.forName("android.app.ActivityThread");
        Method declaredMethod = cls.getDeclaredMethod("currentActivityThread");
        declaredMethod.setAccessible(true);
        Object activityThread = declaredMethod.invoke(null);
        Field mHiddenApiWarningShown = cls.getDeclaredField("mHiddenApiWarningShown");
        mHiddenApiWarningShown.setAccessible(true);
        mHiddenApiWarningShown.setBoolean(activityThread, true);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

但这很危险 这种方式只是让你看不到对话框。