Pass minimum api level to smali library

When apktool creates a DexBuilder class, it creates it without specifying a minimum api level. This causes the DexBuilder class to assume api level 20 by default. This is not ideal since in some cases, the concrete minimum api level is required.

One such case is in smali's DexWriter class which implements a workaround for a bug in Dalvik that was fixed in Android 4.2 (https://code.google.com/p/android/issues/detail?id=35304) that causes apps that call the Method.getParameterAnnotations api to crash in some cases (see bug report for more details). The workaround that smali implements is only triggered if the minimum api level is below 17 (Android 4.2). But since apktool effectively sets the minimum api level to 20, this code is never triggered causing apktool to create apk files that crash on devices below Android 4.2.

This change passes the minimum api level to the smali library.
This commit is contained in:
Benjamin Adolphi 2016-09-05 11:52:58 +02:00 committed by Benjamin Adolphi
parent 64644a1242
commit db35f54af6
2 changed files with 22 additions and 6 deletions

View File

@ -51,6 +51,7 @@ public class Androlib {
private final AndrolibResources mAndRes = new AndrolibResources();
protected final ResUnknownFiles mResUnknownFiles = new ResUnknownFiles();
public ApkOptions apkOptions;
private int mMinSdkVersion = 0;
public Androlib(ApkOptions apkOptions) {
this.apkOptions = apkOptions;
@ -278,6 +279,10 @@ public class Androlib {
mAndRes.setVersionInfo(meta.versionInfo);
mAndRes.setSharedLibrary(meta.sharedLibrary);
if (meta.sdkInfo != null && meta.sdkInfo.get("minSdkVersion") != null) {
mMinSdkVersion = Integer.parseInt(meta.sdkInfo.get("minSdkVersion"));
}
if (outFile == null) {
String outFileName = meta.apkFileName;
outFile = new File(appDir, "dist" + File.separator + (outFileName == null ? "out.apk" : outFileName));
@ -397,7 +402,7 @@ public class Androlib {
if (apkOptions.forceBuildAll || isModified(smaliDir, dex)) {
LOGGER.info("Smaling " + folder + " folder into " + filename +"...");
dex.delete();
SmaliBuilder.build(smaliDir, dex);
SmaliBuilder.build(smaliDir, dex, mMinSdkVersion);
}
return true;
}

View File

@ -26,6 +26,7 @@ import java.util.logging.Logger;
import org.antlr.runtime.RecognitionException;
import org.apache.commons.io.IOUtils;
import org.jf.dexlib2.Opcodes;
import org.jf.dexlib2.writer.builder.DexBuilder;
import org.jf.dexlib2.writer.io.FileDataStore;
@ -33,19 +34,28 @@ import org.jf.dexlib2.writer.io.FileDataStore;
* @author Ryszard Wiśniewski <brut.alll@gmail.com>
*/
public class SmaliBuilder {
public static void build(ExtFile smaliDir, File dexFile) throws AndrolibException {
new SmaliBuilder(smaliDir, dexFile).build();
public static void build(ExtFile smaliDir, File dexFile, int apiLevel) throws AndrolibException {
new SmaliBuilder(smaliDir, dexFile, apiLevel).build();
}
private SmaliBuilder(ExtFile smaliDir, File dexFile) {
public static void build(ExtFile smaliDir, File dexFile) throws AndrolibException {
new SmaliBuilder(smaliDir, dexFile, 0).build();
}
private SmaliBuilder(ExtFile smaliDir, File dexFile, int apiLevel) {
mSmaliDir = smaliDir;
mDexFile = dexFile;
mApiLevel = apiLevel;
}
private void build() throws AndrolibException {
try {
DexBuilder dexBuilder = DexBuilder.makeDexBuilder();
DexBuilder dexBuilder;
if (mApiLevel > 0) {
dexBuilder = DexBuilder.makeDexBuilder(Opcodes.forApi(mApiLevel));
} else {
dexBuilder = DexBuilder.makeDexBuilder();
}
for (String fileName : mSmaliDir.getDirectory().getFiles(true)) {
buildFile(fileName, dexBuilder);
@ -77,6 +87,7 @@ public class SmaliBuilder {
private final ExtFile mSmaliDir;
private final File mDexFile;
private int mApiLevel = 0;
private final static Logger LOGGER = Logger.getLogger(SmaliBuilder.class.getName());
}