¿Es posible cargar dinámicamente una biblioteca en tiempo de ejecución desde una aplicación de Android?
¿Hay alguna forma de crear una aplicación de Android para descargar y usar una biblioteca Java en tiempo de ejecución?
Aquí hay un ejemplo:
Imagine que la aplicación necesita realizar algunos cálculos en función de los valores de entrada. La aplicación solicita estos valores de entrada y luego verifica si los Classe
s o Method
s requeridos están disponibles.
De lo contrario, se conecta a un servidor, descarga la biblioteca necesaria y la carga en tiempo de ejecución para llamar a los métodos requeridos utilizando técnicas de reflexión. La implementación podría cambiar dependiendo de varios criterios, como el usuario que descarga la biblioteca.
Lo siento, llego tarde y la pregunta ya tiene una respuesta aceptada, pero sí , puedes descargar y ejecutar bibliotecas externas. Así es como lo hice:
Me preguntaba si esto era factible, así que escribí la siguiente clase:
package org.shlublu.android.sandbox;
import android.util.Log;
public class MyClass {
public MyClass() {
Log.d(MyClass.class.getName(), "MyClass: constructor called.");
}
public void doSomething() {
Log.d(MyClass.class.getName(), "MyClass: doSomething() called.");
}
}
Y lo empaqueté en un archivo DEX que guardé en la tarjeta SD de mi dispositivo como /sdcard/shlublu.jar
.
Luego escribí el "programa estúpido" a continuación, después de haberlo eliminado MyClass
de mi proyecto Eclipse y limpiado:
public class Main extends Activity {
@SuppressWarnings("unchecked")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
try {
final String libPath = Environment.getExternalStorageDirectory() + "/shlublu.jar";
final File tmpDir = getDir("dex", 0);
final DexClassLoader classloader = new DexClassLoader(libPath, tmpDir.getAbsolutePath(), null, this.getClass().getClassLoader());
final Class<Object> classToLoad = (Class<Object>) classloader.loadClass("org.shlublu.android.sandbox.MyClass");
final Object myInstance = classToLoad.newInstance();
final Method doSomething = classToLoad.getMethod("doSomething");
doSomething.invoke(myInstance);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Básicamente carga la clase MyClass
de esa manera:
crear un
DexClassLoader
Úselo para extraer la clase
MyClass
de"/sdcard/shlublu.jar"
y almacene esta clase en el
"dex"
directorio privado de la aplicación (almacenamiento interno del teléfono).
Luego, crea una instancia MyClass
e invoca doSomething()
la instancia creada.
Y funciona... Veo los rastros definidos en MyClass
mi LogCat:
Lo probé tanto en un emulador 2.1 como en mi teléfono celular HTC físico (que ejecuta Android 2.2 y NO está rooteado).
Esto significa que puede crear archivos DEX externos para que la aplicación los descargue y ejecute. Aquí se hizo de la manera más difícil ( Object
moldes feos, Method.invoke()
llamadas feas...), pero debe ser posible jugar con Interface
s para hacer algo más limpio.
Guau. Soy el primero en sorprenderme. Esperaba un SecurityException
.
Algunos datos para ayudar a investigar más:
- Mi DEX shlublu.jar estaba firmado, pero no mi aplicación
- Mi aplicación se ejecutó desde una conexión Eclipse/USB. Entonces este es un APK sin firmar compilado en modo DEBUG
Técnicamente debería funcionar, pero ¿qué pasa con las reglas de Google? De: play.google.com/intl/en-GB/about/developer-content-policy-print
Una aplicación distribuida a través de Google Play no puede modificarse, reemplazarse ni actualizarse mediante ningún método que no sea el mecanismo de actualización de Google Play. Del mismo modo, una aplicación no puede descargar código ejecutable (por ejemplo, archivos dex, JAR, .so) de una fuente que no sea Google Play. Esta restricción no se aplica al código que se ejecuta en una máquina virtual y tiene acceso limitado a las API de Android (como JavaScript en un WebView o un navegador).
No estoy seguro de poder lograr esto cargando dinámicamente código Java. Quizás pueda intentar incorporar un motor de secuencias de comandos en su código, como rhino, que puede ejecutar secuencias de comandos Java que se pueden descargar y actualizar dinámicamente.