Android-使用DexClassLoader加载apk文件

Cra*_*nor 19 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);
Run Code Online (Sandbox Code Playgroud)

现在我已经安装了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.
Run Code Online (Sandbox Code Playgroud)

所以我在这里有点难过.此活动是在我试图运行的apk的清单中声明的​​.我无法在我的应用程序Manifest中声明它.有任何想法吗?

谢谢,克雷格

Pet*_*ego 11

尝试使用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
    }
Run Code Online (Sandbox Code Playgroud)


小智 7

虽然这个问题很老,但我会回答,因为我为自己找到了同样问题的答案.首先,我想强调一下,您的问题中明确要求是从设备上尚未安装的.apk加载类.因此,使用getPackageManager()调用包管理器并为其提供包路径将明显导致NameNotFoundException,因为设备上未安装包含该包的.apk.

因此,从未安装在设备上的.apk文件加载类的方法(即,只有.apk存储在SDCARD的目录中)是使用DexClassLoader,如下所示:

1-确保SD卡上的目录中有.apk文件.我在SDCARD的Download文件夹中使用了Offloadme.apk.

2-在AndroidManifest.xml中添加读取权限,以允许您的应用从清单中读取.

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
Run Code Online (Sandbox Code Playgroud)

3-使用以下定义来定义.apk的路径,apk中的类名以及要调用的该类中的方法名称:

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

4-使用DexClassLoader加载.apk并使用反射在SimpleCalculator类中调用add方法,如下所示:

    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();
    }
Run Code Online (Sandbox Code Playgroud)

请注意,在我的简单示例中,我使用从存储在SDCARD上的Offloadme.apk文件加载的SimpleCalculator类中可用的add方法添加了两个数字,并且我能够打印正确的答案,即11.