2010-05-25 26 views
17

我打了一下牆。任何幫助,將不勝感激。我有一個應用程序,我想使用DexClassLoader加載另一個apk文件。Android-使用DexClassLoader加載apk文件

這裏是我的代碼:

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

現在我已經安裝了test.apk所以,當我跑在上面的代碼 工作的罰款和啓動的應用程序。不過,我希望能夠在未安裝test.apk的情況下運行此操作(因爲 會打敗應用程序的整個點)。所以我卸載它, 當我跑我的應用程序,我再次得到這個錯誤:

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

所以我有點難倒這裏。此活動在我試圖運行的apk的Manifest 中聲明。我無法在我的應用程序 Manifest中聲明它。有任何想法嗎?

謝謝, 克雷格

回答

-5

你不能做到這一點。即使你能夠從外部文件訪問類,Android仍然不知道它們。而且你不直接運行活動,而是通過請求Android來運行它們,所以它們必須被註冊/安裝到系統中。

10

嘗試使用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

雖然問題是老了,我會回答,因爲我掙扎了一下,找到您爲自己同樣的問題一個明確的答案。首先,我想強調一下,在你的問題中一個明確的要求是從尚未安裝在設備上的.apk中加載一個類。因此,使用getPackageManager()調用包管理器併爲其提供包路徑將明顯導致NameNotFoundException,因爲包含該包的.apk未安裝在設備上。

所以,去加載類由未安裝在設備上的的apk文件的方式(即你只需要存儲在你的SD卡目錄.apk文件)是使用DexClassLoader如下:

1-確保在SDCARD上的目錄中有.apk文件。我的SD卡上的下載文件夾中有我的Offloadme.apk

2-在您的AndroidManifest.xml中添加讀取權限,以允許您的應用從清單中讀取。

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

3-使用以下定義來定義.apk文件在這一類,你想調用路徑,則APK裏面的類名和方法名稱:

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

4 - 使用DexClassLoader加載。APK並調用SimpleCalculator類使用反射添加方法如下:

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(); 
    } 

注意,在我的簡單的例子,我加用增加可用方法在SimpleCalculator類兩個數字從加載Offloadme.apk文件存儲在我的SDCARD,我能夠打印正確答案是11.