2010-03-25 9 views
16

Estoy tratando de hacer algo similar a este stackoverflow posting. Lo que quiero hacer es leer la definición de una actividad o servicio de la tarjeta SD. Para evitar problemas de permiso manifiesto, creo una versión de shell de esta actividad en .apk, pero intento reemplazarla con una actividad del mismo nombre que reside en la tarjeta SD en tiempo de ejecución. Desafortunadamente, puedo cargar la definición de clase de actividad de la tarjeta SD usando DexClassLoader, pero la definición de clase original es la que se ejecuta. ¿Hay alguna forma de especificar que la nueva definición de clase sustituya a la anterior o cualquier sugerencia sobre cómo evitar los problemas de permiso manifiesto sin proporcionar realmente la actividad necesaria en el paquete? El ejemplo de código:Android, cómo usar DexClassLoader para reemplazar dinámicamente una actividad o servicio

ClassLoader cl = new DexClassLoader("/sdcard/mypath/My.apk", 
      getFilesDir().getAbsolutePath(), 
      null, 
      MainActivity.class.getClassLoader()); 

    try { 
     Class<?> c = cl.loadClass("com.android.my.path.to.a.loaded.activity"); 
     Intent i = new Intent(getBaseContext(), c); 
     startActivity(i); 
    } 
    catch (Exception e) { 

Intead de poner en marcha el com.android.my.path.to.a.loaded.activity especificado en /sdcard/mypath/My.apk, se pone en marcha la actividad estáticamente cargado en el proyecto.

+0

Tengo la sensación de que esto no se puede hacer simplemente por la forma en que Android maneja los activos. Si llama a startActivity en una clase en otra aplicación, debería cargar el hilo de esa aplicación que no sea el suyo y, por lo tanto, simplemente una alternativa peligrosa a las Intenciones de Android. – Tom

Respuesta

13

Iniciar una actividad a través de DexClassLoader será muy complicado, ya que no instaló el APK, por lo que no hay nada para manejar su intención.

Debería tener la misma clase de actividad en su plataforma APK y declararla en AndroidManifest.xml. Luego, debe cambiar el ClassLoader actual a su DexClassLoader deseado. Como resultado, iniciará su complemento APK. (Nota: "plataforma APK" se refiere a la aplicación que ya está instalada en el teléfono, mientras que "complemento APK" hace referencia al archivo apk guardado en su tarjeta SD).

La aplicación de la plataforma debe verse más o menos así:

public static ClassLoader ORIGINAL_LOADER; 
public static ClassLoader CUSTOM_LOADER = null; 

@Override 
public void onCreate() { 
    super.onCreate(); 
    try { 
     Context mBase = new Smith<Context>(this, "mBase").get(); 

     Object mPackageInfo = new Smith<Object>(mBase, "mPackageInfo") 
       .get(); 
     //get Application classLoader 
     Smith<ClassLoader> sClassLoader = new Smith<ClassLoader>(
       mPackageInfo, "mClassLoader"); 
     ClassLoader mClassLoader = sClassLoader.get(); 
     ORIGINAL_LOADER = mClassLoader; 

     MyClassLoader cl = new MyClassLoader(mClassLoader); 
     //chage current classLoader to MyClassLoader 
     sClassLoader.set(cl); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 

class MyClassLoader extends ClassLoader { 
    public MyClassLoader(ClassLoader parent) { 
     super(parent); 
    } 

    @Override 
    public Class<?> loadClass(String className) 
      throws ClassNotFoundException { 
     if (CUSTOM_LOADER != null) { 
      try { 
       Class<?> c = CUSTOM_LOADER.loadClass(className); 
       if (c != null) 
        return c; 
      } catch (ClassNotFoundException e) { 
      } 
     } 
     return super.loadClass(className); 
    } 
} 

para más código, se puede visitar https://github.com/Rookery/AndroidDynamicLoader

estoy leyendo el código fuente de Android con el fin de encontrar un método más elegante para implementar esta característica. Si tienes alguna idea, no dudes en contactarme.

+0

Tu respuesta es increíble +1 por eso. Esto hace que mi día. – Krypton

+0

¡¡excelente respuesta !! el enlace me ayudó mucho. – qiuping345

+1

Es mejor si explicas la clase Smith aquí. –

Cuestiones relacionadas