Prácticas recomendadas para aplicaciones Android

16 de marzo de 2018

Los procedimientos recomendados que se describen en este artículo tienen por finalidad mejorar la compatibilidad entre XenMobile y las aplicaciones móviles para dispositivos Android.

MDX App SDK y el empaquetado

Si la aplicación usa el MDX App SDK, debe usar la versión correspondiente del MDX Toolkit para empaquetar. Si las versiones de estos dos componentes no coinciden, el funcionamiento posterior de la aplicación puede no ser correcto.

Para evitar este tipo no problema, empaquete la aplicación con el tipo Premium o General. Eso permite entregar una aplicación empaquetada previamente. Como resultado, el cliente no necesitará empaquetar la aplicación, y así se evitará el uso de un MDX Toolkit de otra versión. Para obtener más información sobre cómo empaquetar aplicaciones, consulte Empaquetado de aplicaciones móviles Android en la documentación del MDX Toolkit.

No bloquee el subproceso principal

No debe usar código de bloqueo cuando ejecute procesos en el subproceso principal. Esta es una directriz de Google, pero es incluso más importante cuando se trata de XenMobile. Algunas acciones pueden tardar más tiempo en una aplicación administrada o pueden incluso bloquear la ejecución posterior del subproceso.

A continuación, dispone de algunos ejemplos de código de bloqueo:

  • Operaciones de archivo o base de datos
  • Operaciones de red

Para mayor claridad, todos los métodos de ciclo de vida típicos de las aplicaciones, como onCreate, se ejecutan en el subproceso principal.

Google ofrece una API StrictMode que puede ayudar a detectar código de bloqueo. Para obtener detalles, consulte esta entrada de blog: http://android-developers.blogspot.com/2010/12/new-gingerbread-api-strictmode.html.

Escriba un código sólido

En concreto, es necesario comprobar los valores de retorno o excepciones de filtrado (catch) que devuelven las API de la plataforma. Aunque esta es solo una recomendación frecuente para una mejor programación, es muy importante para las aplicaciones administradas.

Varias API que suelen funcionar siempre fallarán si las directivas de XenMobile bloquean la funcionalidad subyacente. Entre los ejemplos se incluyen las capacidades descritas anteriormente:

  • Las API de red actúan como si no hubiera red alguna.
  • Las API de sensores, como el GPS y la cámara, devuelven valores nulos o inician una excepción.
  • Fallan los intentos dirigidos a una aplicación no administrada.
  • El acceso a los archivos y las base de datos puede fallar si se intenta desde el subproceso principal. Para obtener más información, consulte Comprobar la compatibilidad del cifrado de datos y Entropía de usuario en el cifrado en este artículo.

Cuando se produce un fallo, la aplicación debe poder gestionar correctamente el problema, en lugar de bloquearse.

Limitaciones de enlazado

MDX introduce funcionalidad en una aplicación Android binaria modificando el código DEX en el APK. Lo que presenta varias limitaciones:

  • Puede que XenMobile no gestione correctamente las clases obsoletas de plataformas pertenecientes a las versiones del Android SDK anteriores a la versión 4.0. Debe evitar esas clases obsoletas.
  • La mayor parte de la funcionalidad se inserta en las API de las plataformas Java o Android. Por lo general, no se administra código nativo (C o C++). Una excepción es que el cifrado de archivos se sigue produciendo incluso con el código nativo.
  • El código nativo que usa JNI para acceder a la funcionalidad de Java debe apuntar solamente al código de la aplicación de usuario. En otras palabras, no use JNI para invocar directamente los métodos de las plataformas Java o Android. En su lugar, use el patrón de diseño de proxy para “empaquetar” la clase necesaria de la plataforma en una clase propia de Java. A continuación, invoque la clase del código nativo.

Comprobar la compatibilidad del cifrado de datos

Una de las funciones principales de MDX es que todos los datos persistente se cifran de forma transparente. No es necesario modificar la aplicación para obtener esta funcionalidad y, de hecho, no se puede evitar directamente. El administrador puede desactivar el cifrado de forma selectiva o completamente, pero la aplicación no tiene esa opción.

