¿Es posible cargar dinámicamente una biblioteca en tiempo de ejecución desde una aplicación de Android?

Resuelto llullulluis asked hace 54 años • 7 respuestas

¿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 Classes o Methods 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.

llullulluis avatar Jan 01 '70 08:01 llullulluis
Aceptado

Lo siento, llego tarde y la pregunta ya tiene una respuesta aceptada, pero , 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 MyClassde 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 MyClassde esa manera:

  • crear unDexClassLoader

  • Úselo para extraer la clase MyClassde"/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 MyClasse invoca doSomething()la instancia creada.

Y funciona... Veo los rastros definidos en MyClassmi LogCat:

ingrese la descripción de la imagen aquí

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 ( Objectmoldes feos, Method.invoke()llamadas feas...), pero debe ser posible jugar con Interfaces 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
Shlublu avatar Jul 28 '2011 14:07 Shlublu

Técnicamente debería funcionar, pero ¿qué pasa con las reglas de Google? De: play.google.com/intl/en-GB/about/developer-content-policy-pr‌​int

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).

Marcin avatar Dec 07 '2017 10:12 Marcin

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.

Naresh avatar Jul 28 '2011 11:07 Naresh