Что означает @hide в исходном коде Android?

Для Activity исходный код, строка 3898 (рядом со дном):

/**
 * @hide
 */
public final boolean isResumed() {
    return mResumed;
}

Что означает @hide?

Я обнаружил, что мой public class ChildActivity extends Activity { ... } не может использовать /see Activity.isResumed(). Это нормально? Как я могу получить к нему доступ?

Ответ 1

В Android есть два типа API, которые недоступны через SDK.

Первый находится в упаковке com.android.internal. Второй тип API - это набор классов и методов, помеченных атрибутом @hide Javadoc.

Начиная с Android 9 (уровень API 28), Google вводит новые ограничения на использование не SDK-интерфейсов, будь то напрямую, через отражение или через JNI. Эти ограничения применяются всякий раз, когда приложение ссылается на интерфейс не SDK или пытается получить его дескриптор, используя отражение или JNI.

Но до уровня API 28 к скрытым методам можно было получить доступ через отражение Java. Атрибут @hide является лишь частью Javadoc (также droiddoc), поэтому @hide просто означает, что метод/класс/поле исключен из документации API.

Например, метод checkUidPermission() в ActivityManager.java использует @hide:

/** @hide */
public static int checkUidPermission(String permission, int uid) {
    try {
        return AppGlobals.getPackageManager()
                .checkUidPermission(permission, uid);
    } catch (RemoteException e) {
        // Should never happen, but if it does... deny!
        Slog.e(TAG, "PackageManager is dead?!?", e);
    }
    return PackageManager.PERMISSION_DENIED;
}

Однако мы можем назвать это отражением:

Class c;
c = Class.forName("android.app.ActivityManager");
Method m = c.getMethod("checkUidPermission", new Class[] {String.class, int.class});
Object o = m.invoke(null, new Object[]{"android.permission.READ_CONTACTS", 10010});

Ответ 2

  • @hide используется для вещей, которые должны быть видимыми по разным причинам, но не являются частью опубликованного API. Они не будут включены в документацию, когда она автоматически извлекает API из источника.

  • Вы правы, вы не можете переопределить его. Это нормально, что по дизайну, так как он обозначен как final. Вы должны быть в состоянии использовать его, хотя редактор может не показывать его вам как один из вариантов в любом intellisense, который он использует, потому что он отмечен @hide, и вы должны принять к сведению пункт 3 ниже.

  • Вы не должны использовать его вообще, так как он не является частью API, и разработчики могут удалить его, когда захотят. Они даже были бы в пределах своих прав, если бы они были настроены с садизмом, чтобы заменить его функцией, которая запирала устройство, на котором оно работало (хотя, возможно, не в строгом юридическом смысле).

Ответ 3

Аннотация @hide означает, что этот интерфейс не является частью общедоступного API и не должен использоваться в вашем коде. Методы предназначены только для внутреннего использования AOSP.

Google фактически начал ограничивать использование интерфейсов не SDK. Это включает интерфейсы, отмеченные @hide

Методы разделены на четыре списка:

  • белый список: SDK
  • light-greylist: не SDK методы/поля, которые все еще доступны.
  • темно-серый список:
    • Для приложений, чей целевой SDK ниже уровня API 28: разрешено каждое использование интерфейса "темного серого".
    • Для приложений с целевым SDK уровня API 28 или выше: такое же поведение, как и в черном списке
  • черный список: ограничен независимо от целевого SDK. Платформа будет вести себя так, как будто интерфейс отсутствует. Например, он бросит NoSuchMethodError/NoSuchFieldException всякий раз, когда приложение пытается использовать его, и не будет включать его, когда приложение хочет знать список поля/методы определенного класса.

Списки можно найти здесь: https://android.googlesource.com/platform/prebuilts/runtime/+/master/appcompat