apk文件比对
新版本发布时,需要check下新版本Apk包大小,以及具体哪些文件导致Apk变大,从而针对性的进行优化。Android studio 有工具Analyze APK 做了类似的事情,但是无法进行持续集成,本文参照Alalyze APK 的功能,分析APK各个文件大小,并给出对应的结果报告
使用方法
java -jar apk.jar App-1.0.apk App-2.0.apk changes
会输出diffReport.html
diffReport.html 结果
源码
Main.java
import java.io.*;
import java.text.NumberFormat;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import org.pegdown.PegDownProcessor;
public class Main {
static final String NA = "N/A";
static String StyleCSS ="";
static final NumberFormat format = NumberFormat.getInstance();
static final Comparator comparator = new Comparator<DiffItem>() {
@Override
public int compare(DiffItem o1, DiffItem o2) {
return (int) (Math.abs(o2.diffSize) - Math.abs(o1.diffSize));
}
};
public static void main(String[] args) {
if (args.length != 3) {
System.out.println("Usage: ApkCompare oldApk newApk outputFilename");
System.out.println("Example: ApkCompare App-1.0.apk App-2.0.apk changes");
System.out.println("This would output a diff file named changes.md at current directory");
return;
}
Map<String, Long> oldFilesInfo = getFilesInfo(args[0]);
Map<String, Long> newFilesInfo = getFilesInfo(args[1]);
List<DiffItem> outputDiffList = new ArrayList<DiffItem>();
Set<Map.Entry<String, Long>> oldEntries = oldFilesInfo.entrySet();
for (Map.Entry<String, Long> oldEntry : oldEntries) {
DiffItem diffItem = new DiffItem();
String keyOldFilename = oldEntry.getKey();
diffItem.oldFilename = keyOldFilename;
Long oldFileSize = oldEntry.getValue();
Long newFileSize = newFilesInfo.get(keyOldFilename);
if (newFileSize == null) { //新APK中删除了的文件
diffItem.newFilename = NA;
diffItem.diffSize = -oldFileSize;
} else {
diffItem.newFilename = diffItem.oldFilename;
diffItem.diffSize = newFileSize - oldFileSize;
}
newFilesInfo.remove(keyOldFilename);
if (diffItem.diffSize != 0L) { //仅统计文件大小有改变的情况
outputDiffList.add(diffItem);
}
}
//新版本中新增的文件
Set<Map.Entry<String, Long>> newEntries = newFilesInfo.entrySet();
for (Map.Entry<String, Long> newEntry : newEntries) {
DiffItem diffItem = new DiffItem();
diffItem.oldFilename = NA;
diffItem.newFilename = newEntry.getKey();
diffItem.diffSize = newEntry.getValue();
outputDiffList.add(diffItem);
}
outputMarkdown(args, outputDiffList);
System.out.println("APK compare done!");
System.out.println("output file: " + new File(args[2]).getAbsolutePath() + ".md");
try {
get(new File(args[2]).getAbsolutePath() + ".md");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static String readFile(String filepath)throws IOException{
FileReader reader = new FileReader(filepath);//定义一个fileReader对象,用来初始化BufferedReader
BufferedReader bReader = new BufferedReader(reader);//new一个BufferedReader对象,将文件内容读取到缓存
StringBuilder sb = new StringBuilder();//定义一个字符串缓存,将字符串存放缓存中
String s = "";
while ((s =bReader.readLine()) != null) {//逐行读取文件内容,不读取换行符和末尾的空格
sb.append(s + "\n");//将读取的字符串添加换行符后累加存放在缓存中
}
bReader.close();
return sb.toString();
}
public static String readJarFile(String filepath)throws IOException{
InputStream inputStream = Main.class.getResourceAsStream(filepath);
BufferedReader bReader = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder sb = new StringBuilder();
String s = "";
while ((s =bReader.readLine()) != null) {
sb