Este es uno de los puntos más densos de MDX y requiere que se entiendan los siguientes puntos:

  • El cifrado de archivos está presente para todo el código Java y nativo que se ejecuta en los procesos administrados.

  • Algunas API de plataforma (como reproductores de medios y respaldos de impresión), se ejecutan en realidad en varios procesos independientes del SO. Si usa una API de este tipo, pueden surgir problemas.

    • Ejemplo: La aplicación guarda un archivo en el disco (cifrado) y, a continuación, pasa una referencia del archivo a una API de medios. Esa API de medios intenta leer el archivo, pero no entiende el contenido cifrado. Se produce un error en la API o incluso se bloquea la aplicación.
    • Ejemplo: Crea un identificador de archivo (que inicia un archivo cifrado) y lo entrega a la API de la cámara. El proceso de cámara escribe directamente los datos sin cifrar en el archivo cifrado. Cuando la aplicación intenta leer los datos, estos dejan de estar cifrados, con lo que se producen elementos basura.
  • Una manera de gestionar varios procesos independientes es descifrar un archivo antes de entregárselo a la API relevante. O bien, si la API escribe datos, podría dejar que los escribiera primero para, a continuación, cifrarlos cuando la API haya terminado. Se requieren varios pasos:

    1. Designar un área que permanecerá sin cifrar. Debe documentar este tema de cara a su cliente, ya que entonces un administrador de XenMobile debe crear una directiva de exclusiones de cifrado.
    2. Para descifrar un archivo, cópielo simplemente desde la ubicación normal (cifrada) a la ubicación no cifrada. Tenga en cuenta que debe realizar una copia de bytes, no una operación de mover el archivo.
    3. Para cifrar el archivo, invierta la dirección de las acciones. Copie el archivo desde una ubicación sin cifrar a una cifrada.
    4. Elimine el archivo no cifrado cuando ya no sea necesario.
  • No se admite la asignación de memoria cuando se trata de archivos cifrados. Por lo tanto, si llama a una API que asigna memoria, esta fallará. Debe poder gestionar el error. Si es posible, evite el uso directo e indirecto de la asignación de memoria. Un caso notable de uso indirecto es la biblioteca de terceros SqlCipher.

    Si la asignación de memoria no se puede evitar, el administrador debe especificar una directiva de exclusiones de cifrado en la que se omitan los archivos pertinentes. Debe documentar esta directiva para su cliente.

  • El cifrado agrega un consumo notorio de los recursos. Debe optimizar las operaciones E/S de los archivos para evitar la degradación del rendimiento. Por ejemplo, si lee y escribe repetidamente la misma información, puede que le interese implementar una caché a nivel de aplicación.

  • Las bases de datos son solo archivos y, por lo tanto, también se cifran. El rendimiento también puede ser un problema aquí. El tamaño de la memoria caché estándar para base de datos es de 2000 páginas u 8 megabytes. Si la base de datos es grande, puede aumentar este tamaño.

    El modo SQLite WAL no se admite debido a la limitación en la asignación de memoria.

Entropía de usuario en el cifrado

Una opción de XenMobile para el cifrado requiere que el usuario final introduzca un PIN para que se genere la clave de cifrado. Esta opción se denomina entropía de usuario. Pueden causar un problema relevante para las aplicaciones.

En concreto, no se puede acceder a ningún archivo o base de datos hasta que el usuario introduzca el PIN. Si hay una operación de E/S para acceder a ellos en una ubicación que se ejecuta antes de que aparezca la solicitud del PIN, esa operación siempre fallará. Este impedimento implica:

  • Debe mantener las operaciones de archivo y base de datos fuera del subproceso principal. Por ejemplo, nunca se podrá leer un archivo del método onCreate() del objeto de aplicación.
  • Las operaciones en segundo plano (como servicios o proveedores de contenido) se pueden ejecutar incluso aunque no haya actividad de las aplicaciones en sí. Estos componentes en segundo plano no pueden mostrar la solicitud de PIN y, por lo tanto, no pueden acceder a archivos ni bases de datos. Tenga en cuenta que, una vez que se ejecuta una actividad en la aplicación, las operaciones de segundo plano tiene permiso para realizar operaciones de E/S.

