Restringe las interacciones con otras apps

Los permisos no solo se utilizan para solicitar funcionalidades del sistema. También puedes restringir las maneras en las que otras apps pueden interactuar con los componentes de la tuya.

En esta guía, se explica cómo verificar el conjunto de permisos que declaró otra app. También se explica cómo puedes configurar actividades, servicios, proveedores de contenido y receptores de emisión para restringir la forma en que otras apps pueden interactuar con la tuya.

Verifica los permisos de otra app

Si quieres ver el conjunto de permisos que declara otra app, usa un dispositivo o emulador para completar los siguientes pasos:

  1. Abre la pantalla Información de la app de una app.
  2. Selecciona Permisos. Se abrirá la pantalla Permisos de la app.

    En esta pantalla, se muestra un conjunto de grupos de permisos. El sistema organiza el conjunto de permisos que una app declaró en estos grupos.

Existen varias otras formas útiles de verificar los permisos.

  • Durante una llamada a un servicio, pasa una string de permiso a Context.checkCallingPermission(). Este método muestra un número entero que indica si se otorgó ese permiso al proceso de llamada actual. Ten en cuenta que esto solo se puede usar cuando ejecutas una llamada que ingresa de otro proceso; por lo general, mediante una interfaz IDL publicada por un servicio o proporcionada de alguna manera diferente a otro proceso.
  • Para verificar si se le otorgó un permiso específico a otro proceso, pasa el proceso (PID) a Context.checkPermission().
  • Para verificar si se le otorgó un permiso específico a otro paquete, pasa el nombre del paquete a PackageManager.checkPermission().

Restringe las interacciones con las actividades de tu app

Usa el atributo android:permission en la etiqueta <activity> del manifiesto para restringir qué otras apps pueden iniciar esa Activity. Se verifica el permiso durante Context.startActivity() y Activity.startActivityForResult(). Si el llamador no tiene el permiso necesario, se producirá un evento SecurityException.

Restringe las interacciones con los servicios de tu app

Usa el atributo android:permission en la etiqueta <service> en el manifiesto para restringir qué otras apps pueden iniciarse o vincularse al Service asociado. Se verifica el permiso durante Context.startService(), Context.stopService() y Context.bindService(). Si el llamador no tiene el permiso necesario, se producirá un evento SecurityException.

Restringe las interacciones con los proveedores de contenido de tu app

Usa el atributo android:permission en la etiqueta <provider> para restringir qué otras apps pueden acceder a los datos de un ContentProvider. (Los proveedores de contenido disponen de un recurso de seguridad adicional importante que se denomina permisos de URI y se describe a continuación). A diferencia de los otros componentes, hay dos atributos de permisos separados que puedes configurar para proveedores de contenido: android:readPermission restringe qué otras apps pueden leer del proveedor. android:writePermission restringe qué otras apps pueden escribir en él. Ten en cuenta que si un proveedor está protegido con un permiso de lectura y escritura, tener el permiso de escritura no permite que una app lea de un proveedor.

Los permisos se verifican cuando se recupera el proveedor por primera vez y cuando una app realiza operaciones en él. Si la app solicitante no tiene ninguno de los permisos, se produce una SecurityException. Se necesita permiso de lectura a fin de usar ContentResolver.query(), mientras que el uso de ContentResolver.insert(), ContentResolver.update() o ContentResolver.delete() requiere permiso de escritura. En todos estos casos, si no tienes el permiso obligatorio, se genera una SecurityException.

Otorga acceso según el URI

El sistema te proporciona un control detallado adicional sobre las maneras en que otras apps pueden acceder a los proveedores de contenido de tu app. En particular, tu proveedor de contenido puede protegerse con permisos de lectura y escritura, a la vez que permite que sus clientes directos compartan URI específicos con otras apps. Para declarar la compatibilidad de tu app con este modelo, usa el atributo android:grantUriPermissions o el elemento <grant-uri-permission>.

También puedes otorgar permisos según el URI. Cuando inicies una actividad o le muestres un resultado a una actividad, establece una o ambas de estas marcas de intent: Intent.FLAG_GRANT_READ_URI_PERMISSION o Intent.FLAG_GRANT_WRITE_URI_PERMISSION. Esto otorga a otras apps permisos de lectura, escritura o lectura y escritura, respectivamente, para el URI de datos que se incluye en el intent. Otras apps obtienen estos permisos para el URI específico, sin importar si tienen permiso de acceso a los datos en el proveedor de contenido de manera más general.

Por ejemplo, supongamos que un usuario utiliza tu app para ver un correo electrónico con un archivo adjunto de imagen. Otras apps no deberían poder acceder al contenido del correo electrónico en general, pero pueden estar interesadas en ver la imagen. Tu app puede usar un intent y la marca de intent Intent.FLAG_GRANT_READ_URI_PERMISSION para permitir que una app de visualización de imágenes la vea.

Otro aspecto que debes tener en cuenta es la visibilidad de la app. 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. Si tu app tiene un proveedor de contenido y le otorgó permisos de URI a otra, será visible automáticamente para la otra app.

Para obtener más información, consulta el material de referencia de los métodos grantUriPermission(), revokeUriPermission() y checkUriPermission().

Restringe las interacciones con los receptores de emisión de tu app

Usa el atributo android:permission en la etiqueta <receiver> para restringir qué otras apps pueden enviar emisiones al BroadcastReceiver asociado. Se verifica el permiso después de que se muestra Context.sendBroadcast(), mientras el sistema intenta proporcionar la emisión enviada al receptor en cuestión. Esto significa que una falla en el permiso no genera una excepción para el llamador, sino que simplemente no entrega el Intent.

De la misma manera, puedes proporcionar un permiso a Context.registerReceiver() para controlar qué otras apps pueden transmitir a un receptor registrado programáticamente. Por otro lado, puedes proporcionar un permiso cuando llames a Context.sendBroadcast() para restringir qué receptores de emisión pueden recibir la transmisión.

Ten en cuenta que tanto un receptor como un emisor pueden requerir un permiso. Cuando esto sucede, deben aprobarse ambas verificaciones de permisos para que se proporcione el intent al objetivo asociado. Para obtener más información, consulta Cómo usar permisos para restringir emisiones.