Chu*_*ger 7 android assets classloader
我正在尝试从jar文件加载一个接口的插件实现,该文件位于我的.apk文件的/ assets目录中.我能够让它工作的唯一方法是将jar文件解压缩到私有外部存储器,然后将该文件传递给DexClassLoader.
这有效,但为什么jar必须存在于两个地方(.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);
Run Code Online (Sandbox Code Playgroud)
和
/** 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();
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
和
/** 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();
}
}
Run Code Online (Sandbox Code Playgroud)
答案是否定的。我想您按照官方来源发布的博客实现您的代码。如果有更好的做法,博主应该在他的博客中推荐。
API 中解释了您需要optimizationDirectory的原因:
该类加载器需要一个应用程序私有的可写目录来缓存优化的类。
另请注意,资产目录在 apk 中是不可写的,因此不能仅使用资产目录来完成。
需要复制 jar 文件的原因有点微妙,在博客中提到:
首先,必须将其复制到可以将其路径提供给类加载器的存储位置。
apk 存档中嵌入的所有内容(文件夹/文件)在运行时都无法向底层文件系统公开(或可解释)。换句话说,DexClassLoader 和 PathClassLoader 的构造函数中所需的dexPath/data/data/com.example/dex/common-lib.jar都需要一个固定的路径字符串,就像代表文件系统中的文件一样。
| 归档时间: |
|
| 查看次数: |
3351 次 |
| 最近记录: |