Running an app built against SDK level 27 on Android P somewhat unpredictably displays the following dialog (the dialog title is the name of the application):
Detected problems with API compatibility (visit g.co/dev/appcompat for more info)
The URL leads to this page about restrictions on non-SDK interfaces. My application doesn't use reflection itself, but it does use Gson.
There are no immediately obvious log messages in Logcat, except may messages such as:
Accessing hidden field Landroid/widget/AbsListView;->mIsChildViewEnabled:Z (light greylist, reflection)
Turns out that one of my Gson models exposed a getter that returned File. Gson uses reflection to recursively inspect the fields of classes, and in doing so, violates the reflection of disallowed SDK interfaces.
Reading the restriction document linked in the question got me to take a closer look at the log messages, and sure enough, one caught my attention:
Accessing hidden field [...] (dark greylist, reflection)
I don't recall exactly the message, but the point here is that it was in the dark greylist.
I discovered this by targeting SDK level 28 and enabling the new StrictMode feature detectNonSdkApiUsage()
, upon which my application would crash with a stack trace:
if (BuildConfig.DEBUG && Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
.detectNonSdkApiUsage()
.penaltyLog()
.build());
}
The stack trace wasn't immediately insightful, but it pointed me in the right direction.
in you application class in the method onCreate() init this method can be close this dialog.
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();
}
}
but this is dangerous this way is just make you can't see the dialog.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With