Android P introduces new restrictions on the use of non-SDK interfaces, whether directly, via reflection, or via JNI. These restrictions are applied whenever an app references a non-SDK interface or attempts to obtain its handle using reflection or JNI. For more information about this decision, see Improving Stability by Reducing Usage of non-SDK Interfaces.
In general, apps should only use the officially documented parts of the classes in the SDK. In particular, this means that you should not plan to access methods or fields that are not listed in the SDK when you interact with a class via semantics such as reflection.
Using such methods or fields has a high risk of breaking your app.
Differentiating between SDK and non-SDK interfaces
Generally speaking, SDK interfaces are those ones found documented in the Android framework Package Index. Handling of non-SDK interfaces is an implementation detail that the API abstracts away; it is subject to change without notice.
Android P introduces new restrictions on the use of non-SDK interfaces, whether directly, via reflection, or via JNI. These restrictions are applied whenever an app references a non-SDK interface or attempts to obtain its handle using reflection or JNI.
Testing for non-SDK interfaces
You can test your app by downloading the first Developer Preview (DP1) of Android P. DP1 does not restrict any non-SDK interfaces; instead, it prints logs and potentially toasts if your app accesses a non-SDK interface. Pay attention to the toasts, which call attention to interfaces that are proposed for restriction. Also, make sure to inspect your app's log messages, which contain more detailed information about the non-SDK interface that your app accessed, including the declaring class, name and type in the format used by the Android runtime. Log messages also indicate the means of access: direct, via reflection, or via JNI. along with the applicable greylist.
There are two greylists: The light greylist contains methods and fields which continue to function in Android P, but to which we do not guarantee access in future versions of the platform. If there is a reason that you cannot implement an alternative strategy to a light-greylisted API, you may file a bug to request reconsideration of the restriction.
The dark greylist contains methods intended to be made inaccessible in a future Developer Preview release.
These log messages can be accessed with
adb logcat and
will appear under the PID of the running app. An entry in the log
might read as follows:
Accessing hidden field Landroid/os/Message;->flags:I (light greylist, JNI) Accessing hidden method Landroid/app/ActivityThread;->currentActivityThread()Landroid/app/ActivityThread; (dark greylist, reflection)
Ramifications of keeping non-SDK interfaces
In a subsequent release of the Developer Preview, various means of accessing non-SDK interfaces will produce errors or other undesirable results. Table 1 provides details about means of access and their respective results.
|Means of access||Result|
|Dalvik instruction referencing a field||NoSuchFieldError thrown|
|Dalvik instruction referencing a method||NoSuchMethodError thrown|
|Reflection via Class.getDeclaredField() or Class.getField()||NoSuchFieldException thrown|
|Reflection via Class.getDeclaredMethod(), Class.getMethod()||NoSuchMethodException thrown|
|Reflection via Class.getDeclaredFields(), Class.getFields()||Non-SDK members not in results|
|Reflection via Class.getDeclaredMethods(), Class.getMethods()||Non-SDK members not in results|
|JNI via env->GetFieldID()||NULL returned, NoSuchFieldError thrown|
|JNI via env->GetMethodID()||NULL returned, NoSuchMethodError thrown|