Cómo administrar la visibilidad de un paquete

Cuando creas una app, es importante que consideres el conjunto de paquetes, que representan otras apps instaladas en el dispositivo, al que deseas que la app acceda. Si tu app se orienta a Android 11 (nivel de API 30) o una versión posterior, el sistema hace que algunas apps sean visibles automáticamente, pero oculta otras de forma predeterminada. Al hacer que algunas aplicaciones no sean visibles de forma predeterminada, el sistema incentiva el principio de privilegio mínimo indicando qué otras apps debe mostrarle a la tuya y ayuda a que las tiendas de aplicaciones, como Google Play, evalúen la privacidad y la seguridad que la app proporciona a los usuarios.

Estas diferencias en cuanto a la visibilidad de las apps afecta los resultados que se muestran correspondientes a métodos que proporcionan información sobre otras aplicaciones, como queryIntentActivities(). Además, afectan las interacciones explícitas con otras apps, como cuando se pretende iniciar su servicio.

En esta guía, se menciona el conjunto de apps visible automáticamente para la tuya y se describe cómo hacer lo mismo con otras aplicaciones. También se ofrecen algunas sugerencias para configurar mensajes de registro a fin de determinar cómo la visibilidad de otras apps afecta la tuya.

Apps visibles automáticamente

El sistema hace que algunas aplicaciones sean visibles automáticamente para la tuya para que pueda interactuar con ellas sin necesidad de declarar el elemento <queries>. Con este comportamiento, se brinda funcionalidad básica y casos de uso comunes.

En especial, los siguientes tipos de aplicaciones son siempre visibles para la tuya, incluso si tu app se orienta a Android 11 (nivel de API 30) o versiones posteriores:

Además, puedes iniciar la actividad de otra app con un intent implícito o explícito, independientemente de si la otra aplicación es visible para la tuya.

Paquetes de sistema visibles automáticamente

Algunos de los paquetes del sistema que implementan funcionalidades principales de Android son visibles automáticamente para tu app, incluso cuando esta se orienta a Android 11 (nivel de API 30) o versiones posteriores. El conjunto específico de paquetes depende del dispositivo que ejecuta tu aplicación.

Para ver la lista completa de paquetes de un dispositivo específico, ejecuta el siguiente comando en una terminal de tu máquina de desarrollo:

adb shell dumpsys package queries

En el resultado del comando, busca la sección forceQueryable. Allí, se incluye la lista de paquetes que el dispositivo hizo visible automáticamente para tu app.

Declara que tu app interactúa con un conjunto de aplicaciones específico

Si tu app se orienta a Android 11 (nivel de API 30) o versiones posteriores y necesita interactuar con aplicaciones que no son visibles automáticamente, agrega el elemento <queries> en el archivo de manifiesto de tu app. Dentro del elemento <queries>, especifica las otras apps por nombre de paquete, firma de intent o autoridad del proveedor, como se describe en las siguientes secciones.

Consulta a paquetes específicos e interactúa con ellos

Si conoces el conjunto específico de apps a las que quieres realizar consultas o con las que quieres interactuar (como las que se integran con tu app o aquellas cuyos servicios usas), incluye los nombres en un conjunto de elementos <package> dentro del elemento <queries>:

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

Cómo realizar consultas a otras apps e interactuar con ellas según un filtro de intents

Es posible que tu app necesite realizar consultas en un conjunto de apps que cumplen con un propósito determinado o interactuar con ese conjunto, pero quizás no conozcas los nombres de los paquetes específicos que debes incluir. En esta situación, puedes mostrar las firmas de filtros de intents en el elemento <queries>. Luego, tu app puede descubrir aplicaciones con elementos <intent-filter> que coincidan.

En el siguiente ejemplo, la app puede ver las apps instaladas que admiten el uso compartido de imágenes JPEG:

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

El elemento <intent> tiene algunas restricciones:

  • Debes incluir exactamente un elemento <action>.
  • No puedes usar los atributos path, pathPrefix, pathPattern o port en un elemento <data>. El sistema se comporta como si configuraras el valor de cada atributo para el carácter comodín genérico (*).
  • No puedes usar el atributo mimeGroup de un elemento <data>.
  • Dentro de los elementos <data> de un solo elemento <intent>, puedes usar cada uno de los siguientes atributos una vez como máximo:

    • mimeType
    • scheme
    • host

    Puedes distribuir esos atributos en varios elementos <data> o usarlos en un elemento <data> único.

El elemento <intent> admite el carácter comodín genérico (*) como valor para algunos atributos:

  • El atributo name del elemento <action>
  • El subtipo del atributo mimeType de un elemento <data> (image/*)
  • El tipo y el subtipo del atributo mimeType de un elemento <data> (*/*)
  • El atributo scheme de un elemento <data>
  • El atributo host de un elemento <data>

A menos que se especifique lo contrario en la lista anterior, el sistema no admite una combinación de caracteres de texto y comodín, como prefix*.

Cómo realizar consultas en apps e interactuar con ellas según una autoridad de proveedor

En los casos en los que necesites consultar un proveedor de contenido, pero no conozcas los nombres de paquetes específicos, puedes declarar la autoridad del proveedor en un elemento <provider>, como se muestra en el siguiente fragmento:

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

Puedes declarar varias autoridades de proveedores en un solo elemento <queries>. Para hacerlo, completa uno de los siguientes pasos:

  • En un solo elemento <provider>, declara una lista de autoridades delimitadas por punto y coma.
  • Incluye varios elementos <provider>, todos dentro del mismo elemento <queries>. En cada elemento <provider>, declara una sola autoridad o una lista de autoridades delimitadas por punto y coma.

Cómo realizar consultas en todas las apps e interactuar con ellas

En pocas ocasiones, es posible que la app necesite realizar consultas en todas las apps instaladas en un dispositivo o interactuar con ellas, independientemente de los componentes que incluyan. Para permitir que tu app vea todas las demás, el sistema proporciona el permiso QUERY_ALL_PACKAGES.

En la siguiente lista, se muestran algunos casos de uso en los que es apropiado incluir el permiso QUERY_ALL_PACKAGES:

  • Apps de lanzamiento
  • Apps de accesibilidad
  • Navegadores
  • Apps de uso compartido entre pares (P2P)
  • Apps de administración de dispositivos
  • Apps de seguridad

Sin embargo, en la gran mayoría de los casos, puedes entregar los casos de uso de tu app cuando interactúas con el conjunto de aplicaciones que son visibles automáticamente y declaras las otras apps a las que necesita acceder la tuya en el archivo de manifiesto. A fin de respetar la privacidad del usuario, tu app debe solicitar la menor cantidad de visibilidad del paquete necesaria para funcionar.

En una próxima actualización de la política, busca en Google Play los lineamientos para las apps que necesitan el permiso QUERY_ALL_PACKAGES.

Mensajes de registro para filtrar paquetes

A fin de descubrir más detalles sobre la manera en la que la visibilidad predeterminada de las apps afecta la tuya, puedes habilitar los mensajes de registro para filtrar paquetes. Si estás desarrollando una app de prueba o depurable en Android Studio, la función ya estará habilitada. De lo contrario, puedes ejecutar el siguiente comando en una ventana de terminal para habilitarla manualmente:

adb shell pm log-visibility --enable PACKAGE_NAME

Luego, cada vez que se filtran paquetes de los valores que se muestran de un objeto PackageManager, aparece un mensaje similar al siguiente en Logcat:

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