2010-05-25 10 views
17

He golpeado un poco de una pared. Cualquier ayuda sería apreciada. Tengo una aplicación que quiero usar DexClassLoader para cargar otro archivo apk.Android- Usando DexClassLoader para cargar el archivo apk

Aquí está mi código:

DexClassLoader dLoader = new DexClassLoader("/sdcard/download/test.apk","/sdcard/download",null,ClassLoader.getSystemClassLoader().getParent()); 
Class calledClass = dLoader.loadClass("com.test.classname"); 
Intent it=new Intent(this, calledClass); 
it.setClassName("com.test", "com.test.classname"); 
startActivity(it); 

Ahora ya se habían instalado test.apk así que cuando me encontré con el código anterior se funcionaba bien y lanza la aplicación. Sin embargo, quiero poder ejecutar esto sin que test.apk esté instalado ya (ya que eso sería derrotar el punto entero de la aplicación). Así que he desinstalado y cuando me encontré con la aplicación de nuevo a mi me sale este error:

android.content.ActivityNotFoundException: Unable to find explicit 
activity class {com.test/com.test.classname}; have you declared this 
activity in your AndroidManifest.xml. 

así que estoy un poco perplejo aquí. Esta actividad se declara en el Manifiesto de la apk que intento ejecutar. No puedo declararlo en mis aplicaciones Manifiesto. ¿Algunas ideas?

Gracias, Craig

Respuesta

-5

No se puede hacer eso. Incluso si puede acceder a las clases desde un archivo externo, Android aún no las conoce. Y no ejecuta actividades directamente, sino solicitando a Android que las ejecute, por lo que deben registrarse/instalarse en el sistema.

10

Intente utilizar de Android PathClassLoader:

String packagePath = "com.mypackage"; 
    String classPath = "com.mypackage.ExternalClass"; 

    String apkName = null; 
    try { 
     apkName = getPackageManager().getApplicationInfo(packagePath,0).sourceDir; 
    } catch (PackageManager.NameNotFoundException e) { 
     // catch this 
    } 

    // add path to apk that contains classes you wish to load 
    String extraApkPath = apkName + ":/path/to/extraLib.apk" 

    PathClassLoader pathClassLoader = new dalvik.system.PathClassLoader(
      apkName, 
      ClassLoader.getSystemClassLoader()); 

    try { 
     Class<?> handler = Class.forName(classPath, true, pathClassLoader); 
    } catch (ClassNotFoundException e) { 
     // catch this 
    } 
7

Aunque la pregunta es viejo, voy a responder porque me ha costado un poco para encontrar una respuesta clara para su misma pregunta para mí. En primer lugar, me gustaría resaltar que un requisito claro en su pregunta es cargar una clase desde una .apk que no esté ya instalada en el dispositivo. Por lo tanto, llamar al gestor de paquetes utilizando getPackageManager() y proporcionarle la ruta del paquete conducirá claramente a NameNotFoundException porque el .apk que tiene el paquete no está instalado en el dispositivo.

Por lo tanto, el camino a seguir acerca de las clases de carga desde un archivo .apk que no está instalado en el dispositivo (es decir, es suficiente con el apk almacenada en un directorio en su sdcard) es mediante el uso DexClassLoader de la siguiente manera:

1- Asegúrese de tener el archivo .apk en un directorio en su SDCARD. Tengo el mío Offloadme.apk en la carpeta de descarga en mi SDCARD.

2- Agregue permiso de lectura en su AndroidManifest.xml para permitir que su aplicación lea del manifiesto.

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> 

3- utilizar las siguientes definiciones para definir la ruta de la apk, el nombre de clase dentro de la apk, y el nombre del método en el que la clase que desea invocar:

final String apkFile =Environment.getExternalStorageDirectory().getAbsolutePath()+"/Download/Offloadme.apk"; 
String className = "com.khaledalanezi.offloadme.SimpleCalculator"; 
String methodToInvoke = "add"; 

4 - Use DexClassLoader para cargar el archivo.apk y llamar a la añadir método en el SimpleCalculator clase mediante la reflexión de la siguiente manera:

final File optimizedDexOutputPath = getDir("outdex", 0); 

    DexClassLoader dLoader = new DexClassLoader(apkFile,optimizedDexOutputPath.getAbsolutePath(), 
      null,ClassLoader.getSystemClassLoader().getParent()); 

    try { 
     Class<?> loadedClass = dLoader.loadClass(className); 
     Object obj = (Object)loadedClass.newInstance(); 
     int x =5; 
     int y=6; 
     Method m = loadedClass.getMethod(methodToInvoke, int.class, int.class); 
     int z = (Integer) m.invoke(obj, y, x);    
     System.out.println("The sum of "+x+" and "+"y="+z); 

    } catch (ClassNotFoundException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } catch (InstantiationException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } catch (IllegalAccessException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } catch (NoSuchMethodException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } catch (IllegalArgumentException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } catch (InvocationTargetException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 

Tenga en cuenta que en mi ejemplo sencillo, añadí dos números usando el añadir método disponible en el clase SimpleCalculator cargado desde el Offloadme.apk archivo almacenado en mi SDCARD y pude imprimir la respuesta correcta que es 11.

Cuestiones relacionadas