com.googlecode.d2j.reader.MultiDexFileReader Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gradle Show documentation
Show all versions of gradle Show documentation
fakeradnroid gradle builder
package com.googlecode.d2j.reader;
import com.googlecode.d2j.DexConstants;
import com.googlecode.d2j.util.zip.AccessBufByteArrayOutputStream;
import com.googlecode.d2j.util.zip.ZipEntry;
import com.googlecode.d2j.util.zip.ZipFile;
import com.googlecode.d2j.visitors.DexFileVisitor;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.*;
public class MultiDexFileReader implements BaseDexFileReader {
final private List readers = new ArrayList<>();
final private List- items = new ArrayList<>();
public MultiDexFileReader(Collection
readers) {
this.readers.addAll(readers);
init();
}
private static byte[] toByteArray(InputStream is) throws IOException {
AccessBufByteArrayOutputStream out = new AccessBufByteArrayOutputStream();
byte[] buff = new byte[1024];
for (int c = is.read(buff); c > 0; c = is.read(buff)) {
out.write(buff, 0, c);
}
return out.getBuf();
}
public static BaseDexFileReader open(byte[] data) throws IOException {
if (data.length < 3) {
throw new IOException("File too small to be a dex/zip");
}
if ("dex".equals(new String(data, 0, 3, StandardCharsets.ISO_8859_1))) {// dex
return new DexFileReader(data);
} else if ("PK".equals(new String(data, 0, 2, StandardCharsets.ISO_8859_1))) {// ZIP
TreeMap dexFileReaders = new TreeMap<>();
try (ZipFile zipFile = new ZipFile(data)) {
for (ZipEntry e : zipFile.entries()) {
String entryName = e.getName();
if (entryName.startsWith("classes") && entryName.endsWith(".dex")) {
if (!dexFileReaders.containsKey(entryName)) { // only the first one
dexFileReaders.put(entryName, new DexFileReader(toByteArray(zipFile.getInputStream(e))));
}
}
}
}
if (dexFileReaders.size() == 0) {
throw new IOException("Can not find classes.dex in zip file");
} else if (dexFileReaders.size() == 1) {
return dexFileReaders.firstEntry().getValue();
} else {
return new MultiDexFileReader(dexFileReaders.values());
}
}
throw new IOException("the src file not a .dex or zip file");
}
void init() {
Set classes = new HashSet<>();
for (DexFileReader reader : readers) {
List classNames = reader.getClassNames();
for (int i = 0; i < classNames.size(); i++) {
String className = classNames.get(i);
if (classes.add(className)) {
items.add(new Item(i, reader, className));
}
}
}
}
@Override
public int getDexVersion() {
int max = DexConstants.DEX_035;
for (DexFileReader r : readers) {
int v = r.getDexVersion();
if (v > max) {
max = v;
}
}
return max;
}
@Override
public void accept(DexFileVisitor dv) {
accept(dv, 0);
}
@Override
public List getClassNames() {
return new AbstractList() {
@Override
public String get(int index) {
return items.get(index).className;
}
@Override
public int size() {
return items.size();
}
};
}
@Override
public void accept(DexFileVisitor dv, int config) {
int size = items.size();
for (int i = 0; i < size; i++) {
accept(dv, i, config);
}
}
@Override
public void accept(DexFileVisitor dv, int classIdx, int config) {
Item item = items.get(classIdx);
item.reader.accept(dv, item.idx, config);
}
static class Item {
int idx;
DexFileReader reader;
String className;
public Item(int i, DexFileReader reader, String className) {
idx = i;
this.reader = reader;
this.className = className;
}
}
}