我试图从我的.apk文件的/ assets目录中的jar文件加载接口的插件实现.我能够让它工作的唯一方法是将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);
和
- /** 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,BUF_SIZE)) > 0)
- {
- aJarOutputStream.write(buf,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文件夹中的文件,这样我就不必使用外部存储来获取已存在的文件的额外副本?
答案是否定的.我想您遵循this blog posted by official source实施您的代码.如果有更好的做事方式,那么bloger应该在他的博客中推荐它.
您需要optimizeDirectory的原因在in the API中解释:
This class loader requires an application-private,writable directory to cache optimized classes.
另请注意,资产目录在apk中不可写,因此无法使用纯资产目录.
First,it has to be copied to a storage location whose path can be supplied to the class loader.
嵌入在apk归档中的所有内容(文件夹/文件)在运行时无法公开(或可解释)到底层文件系统.换句话说,DexClassLoader和PathClassLoader构造函数中所需的dexPath需要一个实体路径字符串,如/data/data/com.example/dex/common-lib.jar,它表示文件系统中的文件.