diff --git a/library/src/main/java/com/orm/util/MultiDexHelper.java b/library/src/main/java/com/orm/util/MultiDexHelper.java new file mode 100644 index 00000000..37b57894 --- /dev/null +++ b/library/src/main/java/com/orm/util/MultiDexHelper.java @@ -0,0 +1,106 @@ +package com.orm.util; + +import android.content.Context; +import android.content.SharedPreferences; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.os.Build; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; + +import dalvik.system.DexFile; + +/** + * Created by xudshen@hotmail.com on 14/11/13. + */ + +//http://stackoverflow.com/a/26892658 +public class MultiDexHelper { + private static final String EXTRACTED_NAME_EXT = ".classes"; + private static final String EXTRACTED_SUFFIX = ".zip"; + + private static final String SECONDARY_FOLDER_NAME = "code_cache" + File.separator + + "secondary-dexes"; + + private static final String PREFS_FILE = "multidex.version"; + private static final String KEY_DEX_NUMBER = "dex.number"; + + private static SharedPreferences getMultiDexPreferences(Context context) { + return context.getSharedPreferences(PREFS_FILE, + Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB + ? Context.MODE_PRIVATE + : Context.MODE_PRIVATE | Context.MODE_MULTI_PROCESS); + } + + /** + * get all the dex path + * + * @param context the application context + * @return all the dex path + * @throws PackageManager.NameNotFoundException + * @throws IOException + */ + public static List getSourcePaths(Context context) throws PackageManager.NameNotFoundException, IOException { + ApplicationInfo applicationInfo = context.getPackageManager().getApplicationInfo(context.getPackageName(), 0); + File sourceApk = new File(applicationInfo.sourceDir); + File dexDir = new File(applicationInfo.dataDir, SECONDARY_FOLDER_NAME); + + List sourcePaths = new ArrayList(); + sourcePaths.add(applicationInfo.sourceDir); //add the default apk path + + //the prefix of extracted file, ie: test.classes + String extractedFilePrefix = sourceApk.getName() + EXTRACTED_NAME_EXT; + //the total dex numbers + int totalDexNumber = getMultiDexPreferences(context).getInt(KEY_DEX_NUMBER, 1); + + for (int secondaryNumber = 2; secondaryNumber <= totalDexNumber; secondaryNumber++) { + //for each dex file, ie: test.classes2.zip, test.classes3.zip... + String fileName = extractedFilePrefix + secondaryNumber + EXTRACTED_SUFFIX; + File extractedFile = new File(dexDir, fileName); + if (extractedFile.isFile()) { + sourcePaths.add(extractedFile.getAbsolutePath()); + //we ignore the verify zip part + } else { + throw new IOException("Missing extracted secondary dex file '" + + extractedFile.getPath() + "'"); + } + } + + return sourcePaths; + } + + /** + * get all the classes name in "classes.dex", "classes2.dex", .... + * + * @param context the application context + * @return all the classes name + * @throws PackageManager.NameNotFoundException + * @throws IOException + */ + public static List getAllClasses(Context context) throws PackageManager.NameNotFoundException, IOException { + List classNames = new ArrayList(); + for (String path : getSourcePaths(context)) { + try { + DexFile dexfile = null; + if (path.endsWith(EXTRACTED_SUFFIX)) { + //NOT use new DexFile(path), because it will throw "permission error in /data/dalvik-cache" + dexfile = DexFile.loadDex(path, path + ".tmp", 0); + } else { + dexfile = new DexFile(path); + } + Enumeration dexEntries = dexfile.entries(); + while (dexEntries.hasMoreElements()) { + classNames.add(dexEntries.nextElement()); + } + } catch (IOException e) { + throw new IOException("Error at loading dex file '" + + path + "'"); + } + } + return classNames; + } +} \ No newline at end of file diff --git a/library/src/main/java/com/orm/util/ReflectionUtil.java b/library/src/main/java/com/orm/util/ReflectionUtil.java index a740b42d..e6e2dd38 100644 --- a/library/src/main/java/com/orm/util/ReflectionUtil.java +++ b/library/src/main/java/com/orm/util/ReflectionUtil.java @@ -289,15 +289,11 @@ private static Class getDomainClass(String className, Context context) { private static List getAllClasses(Context context) throws PackageManager.NameNotFoundException, IOException { String packageName = ManifestHelper.getDomainPackageName(context); - String path = getSourcePath(context); List classNames = new ArrayList(); - DexFile dexfile = null; try { - dexfile = new DexFile(path); - Enumeration dexEntries = dexfile.entries(); - while (dexEntries.hasMoreElements()) { - String className = dexEntries.nextElement(); - if (className.startsWith(packageName)) classNames.add(className); + List allClasses = MultiDexHelper.getAllClasses(context); + for (String classString : allClasses) { + if (classString.startsWith(packageName)) classNames.add(classString); } } catch (NullPointerException e) { ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); @@ -316,7 +312,7 @@ private static List getAllClasses(Context context) throws PackageManager } } } finally { - if (null != dexfile) dexfile.close(); +// if (null != dexfile) dexfile.close(); } return classNames; }