diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/Androlib.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/Androlib.java index 151f9786..b646a2f6 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/Androlib.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/Androlib.java @@ -32,6 +32,10 @@ import brut.androlib.src.SmaliDecoder; import brut.common.BrutException; import brut.directory.*; import brut.util.*; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.FilenameUtils; +import org.jf.dexlib2.iface.DexFile; + import java.io.*; import java.util.*; import java.util.logging.Logger; @@ -41,25 +45,21 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import java.util.zip.ZipOutputStream; -import org.apache.commons.io.FileUtils; -import org.apache.commons.io.FilenameUtils; - public class Androlib { private final AndrolibResources mAndRes = new AndrolibResources(); protected final ResUnknownFiles mResUnknownFiles = new ResUnknownFiles(); public ApkOptions apkOptions; private int mMinSdkVersion = 0; + public Androlib() { + this(new ApkOptions()); + } + public Androlib(ApkOptions apkOptions) { this.apkOptions = apkOptions; mAndRes.apkOptions = apkOptions; } - public Androlib() { - this.apkOptions = new ApkOptions(); - mAndRes.apkOptions = this.apkOptions; - } - public ResTable getResTable(ExtFile apkFile) throws AndrolibException { return mAndRes.getResTable(apkFile, true); @@ -70,6 +70,10 @@ public class Androlib { return mAndRes.getResTable(apkFile, loadMainPkg); } + public int getMinSdkVersion() { + return mMinSdkVersion; + } + public void decodeSourcesRaw(ExtFile apkFile, File outDir, String filename) throws AndrolibException { try { @@ -92,7 +96,11 @@ public class Androlib { OS.rmdir(smaliDir); smaliDir.mkdirs(); LOGGER.info("Baksmaling " + filename + "..."); - SmaliDecoder.decode(apkFile, smaliDir, filename, bakDeb, apiLevel); + DexFile dexFile = SmaliDecoder.decode(apkFile, smaliDir, filename, bakDeb, apiLevel); + int minSdkVersion = dexFile.getOpcodes().api; + if (mMinSdkVersion == 0 || mMinSdkVersion > minSdkVersion) { + mMinSdkVersion = minSdkVersion; + } } catch (BrutException ex) { throw new AndrolibException(ex); } @@ -809,5 +817,5 @@ public class Androlib { "lib", "libs", "assets", "META-INF", "kotlin" }; private final static Pattern NO_COMPRESS_PATTERN = Pattern.compile("(" + "jpg|jpeg|png|gif|wav|mp2|mp3|ogg|aac|mpg|mpeg|mid|midi|smf|jet|rtttl|imy|xmf|mp4|" + - "m4a|m4v|3gp|3gpp|3g2|3gpp2|amr|awb|wma|wmv|webm|mkv)$"); + "m4a|m4v|3gp|3gpp|3g2|3gpp2|amr|awb|wma|wmv|webm|webp|mkv)$"); } diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkDecoder.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkDecoder.java index 9accf1bb..826293a6 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkDecoder.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkDecoder.java @@ -332,6 +332,8 @@ public class ApkDecoder { putVersionInfo(meta); putSharedLibraryInfo(meta); putSparseResourcesInfo(meta); + } else { + putMinSdkInfo(meta); } putUnknownInfo(meta); putFileCompressionInfo(meta); @@ -386,6 +388,15 @@ public class ApkDecoder { } } + private void putMinSdkInfo(MetaInfo meta) { + int minSdkVersion = mAndrolib.getMinSdkVersion(); + if (minSdkVersion > 0) { + Map sdkInfo = new LinkedHashMap<>(); + sdkInfo.put("minSdkVersion", Integer.toString(minSdkVersion)); + meta.sdkInfo = sdkInfo; + } + } + private void putPackageInfo(MetaInfo meta) throws AndrolibException { String renamed = mResTable.getPackageRenamed(); String original = mResTable.getPackageOriginal(); diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/src/SmaliDecoder.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/src/SmaliDecoder.java index 46bbcd7f..226ae3da 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/src/SmaliDecoder.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/src/SmaliDecoder.java @@ -24,6 +24,7 @@ import org.jf.dexlib2.Opcodes; import org.jf.dexlib2.dexbacked.DexBackedDexFile; import org.jf.dexlib2.dexbacked.DexBackedOdexFile; import org.jf.dexlib2.analysis.InlineMethodResolver; +import org.jf.dexlib2.iface.DexFile; import org.jf.dexlib2.iface.MultiDexContainer; import java.io.File; @@ -31,9 +32,9 @@ import java.io.IOException; public class SmaliDecoder { - public static void decode(File apkFile, File outDir, String dexName, boolean bakDeb, int apiLevel) + public static DexFile decode(File apkFile, File outDir, String dexName, boolean bakDeb, int apiLevel) throws AndrolibException { - new SmaliDecoder(apkFile, outDir, dexName, bakDeb, apiLevel).decode(); + return new SmaliDecoder(apkFile, outDir, dexName, bakDeb, apiLevel).decode(); } private SmaliDecoder(File apkFile, File outDir, String dexName, boolean bakDeb, int apiLevel) { @@ -44,7 +45,7 @@ public class SmaliDecoder { mApiLevel = apiLevel; } - private void decode() throws AndrolibException { + private DexFile decode() throws AndrolibException { try { final BaksmaliOptions options = new BaksmaliOptions(); @@ -67,7 +68,8 @@ public class SmaliDecoder { } // create the container - MultiDexContainer container = DexFileFactory.loadDexContainer(mApkFile, mApiLevel > 0 ? Opcodes.forApi(mApiLevel) : null); + MultiDexContainer container = + DexFileFactory.loadDexContainer(mApkFile, mApiLevel > 0 ? Opcodes.forApi(mApiLevel) : null); MultiDexContainer.DexEntry dexEntry; DexBackedDexFile dexFile; @@ -96,6 +98,8 @@ public class SmaliDecoder { } Baksmali.disassembleDexFile(dexFile, mOutDir, jobs, options); + + return dexFile; } catch (IOException ex) { throw new AndrolibException(ex); }