• 前言
    • AAPT 介绍
    • 技术要点
    • 总结
    • 源码下载

前言

Android项目迭代中,常常将APK,APK的信息提交到后台,然后后台开发人员提供API给Android调用,返回迭代更新的内容以及apk,可以我们在提交APK的时候可以会本次更新的版本号比上次低,导致Android前端下载最新的APK无法正常安装,因为Android端覆盖安装的APK必须比之前的APK的版本号要大。

本文运用Android原生工具AAPT在提交APK的时候解析APK的版本号,在提交APK的时候进行判断APK的版本号是否大于上次的版本号,以达到每次迭代APK都是正确的

AAPT 介绍

开发过Android的同学对AAPT并不陌生,AAPT 全称Android Asset Packaging Tool,位于 Android SDK 的build-tools目录下,是Android打包的一个工具,也就是Android最后的APK就是由AAPT生成的,既然APK是由它生成的,AAPT当然也可以解析APK,下图是AAPT所在的位置截图,需要各位同学去下载Android SDK

有了AAPT我们就能使用AAPT命令对APK进行命令操作,AAPT命令跟Android的adb命令类似,不懂的同学请自行查阅,AAPT命令如下:

查看apk一些信息
aapt d[ump] [–values] WHAT file.{apk} [asset [asset …]]

badging Print the label and icon for the app declared in APK
permissions Print the permissions from the APK.
resources Print the resource table from the APK.
configurations Print the configurations in the APK.
xmltree Print the compiled xmls in the given assets.
xmlstrings Print the strings of the given compiled xml assets

技术要点

前面我们学习了AAPT的使用以及AAPT的命令,现在让我们用java代码去实现AAPT命令操作APK吧,具体代码如下

String apkPath ="C:\Users\Administrator\Desktop\test\PluginApp-debug-20180622_18-[V 2.1.1].apk";
String aaptTool = aaptToolPath +"/"+ getAaptToolName();
Process process = null;
InputStream inputStream = null;
BufferedReader bufferedReader = null;
try {
ProcessBuilder builder = new ProcessBuilder();
builder.redirectErrorStream(true);
process = builder.command(aaptTool, "d", "badging", apkPath).start();
inputStream = process.getInputStream();
bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "utf-8"));
ApkInfo apkInfo = new ApkInfo();
apkInfo.setSize(new File(apkPath).length());
String temp = null;
while ((temp = bufferedReader.readLine()) != null) {
setApkInfoProperty(apkInfo, temp);
}
return apkInfo;
} catch (IOException e) {
e.printStackTrace();
return null;
} finally {
if (process != null) {
process.destroy();
}
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

我们使用了ProcessBuilder执行了AAPT命令获取了执行过后的InputStream,其中InputStream就包含我们想要的信息,让我们开始解析InputStream信息,setApkInfoProperty函数的代码如下:

private void setApkInfoProperty(ApkInfo apkInfo, String source) {
if (source.startsWith(APPLICATION)) {
String[] rs = source.split("( icon=')|'");
apkInfo.setIcon(rs[rs.length - 1]);
} else if (source.startsWith(APPLICATION_ICON)) {
apkInfo.addToIcons(getKeyBeforeColon(source), getPropertyInQuote(source));
} else if (source.startsWith(APPLICATION_LABEL)) {
apkInfo.setLabel(getPropertyInQuote(source));
} else if (source.startsWith(LAUNCHABLE_ACTIVITY)) {
apkInfo.setLaunchableActivity(getPropertyInQuote(source));
} else if (source.startsWith(PACKAGE)) {
String[] packageInfo = source.split(SPLIT_REGEX);
apkInfo.setPackageName(packageInfo[2]);
apkInfo.setVersionCode(packageInfo[4]);
apkInfo.setVersionName(packageInfo[6]);
} else if (source.startsWith(SDK_VERSION)) {
apkInfo.setSdkVersion(getPropertyInQuote(source));
} else if (source.startsWith(TARGET_SDK_VERSION)) {
apkInfo.setTargetSdkVersion(getPropertyInQuote(source));
} else if (source.startsWith(USES_PERMISSION)) {
apkInfo.addToUsesPermissions(getPropertyInQuote(source));
} else if (source.startsWith(USES_FEATURE)) {
apkInfo.addToFeatures(getPropertyInQuote(source));
} else {
}
}

我们的APK信息就全部缓存到了ApkInfo 这个对象身上了

总结

此前看到网上有很多博客解析APK使用的是解析ZIP包,然后解析Manifest文件去实现的,但是那种方法对应APK加密,加壳的无法解析,使用AAPT可以无痕解析任何APK信息

源码下载

更多相关文章

  1. Android(安卓)Service解析解析再解析
  2. 【转】Android(安卓)调试桥(adb),很方便很强大
  3. 通过CMake来进行ndk开发之补充篇
  4. 搜集整理的一些博客导航
  5. Android加载大图防止OOM
  6. android在framework层增加自己的service仿照GPS
  7. android的消息处理惩罚机制(图+源码解析)——Looper,Handler,Message
  8. Android(安卓)Activity全面解析
  9. Android(安卓)Monkey测试入门-2-ADB安装和卸载命令

随机推荐

  1. android 异步处理
  2. 跟大家分享下Android布局文件layout.xml
  3. Android(安卓)跑马灯效果auto scroll tex
  4. coreApp="true";android:sharedUserId="an
  5. android中用Spannable在TextView中设置超
  6. Android(安卓)GIS +webservice
  7. Android(安卓)xml资源文件中@、@android:
  8. android XML布局大全
  9. Android(安卓)ApiDemos示例解析(145):Vie
  10. Shape的使用