Como gerenciar a visibilidade do pacote

Ao criar o app, é importante considerar o conjunto de pacotes que seu app pretende acessar representando outros apps instalados no dispositivo. Se o app for direcionado ao Android 11 (API de nível 30) ou versões mais recentes, o sistema deixará alguns apps visíveis automaticamente para o seu, mas ocultará outros por padrão. Ao tornar alguns apps não visíveis por padrão, o sistema ajuda a incentivar o princípio de privilégio mínimo informando ao sistema quais outros apps precisam ser exibidos ao seu, além de ajudar as app stores, como o Google Play, a avaliar a privacidade e segurança que seu app oferece aos usuários.

Essas diferenças na visibilidade do app afetam os resultados de retorno dos métodos que fornecem informações sobre outros apps, como queryIntentActivities(). As diferenças de visibilidade também afetam as interações explícitas com outros apps, como iniciar o serviço de outro app.

Este guia lista o conjunto de apps que são visíveis automaticamente para seu app e descreve como tornar outros apps visíveis para ele. O guia também oferece algumas sugestões sobre como configurar mensagens de registro para determinar como a visibilidade de outros apps afeta o seu.

Apps visíveis automaticamente

O sistema torna alguns apps visíveis para seu app automaticamente para que ele possa interagir com eles sem precisar declarar o elemento <queries>. Esse comportamento ajuda a oferecer compatibilidade com funcionalidades básicas e casos de uso comuns.

Especificamente, os seguintes tipos de apps sempre ficam visíveis para seu app, mesmo quando ele é destinado ao Android 11 (nível 30 da API) ou versões mais recentes:

Além disso, é possível iniciar a atividade de outro app usando uma intent implícita ou explícita, independentemente do outro app estar visível ou não para o seu.

Pacotes do sistema que são visíveis automaticamente

Alguns pacotes do sistema que implementam funcionalidades principais do Android ficam automaticamente visíveis para seu app, mesmo quando ele é destinado ao Android 11 (nível 30 da API) ou versões mais recentes. O conjunto específico de pacotes depende do dispositivo que executa o app.

Para ver a lista completa de pacotes de um dispositivo específico, execute o seguinte comando em um terminal na máquina de desenvolvimento:

adb shell dumpsys package queries

Na resposta ao comando, localize a seção forceQueryable. Essa seção inclui a lista de pacotes que o dispositivo deixou visíveis automaticamente para seu app.

Declarar que seu app interage com um conjunto específico de outros apps

Se o app for direcionado ao Android 11 (nível 30 da API) ou versões mais recentes e precisar interagir com outros apps visíveis automaticamente, adicione o elemento <queries> ao seu arquivo de manifesto do app. No elemento <queries>, especifique os outros apps pelo nome do pacote, pela assinatura da intent ou pela autoridade do provedor, conforme descrito nas seções a seguir.

Consultar e interagir com pacotes específicos

Se você conhece o conjunto específico de apps que quer consultar ou com os quais quer interagir, como apps que se integram ao seu ou apps cujos serviços você usa, inclua os nomes dos pacotes deles em um conjunto de elementos <package> dentro do elemento <queries>:

<manifest package="com.example.game">
    <queries>
        <package android:name="com.example.store" />
        <package android:name="com.example.services" />
    </queries>
    ...
</manifest>

Consultar e interagir com apps que receberam um filtro de intent

Seu app pode precisar consultar ou interagir com um conjunto de apps que atendem a uma finalidade específica, mas você pode não saber os nomes de pacotes específicos a serem incluídos. Nessa situação, você pode listar as assinaturas de filtro de intent no elemento <queries>. Seu app poderá descobrir apps que têm elementos <intent-filter> correspondentes.

O exemplo a seguir permite que seu app veja apps instalados compatíveis com o compartilhamento de imagens JPEG:

<manifest package="com.example.game">
    <queries>
        <intent>
            <action android:name="android.intent.action.SEND" />
            <data android:mimeType="image/jpeg" />
        </intent>
    </queries>
    ...
