2010-05-25 80 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.