Existen varios mecanismos de fallo si la clave de cifrado no está disponible debido a la entropía de usuario:

  • Si el subproceso principal accede a una base de datos antes de que el PIN esté disponible, se cierra la aplicación.
  • Si no es el subproceso principal el que accede a la base de datos antes de que esté disponible el PIN, ese subproceso se bloquea hasta que se introduzca el PIN.
  • Cuando se trata de un acceso que no sea a la base de datos y se inicia antes de que el PIN esté disponible, la operación de apertura fallará. En el nivel C, se devuelve un error EACCES. En Java, se produce una excepción.

Para que este problema no se dé en la aplicación, realice pruebas con la entropía de usuario habilitada. La propiedad de cliente de XenMobile llamada “Encrypt secrets using Passcode” agrega la entropía de usuario. Configure dicha propiedad de cliente, que se encuentra inhabilitada de forma predeterminada. Para ello, desde la consola de XenMobile, vaya a Configurar > Parámetros > Más > Propiedades de cliente.

Redes y micro VPN

Se ofrecen varias opciones de directivas XenMobile a los administradores de red. La directiva “Acceso de red” impide, permite o redirige la actividad de red de la aplicación de este modo:

  • De forma predeterminada, la aplicación tiene completamente bloqueado el acceso a la red. Si la directiva “Acceso de red” se establece en Bloqueado, fallarán las API de red que utilice la aplicación. Como se dicta en la directriz anterior, debe poder gestionar correctamente dicho fallo.
  • Cuando la directiva “Acceso de red” se establece en Sin restricciones, todas las llamadas de red van directamente y no se canalizan.
  • Cuando la directiva “Acceso de red” se establece en Túnel a la red interna, todas las llamadas de red se canalizan a través de NetScaler Gateway. El túnel de esta directiva se controla con la directiva “Modo preferido de VPN”.

La directiva “Modo preferido de VPN” establece el modo inicial para las conexiones que dirigen el tráfico a la red interna:

  • Cuando la directiva “Modo preferido de VPN” se establece en Exploración segura, la URL de HTTP o HTTPS se reescribe. El modo “Exploración segura” solo puede dirigir el tráfico HTTP y HTTPS. El modo “Exploración segura” ofrece dos ventajas considerables: la autenticación PKINIT y el tipo de inicio de sesión Single Sign-On (SSO) para el tráfico HTTP y HTTPS. En Android, el modo “Exploración segura” no consume muchos recursos. Por lo tanto, es la opción preferida para operaciones del tipo exploración Web.
  • Cuando la directiva “Modo de VPN preferido” se establece en Túnel VPN completo, todo el tráfico proveniente de la aplicación administrada se canaliza a través de NetScaler Gateway. En Android, este modo ejecuta una VPN pata todo el dispositivo, pero su uso está restringido a solo las aplicaciones administradas.

Limitación: XenMobile no admite servidores de socket. Si se está ejecutando un servidor de socket dentro de la aplicación empaquetada, el tráfico de red dirigido al servidor de socket no se canaliza a través de NetScaler Gateway.

Respaldo para plataformas de desarrollo de aplicaciones móviles

Las plataformas de algunas aplicaciones presentan problemas de compatibilidad con XenMobile:

  • Con PhoneGap, el servicio de localización no se bloquea.
  • SQLCipher no funciona con cifrado porque usa la asignación de memoria. Una solución es no usar SQLCipher. Otra solución es excluir el archivo de base de datos del cifrado mediante una directiva de exclusiones de cifrado. Un administrador de XenMobile debe configurar la directiva desde la consola de XenMobile.

Sugerencias de depuración