</manifest>

O elemento <intent> tem algumas restrições:

  • É necessário incluir exatamente um elemento <action>.
  • Não é possível usar os atributos path, pathPrefix, pathPattern ou port em um elemento <data>. O sistema se comporta como se o valor de cada atributo fosse o valor do caractere curinga genérico (*).
  • Não é possível usar o atributo mimeGroup de um elemento <data>.
  • Nos elementos <data> de um único elemento <intent>, é possível usar cada um dos seguintes atributos no máximo uma vez:

    • mimeType
    • scheme
    • host

    É possível distribuir esses atributos em vários elementos <data> ou usá-los em um único elemento <data>.

O elemento <intent> aceita o caractere curinga genérico (*) como o valor de alguns atributos:

  • O atributo name do elemento <action>.
  • O subtipo do atributo mimeType de um elemento <data> (image/*).
  • O tipo e subtipo do atributo mimeType de um elemento <data> (*/*).
  • O atributo scheme de um elemento <data>.
  • O atributo host de um elemento <data>.

A menos que especificado de outra forma na lista anterior, o sistema não é compatível com uma combinação de caracteres curinga e de texto, como prefix*.

Consultar e interagir com apps que tenham uma autoridade do provedor

Nos casos em que é preciso consultar um provedor de conteúdo, mas você não sabe os nomes dos pacotes específicos, declare essa autoridade de provedor em um elemento <provider>, conforme demonstrado no snippet a seguir:

<manifest package="com.example.suite.enterprise">
    <queries>
        <provider android:authorities="com.example.settings.files" />
    </queries>
    ...
</manifest>

É possível declarar várias autoridades do provedor em um único elemento <queries>. Para fazer isso, conclua uma das seguintes etapas:

  • Em um único elemento <provider>, declare uma lista de autoridades delimitada por ponto e vírgula.
  • Inclua vários elementos <provider>, todos no mesmo elemento <queries>. Em cada elemento <provider>, declare uma única autoridade ou uma lista de autoridades delimitada por ponto e vírgula.

Consultar e interagir com todos os apps

Em casos raros, o app pode precisar consultar ou interagir com todos os apps instalados em um dispositivo, independentemente dos componentes que eles contenham. Para permitir que seu app veja todos os outros apps instalados, o sistema fornece a permissão QUERY_ALL_PACKAGES.

A lista a seguir fornece alguns exemplos de casos de uso em que a permissão QUERY_ALL_PACKAGES é apropriada para incluir:

  • Apps da tela de início
  • Apps de acessibilidade
  • Navegadores
  • Apps de compartilhamento ponto a ponto (P2P)
  • Apps de gerenciamento de dispositivos
  • Apps de segurança

No entanto, na grande maioria dos casos, é possível atender aos casos de uso do seu app interagindo com o conjunto de apps visíveis automaticamente e declarando os outros apps que seu app precisa acessar no arquivo de manifesto. Para respeitar a privacidade do usuário, seu app precisa solicitar a menor quantidade de visibilidade do pacote necessária para que ele funcione.

Na próxima atualização da política, procure o Google Play para fornecer diretrizes para apps que precisam da permissão QUERY_ALL_PACKAGES.

Mensagens de registro para filtragem de pacotes

Para descobrir mais detalhes sobre como a visibilidade padrão de apps afeta seu app, ative as mensagens de registro para filtragem de pacotes. Se estiver desenvolvendo um app de teste ou depurável no Android Studio, esse recurso estará ativado. Caso contrário, será possível executar o seguinte comando em uma janela de terminal para ativá-lo manualmente:

adb shell pm log-visibility --enable PACKAGE_NAME

Em seguida, sempre que os pacotes forem filtrados dos valores de retorno de um objeto PackageManager, você verá uma mensagem semelhante à seguinte no Logcat:

I/AppsFilter: interaction: PackageSetting{7654321 \
  com.example.myapp/12345} -> PackageSetting{...} BLOCKED