Cómo construir un APK y separar bibliotecas que la aplicación carga dinámicamente

El breve resumen es: ¿Cómo puedo construir un APK y bibliotecas separadas (por lo que me refiero a conjuntos de clases (e idealmente, recursos también) de alguna forma, como archivos JAR, AAR o DEX), pero no incluyen esas bibliotecas en el APK; En su lugar, la aplicación los carga en tiempo de ejecución?

Detalle

Así que mi pregunta principal es cómo construir tal aplicación (por ejemplo, la configuración de Gradle). ¿Cómo puedo especificar qué clases van a qué archivos JAR o DEX? ¿Creo un módulo de Android Studio para cada archivo DEX con el que quiero terminar?

Una pregunta muy relacionada es cómo el código Java debería cargar las bibliotecas externas y acceder a sus clases en tiempo de ejecución. Para el último, tengo la esperanza de que el enfoque mostrado en el acceso a las clases de aplicación de dex file por classloader funcionaría.

He intentado las instrucciones en https://developer.android.com/studio/projects/android-library.html , pero eso construye un APK que incluye la biblioteca de la dependencia.

También he intentado Multidex ( https://developer.android.com/studio/build/multidex.html ), pero eso no parece dejar al desarrollador ningún control sobre qué clases van en qué archivo DEX, y además, Los empaqueta todos en un solo APK. AFAICT no hay manera de controlar la carga de estos archivos DEX en tiempo de ejecución.

Fondo

Hay una posibilidad del " problema XY " aquí, así que es mejor que explique el fondo.

Estoy creando una aplicación para un cliente. No se distribuirá a través de una tienda de aplicaciones, por lo que no tendrá acceso al mecanismo normal de actualizaciones. En su lugar, el cliente quiere que la aplicación pueda actualizarse descargando nuevos componentes de sí misma para reemplazar los componentes antiguos, sin necesidad de cargar manualmente un nuevo APK. El motivo principal aquí es que las actualizaciones tienen que ser fáciles para los usuarios no técnicos. Si la aplicación puede controlar el proceso de actualización, puede hacerlo suave y guiar al usuario.

Además, la aplicación se utilizará en áreas donde el acceso a Internet es escaso y costoso, por lo que el cliente desea publicar actualizaciones de aplicaciones en trozos más pequeños (por ejemplo, 2 MB) en lugar de forzar al usuario a volver a descargar la aplicación completa para recibir una Pequeña actualización.

Un aspecto de los requisitos que debo mencionar, en caso de que importe, es que las bibliotecas que se cargan en tiempo de ejecución se supone que viven en una tarjeta microSD. Esto también puede ayudar con la distribución de actualizaciones sin acceso a Internet.

El estado actual de la aplicación es que se escribe alrededor del 50%. Es decir, se han publicado un par de versiones anteriores, pero ahora la aplicación debe modificarse (reestructurada) para satisfacer los requisitos anteriores, así como otros.

Este tutorial es un buen comienzo para la carga externa de archivos DEX. Sólo tres pequeños archivos de origen (MainActivity.java, LibraryInterface.java, LibraryProvider.java) y copia secondary_dex.jar de la carpeta assets, en el almacenamiento de aplicaciones internas [outdex / dex] (Internet también se indica como posible en el tutorial ). Tienes que construirlo con ant , porque utiliza pasos de construcción personalizados. Lo intenté, funciona bien. Digno de una mirada.
Carga de clase personalizada en Dalvik y ART

ACTUALIZAR este código ha sido portado a Android Studio gradle (no hay necesidad de hormiga). https://github.com/timrae/custom-class-loader
Probado bien . Copia com.example.toastlib.jar de la tarjeta SD en el almacenamiento interno de la aplicación [outdex / dex], (no carpeta de activos). (Debe leer el archivo README.md del proyecto para crearlo ).

P: ¿Cómo puedo agregar una actividad, no puedo agregarla al manifiesto?
R: Utilice Fragmentos, no necesitan entradas en el manifiesto.

P: Un frasco con recursos que se pretende añadir a un proyecto existente necesita poder combinar sus recursos con los recursos propios del proyecto (R.).
A: Hacks están disponibles, archivo de datos …
Empaquetado de archivos de recursos de Android dentro de un archivo Jar distribuible

P: El archivo externo tiene permisos incorrectos.
R: Importarla.

P: Necesito agregar permisos de uso.
R: Utilice API23 puede agregar permisos de uso mediante programación (pero todavía deben declararse en el manifiesto, por lo que el nuevo modelo de permisos probablemente no nos sirva mucho).

Esta sección es para usuarios más generales (@LarsH tiene requisitos más específicos sobre las actualizaciones), El ejemplo anterior es 17kb apk y 1 kb jar. Podrías poner la mayor parte de tu código en el frasco único, y las actualizaciones implicarían simplemente cargar un nuevo Apk (y luego importar el frasco de código masivo, para minimizar la transferencia de datos). Cuando el Apk se vuelve demasiado grande, comienza de nuevo con un pequeño Apk y todo migró a otro tarro (import 2 jar's). Es necesario equilibrar el esfuerzo de codificación, la experiencia del usuario, la facilidad de mantenimiento, la capacidad de soporte, el ancho de banda, las reglas de android, las reglas de juego de la tienda (si estas palabras existen, O)).

NOTA Dalvik se interrumpe

El sucesor de Dalvik es Android Runtime (ART), que utiliza los mismos archivos bytecode y .dex (pero no archivos .odex), con la sucesión con el objetivo de mejorar el rendimiento transparente para los usuarios finales. El nuevo entorno de ejecución se incluyó por primera vez en Android 4.4 "KitKat" como una vista previa de la tecnología, y sustituyó a Dalvik por completo en versiones posteriores; Android 5.0 "Lollipop" es la primera versión en la que ART es el único tiempo de ejecución incluido.

Usted podría intentar construir múltiples apk con el mismo sharedUserId y el mismo proceso .

Este es el mecanismo de complemento utilizado por Threema

Edit: Más sobre Theema

Threema tiene una aplicación principal y dos complementos:

De este modo, la aplicación principal no necesita permisos para acceder a la cámara o al micrófono

  • ¿hay alguna manera de configurar gradle para comprobar la ortografía en strings.xml?
  • Gradle release build con proguard: java.lang.IncompatibleClassChangeError y java.lang.NoSuchMethodError
  • "La configuración de firma se debe especificar en los scripts de compilación de Gradle" ... lo hice
  • Android Studio: instala la aplicación de lanzamiento por línea de comandos
  • Publica la biblioteca de android en jcenter: gradle bintrayUpload no encuentra bibliotecas
  • Multi sabor app basado en la biblioteca de múltiples sabores en Android Gradle
  • Cómo realizar una prueba de unidad
  • Google GCM Android bloquea (java.lang.NoClassDefFoundError: com.google.android.gms.R $ cadena)
  • Mi R en la biblioteca es rojo, pero puedo crear y ejecutar la aplicación normalmente
  • IncompatibleClassChangeError después de actualizar a Android Build Tools 25.1.6 GCM / FCM
  • Error de aserción en Android Studio al intentar compilar el proyecto de trabajo
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.