.apk ファイルの /assets ディレクトリにある jar ファイルからインターフェイスのプラグイン実装をロードしようとしています。これを機能させる唯一の方法は、jar ファイルをプライベート外部ストレージに抽出し、そのファイルを DexClassLoader に渡すことです。
それは機能しますが、jar が 2 つの場所 (.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();
}
}