package com.headius.android.dex; import java.io.ByteArrayOutputStream; import java.io.OutputStreamWriter; import com.android.dx.cf.iface.ParseException; import com.android.dx.dex.DexFormat; import com.android.dx.dex.DexOptions; import com.android.dx.dex.cf.CfOptions; import com.android.dx.dex.cf.CfTranslator; import com.android.dx.dex.code.PositionList; import com.android.dx.dex.file.ClassDefItem; import com.android.dx.dex.file.DexFile; public class DexClient { /** {@code non-null;} output file in-progress */ private static DexFile outputDex; private static DexOptions dexOptions = new DexOptions(); static { dexOptions.targetApiLevel = DexFormat.API_NO_EXTENDED_OPCODES; } private final CfOptions cfOptions; public DexClient() { outputDex = new DexFile(dexOptions); cfOptions = new CfOptions(); cfOptions.positionInfo = PositionList.LINES; cfOptions.localInfo = true; cfOptions.strictNameCheck = true; cfOptions.optimize = false; cfOptions.optimizeListFile = null; cfOptions.dontOptimizeListFile = null; cfOptions.statistics = false; } public byte[] classesToDex(String[] names, byte[][] byteArrays) { for (int i = 0; i < names.length; i++) { String name = names[i]; byte[] byteArray = byteArrays[i]; processClass(name, byteArray); } byte[] outputArray = writeDex(); return outputArray; } /** * Processes one classfile. * * @param name {@code non-null;} name of the file, clipped such that it * should correspond to the name of the class it contains * @param bytes {@code non-null;} contents of the file * @return whether processing was successful */ private boolean processClass(String name, byte[] bytes) { try { ClassDefItem clazz; clazz = CfTranslator.translate(name, bytes, cfOptions, dexOptions); outputDex.add(clazz); return true; } catch (ParseException ex) { ex.printStackTrace(); } return false; } /** * Converts {@link #outputDex} into a {@code byte[]}, write * it out to the proper file (if any), and also do whatever human-oriented * dumping is required. * * @return {@code null-ok;} the converted {@code byte[]} or {@code null} * if there was a problem */ private byte[] writeDex() { byte[] outArray = null; OutputStreamWriter out = new OutputStreamWriter(new ByteArrayOutputStream()); try { outArray = outputDex.toDex(out, false); } catch (Exception ex) { ex.printStackTrace(); } return outArray; } }