21

Android introduced @SystemApi in its SDK source code recently. Seems like same in effect as the @hide annotation before, since they also got stripped from SDK jar classes.

Is there any chance an app can call them in ways different from the old @hide APIs.

/**
 * Indicates an API is exposed for use by bundled system applications.
 * <p>
 * These APIs are not guaranteed to remain consistent release-to-release,
 * and are not for use by apps linking against the Android SDK.
 * </p><p>
 * This annotation should only appear on API that is already marked <pre>@hide</pre>.
 * </p>
 *
 * @hide
 */
Oasis Feng
  • 7,490
  • 3
  • 31
  • 44

2 Answers2

30

@SystemApi, @PrivateApi and @hide

According to this commit, @SystemApi is a rename of the old @PrivateApi. APIs marked @hide are not necessarily @SystemApi, but @SystemApi requires @hide.

For more information about @hide javadoc annotation, this post gives a good answer.

Based on my own experiments, one (non-system application) can still access @hide APIs and fields using Java reflection like (from this post):

WifiManager manager = (WifiManager) getSystemService(Context.WIFI_SERVICE);

WifiConfiguration config = new WifiConfiguration();
config.SSID = "AccessPointSSID";

Method method = manager.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, boolean.class);
method.invoke(manager, config, true);

But trying to access @SystemApi things using Java reflection is impossible (following code will trigger invocationTargetException):

WifiManager manager = (WifiManager) getSystemService(Context.WIFI_SERVICE);

Method method = manager.getClass().getMethod("getPrivilegedConfiguredNetworks");
List<WifiConfiguration> configs = (List<WifiConfiguration>)method.invoke(manager);

P.S.

In the WifiManager java code, the setWifiApEnabled and getPrivilegedConfiguredNetworks APIs are defined as:

/**
 * Start AccessPoint mode with the specified
 * configuration. If the radio is already running in
 * AP mode, update the new configuration
 * Note that starting in access point mode disables station
 * mode operation
 * @param wifiConfig SSID, security and channel details as
 *        part of WifiConfiguration
 * @return {@code true} if the operation succeeds, {@code false} otherwise
 *
 * @hide Dont open up yet
 */
public boolean setWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled) {
    try {
        mService.setWifiApEnabled(wifiConfig, enabled);
        return true;
    } catch (RemoteException e) {
        return false;
    }
}

and

/** @hide */
@SystemApi
public List<WifiConfiguration> getPrivilegedConfiguredNetworks() {
    try {
        return mService.getPrivilegedConfiguredNetworks();
    } catch (RemoteException e) {
        return null;
    }
}
ashughes
  • 7,155
  • 9
  • 48
  • 54
Moony Chou
  • 497
  • 5
  • 10
  • 1
    Thanks for your explanation! In my tests, most APIs with `@SystemApi` and `@hide` annotated (previously only annotated by `@hide`) are still accessible via reflection. What's the detailed message of `InvocationTargetException` in your case? – Oasis Feng Dec 07 '14 at 11:57
  • I did the experiment on my Nexus 5 with Android 5.0. @oasis-feng I guess the behavior of `@SystemApi` is version related? – Moony Chou Jan 12 '15 at 03:05
  • I also tested it on Nexus 5 with Android 5.0.2. Maybe it's different from API to API. Can you paste the detailed message of your InvocationTargetException? – Oasis Feng Jan 12 '15 at 08:43
7

Methods annotated with @SystemApi are a subset of ones with @hide. It's apparently an indicator for internal teams (perhaps also partners) that these methods are actual APIs, although not for public developers.

As a result, @SystemApi methods will be more stable than @hide ones, which could be changed at any time in the future without any compatibility consideration, and also any OEM is allowed to change them at their own will.

If you are trying to invoke internal APIs via reflection, always prefer @SystemApi methods for better future compatibility.

Oasis Feng
  • 7,490
  • 3
  • 31
  • 44