我怎样才能从我的.apk文件打包的jar文件加载一个类?

我试图从我的.apk文件的/ assets目录中的jar文件加载一个接口的插件实现。 我能够实现这个功能的唯一方法是将jar文件解压到私有的外部存储,然后将该文件传递给DexClassLoader。

这是有效的,但为什么罐子必须存在于两个地方(.apk和私人外部存储)? DexClassLoader必须有一个文件路径作为它的参数。

有没有办法让它直接访问/ assets文件夹中的文件,以便我不必为外部存储使用已存在的额外副本?

以下是相关的代码片段:

// somewhere in my main Activity ...
  final File aExtractedDexFile = new File(getDir("dex", Context.MODE_PRIVATE),
                                  LIBRARY_DEX_JAR);
  extractDexTo(aExtractedDexFile);
  loadLibraryProvider(aExtractedDexFile);

/** Extract the jar file that contains the implementation class.dex and place in private storage */
private void extractDexTo(File tJarInternalStoragePath) {
  BufferedInputStream aJarInputStream = null;
  OutputStream aDexOutputStream = null;

  try {
    aJarInputStream = new BufferedInputStream(getAssets().open(LIBRARY_DEX_JAR));
    aJarOutputStream = new BufferedOutputStream(new FileOutputStream(tJarInternalStoragePath));
    byte[] buf = new byte[BUF_SIZE];
    int len;
    while ((len = aJarInputStream.read(buf, 0, BUF_SIZE)) > 0)
    {
      aJarOutputStream.write(buf, 0, len);
    }
    aJarOutputStream.close();
    aJarInputStream.close();
  } catch (IOException e) {
    if (aDexOutputStream != null) {
      try {
        aJarOutputStream.close();
      } catch (IOException ioe) {
        ioe.printStackTrace();
      }
    }

    if (aJarInputStream != null) {
      try {
        aJarInputStream.close();
      } catch (IOException ioe) {
        ioe.printStackTrace();
      }
    }
  }
}

/** Use DexClassLoader to load the classes from LibraryProvider */
private void loadLibraryProvider(File tFile) {
  // Internal storage where the DexClassLoader writes the optimized dex file to.
  final File aOptimizedDexOutputPath = getDir("outdex", Context.MODE_PRIVATE);

  // Initialize the class loader with the secondary dex file.
  DexClassLoader cl = new DexClassLoader(tFile.getAbsolutePath(),
          aOptimizedDexOutputPath.getAbsolutePath(),
          null,
          getClassLoader());
  Class<?> aLibProviderClazz = null;

  try {
    // Load the library class from the class loader.
    aLibProviderClazz = cl.loadClass(LIBRARY_PROVIDER_CLASS);      
    sLibraryProvider = (LibraryInterface) aLibProviderClazz.newInstance();
  } catch (Exception exception) {
    // Handle exception gracefully here.
    exception.printStackTrace();
  }
}

有没有办法让它直接访问/ assets文件夹中的文件,以便我不必为外部存储使用已存在的额外副本?

答案是否定的。我想你会按照官方来源发布的这个博客来实现你的代码。 如果有更好的办法,那么这个大个子应该在他的博客中推荐它。

API中解释了为什么您需要optimizeDirectory的原因:

这个类加载器需要一个应用程序专用的可写目录来缓存优化的类。

另请注意,资产目录在apk中不可写,所以无法使用纯资产目录来完成。

在博客中提到需要复制jar文件的原因有点微妙:

首先,它必须被复制到其路径可以提供给类加载器的存储位置。

嵌入在apk压缩文件中的所有内容(文件夹/文件)在运行时不可暴露(或可解释)为底层文件系统。 换句话说, DexClassLoader和PathClassLoader构造函数中所需的dexPath需要一个像/data/data/com.example/dex/common-lib.jar这样的固定路径字符串,它表示文件系统中的文件。

链接地址: http://www.djcxy.com/p/10723.html

上一篇: How can I load a class from a jar file packaged in my .apk file?

下一篇: What is the TREC format?