【问题标题】:Android- Using DexClassLoader to load apk fileAndroid- 使用 DexClassLoader 加载 apk 文件
【发布时间】:2010-05-25 09:02:01
【问题描述】:

我有点碰壁了。任何帮助,将不胜感激。我有一个应用程序,我想使用 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.

所以我在这里有点难过。此活动在 Manifest 中声明 我正在尝试运行的 apk。我不能在我的应用程序中声明它 显现。有什么想法吗?

谢谢, 克雷格

【问题讨论】:

    标签: android


    【解决方案1】:

    尝试使用安卓的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
        }
    

    【讨论】:

      【解决方案2】:

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

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

      1- 确保您的 SDCARD 目录中有 .apk 文件。我的 Offloadme.apk 在我的 SDCARD 的下载文件夹中。

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

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

      【讨论】:

      • 我可以使用这个启动其他 apk 的活动吗?
      【解决方案3】:

      你不能那样做。即使您能够从外部文件访问类,Android 仍然不知道它们。而且您不直接运行活动,而是通过请求 Android 运行它们,因此必须将它们注册/安装到系统中。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-01-17
        • 1970-01-01
        • 1970-01-01
        • 2017-11-22
        相关资源
        最近更新 更多