Cuando depure una aplicación empaquetada, tenga en cuenta estos consejos.

  • Determine si el problema está presente en una versión no empaquetada de la aplicación. Si el problema ocurre cuando la aplicación no está empaquetada, utilice las técnicas habituales de depuración.
  • Compruebe si el problema se soluciona cuando desactiva determinadas directivas de XenMobile.
    • Así, puede localizar incompatibilidades. Inhabilitar una directiva significa que MDX deja de aplicar la restricción relacionada, lo que le permite probar las funciones como si la aplicación no se hubiera empaquetado.
    • Si inhabilitar una directiva resuelve el problema, puede que la aplicación no esté buscando correctamente si hay errores en las API asociadas.
  • Si no se ejecuta una aplicación que no se ha modificado pero se ha vuelto a firmar:
    1. Desinstale el contenido jar del APK con JAR:

      jar xvf {some.apk}

    2. Elimine la carpeta META-INF:

      rm -rf META-INF

    3. Vuelva a instalar el contenido jar en un nuevo APK con JAR:

      jar cvf {/tmp/new.apk} *

    4. Firme el nuevo APK con JARSIGNER:

      jarsigner -keystore {some.keystore} -storepass {keystorepassword} -keypass {keypassword} {/tmp/new.apk} {keyalias}

    5. Si la aplicación sigue sin ejecutarse, es que no puede empaquetar la aplicación con un certificado de firma diferente al utilizado por el APK de original.

  • Si no se ejecuta un APK descompilado o recompilado:
    1. Descompile y recompile con APKTOOL:

      apktool d {some.apk} -o {some.directory}

      apktool b {some.directory} -o {new.apk}

    2. Firme el APK con JARSIGNER, como se ha indicado anteriormente.

    3. Si la aplicación sigue sin ejecutarse, se trata de un fallo APKTOOL de terceros.

  • Si no funciona el empaquetado de aplicaciones:
    1. Compruebe si el problema se soluciona tras eliminar la plataforma APKTOOL y volver a empaquetar.
      • Mac o Linux: rm -rf ~/Library/apktool/framework
      • Windows: del /q /s C:\Users\{username}\apktool\framework
    2. Compare el APKTOOL que utiliza el programa de empaquetado con el que se utilizó para descompilar y recompilar en el paso anterior.
      • Si es la misma versión APKTOOL, el fallo proviene del programa de empaquetado.
      • Si se trata de otra versión de APKTOOL, puede que el APKTOOL integrado en la herramienta MDX Toolkit esté defectuoso.
        1. Desinstale el contenido jar de ManagedAppUtility.jar.
        2. Sobrescríbalo con el contenido de APKTOOL.jar que utilizó para empaquetar la aplicación en el paso anterior.
        3. Vuelva a instalar el contenido jar en un nuevo ManagedAppUtility.jar.
        4. Empaquete la aplicación para confirmar que el error se encuentra en el APKTOOL incrustado.
  • Ejecute la aplicación empaquetada y capture información de registro.
    1. Use grep para investigar lo que ocurre en la aplicación.

      Para realizar un seguimiento de las actividades de la aplicación: grep “MDX-Activity”

      Para realizar un seguimiento del bloqueo de la aplicación por parte de MDX: grep “MDX-Locked”

      Para ver ambos registros juntos: egrep “MDX-Act|MDX-Loc”

    2. Si se produce un error en que la aplicación no responde, extraiga los seguimientos ANR mediante ADB.

  • Si se produce un problema al interactuar con varias aplicaciones (como cuando se usa “Abrir en”):
    1. Compruebe que las directivas de cifrado y los parámetros del grupo de seguridad son los mismos entre las aplicaciones.
    2. Intente realizar la misma operación con otra aplicación. Es posible que se trate de fallo en una de las aplicaciones que se están probando.
    3. Capture los registros de todas las aplicaciones implicadas. Tenga en cuenta que Secure Hub puede combinar registros y enviarlos desde aplicaciones individuales. En la pantalla “Mis aplicaciones”, deslice el dedo a la derecha hacia la pantalla “Asistencia”. A continuación, haga clic en el botón de ayuda situado en la parte inferior de la pantalla.

Además de las herramientas mencionadas anteriormente, es posible que también pueda ayudarle:

  • AAPT para agregar información acerca de la aplicación.

    aapt dump badging {some.apk}

  • Comando DUMPSYS en el dispositivo.

    adb shell dumpsys 2>&1 | tee {dumpsys.out}

  • DEX2JAR para recompilar clases en pseudo-Java.

    dex2jar {some.apk}

    Convertir clases de aplicaciones empaquetadas de Dex dual:

    apktool d {some.apk} -o {some.dir}

    dex2jar {some.dir}/assets/secondary-1.dex

  • JD-GUI para ver código pseudo-Java.

  • BAKSMALI para descompilar clases de aplicaciones empaquetadas Dex dual.

    • Descompile el APK empaquetado:

      apktool d {some.apk} -o {some.dir}

    • Descompile las clases de aplicación que no se han descompilado con la llamada anterior:

      baksmali {some.dir}/assets/secondary-1.dex -o {some.dir}/smali