O que significa @hide no código fonte do Android?

120

Para o Activitycódigo fonte , linha 3898 (próxima à parte inferior):

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

O que @hidesignifica isso ?

Eu encontrei o meu public class ChildActivity extends Activity { ... }não pode usar / ver Activity.isResumed(). Isso é normal? Como posso acessá-lo?

midnite
fonte

Respostas:

182

O Android tem dois tipos de APIs que não são acessíveis via SDK.

O primeiro está localizado no pacote com.android.internal. O segundo tipo de API é uma coleção de classes e métodos marcados com o atributo @hide Javadoc .

A partir do Android 9 (API nível 28), o Google introduz novas restrições ao uso de interfaces não SDK , seja diretamente, via reflexão ou via JNI. Essas restrições são aplicadas sempre que um aplicativo faz referência a uma interface não SDK ou tenta obter seu identificador usando reflexão ou JNI.

Porém, antes do nível 28 da API, os métodos ocultos ainda podiam ser acessados ​​via reflexão de Java. O @hideatributo é apenas parte do Javadoc (droiddoc também), portanto, @hidesignifica simplesmente que o método / classe / campo é excluído dos documentos da API.

Por exemplo, o checkUidPermission()método em ActivityManager.javausa @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;
}

No entanto, podemos chamá-lo por reflexão:

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});
StarPinkER
fonte
1
Olá, @StarPinkER, posso conceder permissão "android.permission.CHANGE_COMPONENT_ENABLED_STATE" usando API oculta ou interna ou por reflexão?
Hardik
1
Verifique esta resposta primeiro. Essa permissão é uma assinatura / permissão do sistema. Na maioria dos casos, você não pode obter essa permissão, a menos que sejam aplicativos do sistema. Isso significa que você precisa modificar a Fonte Android para aceitar seu aplicativo ou torná-lo um aplicativo de sistema e assiná-lo. No entanto, você não poderá fazer isso a menos que esteja criando seu próprio sistema Android. O Reflection pode lidar com "ocultação", mas não pode alterar a lógica do sistema de segurança Android. Você pode imaginar como podemos atacar facilmente um dispositivo Android, se pudermos fazer isso. @Hardik
StarPinkER
2
Obrigado pela resposta, mas acho que há dois problemas na resposta, corrija-me se estiver errado. Eu recebo um erro sem classe se tentar encontrá-lo por "ActivityManager" em vez de "android.app.ActivityManager" e "m.invoke (c," parece ser "m.invoke (null", "para métodos estáticos" e "m. invoke (o, ", onde o é um objeto do tipo c, por métodos dinâmicos Desculpem a minha gramática polaca :).
lindenrovio
3
Apenas uma observação sobre a reflexão: como esses métodos / campos não fazem parte do SDK oficial, não há garantia de que eles estarão presentes em qualquer futura revisão do Android.
sstn
2
Se a anotação remove apenas o método da documentação, por que ainda não posso usá-lo no código?
Javier Delgado
25
  1. @hideé usado para itens que precisam estar visíveis por vários motivos, mas não fazem parte da API publicada. Eles não serão incluídos na documentação quando extrair automaticamente a API da fonte.

  2. Você está certo, você não pode substituí-lo. Isso é normal, é por design, pois está marcado como final. Você deve poder usá- lo, embora um editor não o mostre como uma das opções em qualquer intelecto que ele usa porque está marcado com @hide, e você deve tomar nota do ponto 3 abaixo.

  3. Você não deve usá-lo, pois não faz parte da API e os desenvolvedores podem removê-la sempre que desejarem. Eles estariam dentro dos seus direitos, se eles estivessem sadicamente inclinados, para substituí-lo por uma função que bloqueava o dispositivo em que ele era executado (embora talvez não em um sentido legal estrito).

paxdiablo
fonte
Oh sim ... é finalclaro que não posso substituí-lo. Desculpe, esse é o meu erro: x
midnite
Você quer dizer, é publicatravés de todas as classes durante o estágio de desenvolvimento. Mas ele age como privateou /*package*/para usuários como nós?
midnite
Hmm ... Isso é apenas um comentário. eu entendo seus significados. Mas o que e onde aplicar esse comportamento no nível do código?
midnite
1
Por que é público, não posso realmente comentar. Talvez a implementação do código Activityesteja espalhada por várias classes e todas elas precisem acessar esse membro. Resumindo, é público, mas não faz parte da API, o que significa que você a utiliza por seu próprio risco.
paxdiablo
1
@ midnite, o Eclipse tem seu próprio compilador Java, que sem dúvida é integrado ao material do intellisense. Eu sugeriria que se você compilasse isso com o Java SDK, ele seria bem compilado. Não que eu estou sugerindo isso, claro, ver o ponto 3.
paxdiablo
4

A @hideanotação significa que essa interface não faz parte da API pública e não deve ser usada no seu código. Os métodos são apenas para uso interno do AOSP.

O Google começou a restringir o uso de interfaces não sdk . Isso inclui interfaces marcadas com@hide

Os métodos são classificados em quatro listas:

  • lista branca: o SDK
  • light-greylist: métodos / campos não SDK que ainda estão acessíveis.
  • greylist escuro:
    • Para aplicativos cujo SDK de destino está abaixo do nível 28 da API: é permitido o uso de uma interface de lista cinza escura.
    • Para aplicativos cujo SDK de destino é API nível 28 ou superior: mesmo comportamento da lista negra
  • lista negra: restrita, independentemente do SDK de destino. A plataforma se comportará como se a interface estivesse ausente. Por exemplo, ele lançará NoSuchMethodError / NoSuchFieldException sempre que o aplicativo estiver tentando usá-lo e não o incluirá quando o aplicativo quiser conhecer a lista de campos / métodos de uma classe específica.

As listas podem ser encontradas aqui: https://android.googlesource.com/platform/prebuilts/runtime/+/master/appcompat

leonardkraemer
fonte