La plataforma Android permite que los dispositivos tengan perfiles de trabajo (a veces denominados perfiles administrados). Un administrador de TI controla un perfil de trabajo, y la funcionalidad disponible para este se configura por separado de la funcionalidad del perfil principal del usuario. Este enfoque permite que las organizaciones controlen el entorno en el que se ejecutan apps y datos específicos de la empresa en el dispositivo de un usuario, a la vez que permite que los usuarios usen sus apps y perfiles personales.
En esta lección, se muestra cómo modificar tu aplicación para que funcione de manera confiable en un dispositivo con un perfil de trabajo. No necesitas hacer nada más que las prácticas recomendadas comunes para el desarrollo de apps. Sin embargo, algunas de estas prácticas recomendadas se vuelven especialmente importantes en los dispositivos con perfiles de trabajo. En este documento, se destacan los problemas que debes tener en cuenta.
Descripción general
A menudo, los usuarios quieren utilizar sus dispositivos personales en un entorno empresarial. Esta situación puede presentar un dilema a las organizaciones. Si el usuario puede usar su propio dispositivo, la organización debe preocuparse de que la información confidencial (como los correos electrónicos y contactos de los empleados) esté en un dispositivo que la organización no controla.
Para solucionar esta situación, Android 5.0 (nivel de API 21) permite a las organizaciones configurar perfiles de trabajo. Si un dispositivo tiene un perfil de trabajo, el administrador de TI controla la configuración del perfil. El administrador de TI puede elegir qué apps se permiten en ese perfil y controlar solo las funciones del dispositivo disponibles para el perfil.
Si un dispositivo tiene un perfil de trabajo, existen consecuencias para las apps que se ejecutan en él, independientemente del perfil en el que se ejecute la app:
- De forma predeterminada, la mayoría de los intents no pasan de un perfil a otro. Si una app que se ejecuta en el perfil activa un intent, no hay un controlador para el intent en ese perfil y no se permite que el intent pase al otro perfil debido a restricciones del perfil, la solicitud falla y la app puede cerrarse de forma inesperada.
- El administrador de TI del perfil puede limitar las apps del sistema que están disponibles en el perfil de trabajo. Esta restricción también puede provocar que no haya un controlador para algunos intents comunes en el perfil de trabajo.
- Dado que los perfiles personal y de trabajo tienen áreas de almacenamiento separadas, un URI de archivo válido en un perfil no lo es en el otro. Cualquier intent activado en un perfil puede controlarse en el otro (según la configuración del perfil), por lo que no es seguro adjuntar URI de archivos a intents.
Cómo evitar intents con errores
En un dispositivo con un perfil de trabajo, existen restricciones en cuanto a la posibilidad de que los intents pasen de un perfil a otro. En la mayoría de los casos, cuando se envía un intent, se controla en el mismo perfil en el que se activa. Si no hay un controlador para el intent en ese perfil, el intent no se maneja, y la app que lo activó puede cerrarse de forma inesperada, incluso si hay un controlador para el intent en el otro perfil.
El administrador de perfiles puede elegir qué intents pueden pasar de un perfil a otro. Dado que el administrador de TI toma esta decisión, no hay forma de que sepas con anticipación qué intents pueden cruzar este límite. El administrador de TI establece esta política y tiene la libertad de cambiarla en cualquier momento.
Antes de que tu app inicie una actividad, debes verificar que haya una resolución adecuada. Llama a Intent.resolveActivity()
para verificar que exista una resolución aceptable. Si no hay forma de resolver el intent, el método muestra null
. Si el método muestra un valor no nulo, hay al menos una forma de resolver el intent y es seguro activarlo. En este caso, el intent se podría resolver porque hay un controlador en el perfil actual o porque el intent tiene permiso para cruzarse con un controlador en el otro perfil. (Para obtener más información sobre la resolución de intents, consulta Intents comunes).
Por ejemplo, si tu app necesita establecer temporizadores, debería verificar que haya un controlador válido para el intent ACTION_SET_TIMER
. Si la app no puede resolver el intent, debería realizar una acción adecuada (como mostrar un mensaje de error).
Kotlin
fun startTimer(message: String, seconds: Int) { // Build the "set timer" intent val timerIntent = Intent(AlarmClock.ACTION_SET_TIMER).apply { putExtra(AlarmClock.EXTRA_MESSAGE, message) putExtra(AlarmClock.EXTRA_LENGTH, seconds) putExtra(AlarmClock.EXTRA_SKIP_UI, true) } // Check if there's a handler for the intent if (timerIntent.resolveActivity(packageManager) == null) { // Can't resolve the intent! Fail this operation cleanly // (perhaps by showing an error message) } else { // Intent resolves, it's safe to fire it off startActivity(timerIntent) } }
Java
public void startTimer(String message, int seconds) { // Build the "set timer" intent Intent timerIntent = new Intent(AlarmClock.ACTION_SET_TIMER) .putExtra(AlarmClock.EXTRA_MESSAGE, message) .putExtra(AlarmClock.EXTRA_LENGTH, seconds) .putExtra(AlarmClock.EXTRA_SKIP_UI, true); // Check if there's a handler for the intent if (timerIntent.resolveActivity(getPackageManager()) == null) { // Can't resolve the intent! Fail this operation cleanly // (perhaps by showing an error message) } else { // Intent resolves, it's safe to fire it off startActivity(timerIntent); } }
Cómo compartir archivos entre perfiles
En ocasiones, una app necesita proporcionar a otras apps acceso a sus propios archivos. Por ejemplo, una app de galería de imágenes podría querer compartir sus imágenes con editores de imágenes. Por lo general, hay dos maneras en las que compartirías un archivo: con un URI de archivo o un URI de contenido.
El URI de un archivo comienza con el prefijo file:
, seguido de la ruta de acceso absoluta del archivo en el almacenamiento del dispositivo. Sin embargo, debido a que el perfil de trabajo y el perfil personal usan áreas de almacenamiento separadas, un URI de archivo que sea válido en un perfil no lo será en el otro. Esta situación significa que si adjuntas un URI de archivo a un intent y el intent se controla en el otro perfil, el controlador no puede acceder al archivo.
En su lugar, debes compartir archivos con URI de contenido. Los URI de contenido identifican el archivo de una manera más segura y que se puede compartir. El URI de contenido incluye la ruta de acceso al archivo, pero también la autoridad que proporciona el archivo y un número de ID que identifica el archivo. Puedes generar un ID de contenido para cualquier archivo mediante un FileProvider
. Luego, puedes compartir ese Content ID con otras apps (incluso en el otro perfil). El destinatario puede usar el ID de contenido para obtener acceso al archivo real.
Por ejemplo, así es como obtendrías el URI de contenido para un URI de archivo específico:
Kotlin
// Open File object from its file URI val fileToShare = File(fileUriToShare) val contentUriToShare: Uri = FileProvider.getUriForFile( context, "com.example.myapp.fileprovider", fileToShare )
Java
// Open File object from its file URI File fileToShare = new File(fileUriToShare); Uri contentUriToShare = FileProvider.getUriForFile(getContext(), "com.example.myapp.fileprovider", fileToShare);
Cuando llamas al método getUriForFile()
, debes incluir la autoridad del proveedor de archivos (en este ejemplo, "com.example.myapp.fileprovider"
), que se especifica en el elemento <provider>
del manifiesto de tu app.
Para obtener más información sobre cómo compartir archivos con URI de contenido, consulta Cómo compartir archivos.
Cómo escuchar notificaciones
Por lo general, una app proporciona una subclase NotificationListenerService
para recibir devoluciones de llamada del sistema sobre los cambios en las notificaciones. Los dispositivos con perfiles de trabajo pueden afectar el funcionamiento de NotificationListenerService
con tu app.
En un perfil de trabajo
No puedes usar un NotificationListenerService
de una app que se ejecute en el perfil de trabajo. Cuando tu app se ejecuta en un perfil de trabajo, el sistema ignora el NotificationListenerService
de la app. Sin embargo, las apps que se ejecutan en el perfil personal pueden escuchar notificaciones.
En un perfil personal
Cuando tu app se ejecuta en el perfil personal, es posible que no recibas notificaciones
de las apps que se ejecutan en el perfil de trabajo. De forma predeterminada, todas las apps de perfil personal reciben devoluciones de llamada, pero un administrador de TI puede incluir en la lista de entidades permitidas una o más apps de perfil personal que permiten detectar cambios en las notificaciones. Luego, el sistema bloquea las apps que no están incluidas en la lista de entidades permitidas. En Android 8.0 (nivel de API 26) o versiones posteriores, un controlador de política de dispositivo (DPC) que administra un perfil de trabajo podría bloquear tu app para que no escuche las notificaciones del perfil de trabajo con el método DevicePolicyManager
setPermittedCrossProfileNotificationListeners()
.
Tu app seguirá recibiendo devoluciones de llamada sobre las notificaciones publicadas en el perfil personal.
Prueba la compatibilidad de tu app con los perfiles de trabajo
Debes probar tu app en un entorno de perfil de trabajo para detectar problemas que podrían hacer que tu app falle en un dispositivo con perfiles de trabajo. En particular, realizar pruebas en un dispositivo con perfil de trabajo es una buena manera de asegurarte de que tu app controle los intents correctamente: no activa intents que no se pueden controlar, no adjunta URIs que no funcionan en el perfil sincronizado, etc.
Proporcionamos una app de ejemplo, TestDPC, que puedes usar para configurar un perfil de trabajo en un dispositivo Android que ejecuta Android 5.0 (nivel de API 21) y versiones posteriores. Esta app te ofrece una manera sencilla de probar tu app en un entorno de perfil de trabajo. También puedes usar esta app para configurar el perfil de trabajo de la siguiente manera:
- Especificar qué apps predeterminadas están disponibles en el perfil administrado
- Configura qué intents pueden pasar de un perfil a otro
Si instalas de forma manual una app mediante un cable USB en un dispositivo que tiene un perfil de trabajo, la app se instalará en el perfil personal y en el de trabajo. Una vez que hayas instalado la app, podrás probarla en las siguientes condiciones:
- Si una app predeterminada (por ejemplo, la app de cámara) suele controlar un intent, intenta inhabilitar esa app predeterminada en el perfil de trabajo y verifica que la app maneje esto correctamente.
- Si activas un intent y espera que lo controle otra app, intenta habilitar e inhabilitar el permiso de ese intent para cruzar de un perfil a otro. Verifica que la app se comporte de manera correcta en ambas circunstancias. Si no se permite que el intent pase entre perfiles, verifica el comportamiento de la app cuando haya un controlador adecuado en el perfil de la app y cuando no lo haya.
Por ejemplo, si tu app activa un intent relacionado con un mapa, prueba cada una de las siguientes situaciones:
- El dispositivo permite que los intents de mapa se crucen de un perfil a otro, y hay un controlador adecuado en el otro perfil (el perfil en el que no se ejecuta la app)
- El dispositivo no permite que los intents de mapa se crucen entre perfiles, pero existe un controlador adecuado en el perfil de la app
- El dispositivo no permite que los intents de mapa se crucen entre perfiles, y no hay un controlador adecuado para estos intents en el perfil del dispositivo
- Si adjuntas contenido a un intent, verifica que se comporte de manera correcta cuando se controla en el perfil de la app y cuando cruza entre perfiles.
Prueba los perfiles de trabajo: sugerencias y trucos
Hay algunos trucos que pueden resultarte útiles para realizar pruebas en un dispositivo de perfil de trabajo.
- Como se indicó, cuando transfieres una app en un dispositivo con perfil de trabajo, se instala en ambos perfiles. Si lo deseas, puedes borrar la app de un perfil y dejarla en el otro.
- La mayoría de los comandos del administrador de actividades disponibles en el shell de Android Debug Bridge (adb) admiten la marca
--user
, que te permite especificar con qué usuario ejecutarlos. Cuando especificas un usuario, puedes elegir si se ejecutará como el usuario principal no administrado o como el perfil de trabajo. Para obtener más información, consulta Comandos de shell de ADB. - Para encontrar los usuarios activos en un dispositivo, usa el comando
list users
del administrador de paquetes adb. El primer número de la string de salida es el ID del usuario, que puedes usar con la marca--user
. Para obtener más información, consulta Comandos de shell de ADB.
Por ejemplo, para buscar a los usuarios en un dispositivo, deberías ejecutar este comando:
$ adb shell pm list users UserInfo{0:Drew:13} running UserInfo{10:Work profile:30} running
En este caso, el usuario principal("Drew") tiene el ID de usuario 0, y el perfil de trabajo tiene el ID de usuario 10. Para ejecutar una app en el perfil de trabajo, usarías un comando como el siguiente:
$ adb shell am start --user 10 \ -n "com.example.myapp/com.example.myapp.testactivity" \ -a android.intent.action.MAIN -c android.intent.category.LAUNCHER