【发布时间】:2012-05-13 10:53:54
【问题描述】:
我正在尝试从 .apk 文件的 /assets 目录中的 jar 文件加载接口的插件实现。我能够让它工作的唯一方法是将 jar 文件提取到私有外部存储,然后将该文件传递给 DexClassLoader。
这行得通,但为什么 jar 必须存在于两个地方(.apk 和私有外部存储)? DexClassLoader 必须有一个文件路径作为它的参数。
有没有办法为其提供指向 /assets 文件夹中文件的直接路径,这样我就不必用完外部存储来获取已经存在的文件的额外副本?
以下是相关代码sn-ps:
// 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();
}
}
【问题讨论】:
-
这可能是个愚蠢的问题,但为什么要将 Jar 打包在 assets/ 而不是 libs/ 中,因为它可以作为应用程序构建路径的一部分直接引用?
-
这需要很多上下文来解释,但我能给出的最短答案是我提供了一个其他人会使用的框架。他们的贡献将被编译成 jars,这些 jars 将与框架一起打包以形成一个完整的应用程序。该框架将有一个接口在运行时从 jar 中加载模块。
-
你试过
file:///android_asset/...吗?另外,请考虑以下讨论:stackoverflow.com/questions/4789325/…stackoverflow.com/questions/4820816/… -
@ArunWarrier 上面的解决方案是正确的方法。请参阅下面的答案。您必须先将 jar 文件提取到一个目录中,然后再将其交给类加载器。
-
@AndEngine 是的,完全正确。
标签: android classloader assets