Andorid快速打包工具Package_Ng 简介
来源:互联网 发布:房价数据网 编辑:程序博客网 时间:2024/06/07 17:39
- 背景
- 原理
- 实现
- package_ng在as中配置
- 使用特别注意事项
背景
我们在日常使用应用可能会遇到以下场景。
场景1:多渠道打包,算下公司渠道有100多个,每次发版打包就要花掉1个多小时。发版中出现bug需要及时修复,就需要重复打包。严重影响上线效率。那么有没有一种技术能代码gradle脚本,实现快速打包呢?答案是肯定的
Package_ng链接地址:
https://github.com/mcxiaoke/packer-ng-plugin
原理
android使用的apk包的压缩方式是zip,与zip有相同的文件结构,在zip的Central directory file header中包含一个File comment区域,可以存放一些数据。File comment是zip文件如果可以正确的修改这个部分,就可以在不破坏压缩包、不用重新打包的的前提下快速的给apk文件写入自己想要的数据。
comment是在Central directory file header末尾储存的,可以将数据直接写在这里,下表是header末尾的
由于数据是不确定的,我们无法知道comment的长度,从表中可以看到zip定义comment的长度的位置在comment之前,所以无法从zip中直接获取comment的长度。这里我们需要自定义comment的长度,在自定义comment内容的后面添加一个区域储存comment的长度,结构如下图。
这里可以将一个固定的结构写在comment中,然后根据自定义的长度分区获取每个部分的内容,还可以添加其它数据,如校验码、版本等。
具体源码介绍:
查看master中的Pack_ng 类,核心逻辑都在这个类中。
下面给出PACKER_Ng中的类结构
上面圈红的类就是具体的读写marker内容的类
实现
1.将数据写入comment
这一部分可以在本地进行,需要定义一个长度为2的byte[]来储存comment的长度,直接使用Java的api就可以把comment和comment的长度写到apk的末尾,代码如下。
public static void writeApk(File file, String comment) { ZipFile zipFile = null; ByteArrayOutputStream outputStream = null; RandomAccessFile accessFile = null; try { zipFile = new ZipFile(file); String zipComment = zipFile.getComment(); if (zipComment != null) { return; } byte[] byteComment = comment.getBytes(); outputStream = new ByteArrayOutputStream(); outputStream.write(byteComment); outputStream.write(short2Stream((short) byteComment.length)); byte[] data = outputStream.toByteArray(); accessFile = new RandomAccessFile(file, "rw"); accessFile.seek(file.length() - 2); accessFile.write(short2Stream((short) data.length)); accessFile.write(data); } catch (IOException e) { e.printStackTrace(); } finally { try { if (zipFile != null) { zipFile.close(); } if (outputStream != null) { outputStream.close(); } if (accessFile != null) { accessFile.close(); } } catch (Exception e) { } }}
2.读取apk包中的comment数据
首先获取apk的路径,通过context中的getPackageCodePath()方法就可以获取,代码如下。
public static String getPackagePath(Context context) { if (context != null) { return context.getPackageCodePath(); } return null;}
获取路径之后就可以读取comment的内容了,这里不能直接使用ZipFile中的getComment()方法直接获取comment,因为这个方法是Java7中的方法,在android4.4之前是不支持Java7的,所以我们需要自己去读取apk文件中的comment。首先根据之前自定义的结构,先读取写在最后的comment的长度,根据这个长度,才可以获取真正comment的内容,代码如下。
public static String readApk(File file) { byte[] bytes = null; try { RandomAccessFile accessFile = new RandomAccessFile(file, "r"); long index = accessFile.length(); bytes = new byte[2]; index = index - bytes.length; accessFile.seek(index); accessFile.readFully(bytes); int contentLength = stream2Short(bytes, 0); bytes = new byte[contentLength]; index = index - bytes.length; accessFile.seek(index); accessFile.readFully(bytes); return new String(bytes, "utf-8"); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return null;}
这里的stream2Short()和short2Stream()参考了MultiChannelPackageTool中的方法。
然后就是断点查看了。看结果28s 时间打了 100 +个渠道包。(mama 再也不担心我的多渠道打包!!!)
3.package_ng在as中配置
Eg:这里以umeng 服务为样本
一般卸载app的入口处,Application中
/设置渠道/
market = PackerNg.getMarket(context); //读取apk中的渠道
AnalyticsConfig.setChannel(market); //调用umeng的api 进行渠道设置
Build.gradle中的配置 主要配置Pg依赖
项目 root 下的Build.gradle
buildscript { repositories { jcenter() } dependencies { classpath 'com.android.tools.build:gradle:2.2.2' classpath 'com.mcxiaoke.gradle:packer-ng:1.0.8' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files }}allprojects { repositories { jcenter() }}task clean(type: Delete) { delete rootProject.buildDir}
app root 下的build.gradle文件
apply plugin: 'packer'dependencies { compile fileTree(include: ['*.jar'], dir: 'libs') compile files('libs/android-support-v4.jar') compile files('libs/gson-2.2.2.jar') compile files('libs/nineoldandroids.jar') compile files('libs/systembartint-1.0.4.jar') compile files('libs/umeng-analytics-v5.5.3.jar') compile files('libs/umeng-update-v2.6.0.1.jar') compile files('libs/universal-image-loader-1.9.3.jar') compile 'com.mcxiaoke.gradle:packer-helper:1.0.8' compile 'de.greenrobot:greendao:1.3.7' compile project(':PushSDK')}
使用特别注意事项
近期使用packet_ng 打渠道包,出现360应用市场统计不到渠道信息问题,具体原因是由于 360加固导致。从新查看的原作者文章看到有具体说明,一定要看完整文档!!!!!
本人使用packet_ng jar 进行命令行打包,发现打出来的包渠道信息乱码,最后选择使用Helper 类中的api (writer reader)
@Test public void readZipComment() { try { String name = "app-release1_252_jiagu_sign.apk"; File file = new File("E:\\2.5.5\\app\\build\\outputs\\apk\\" + name + ""); String mart = PackerNg.Helper.readMarket(file); Log.d("readZipComment", mart); } catch (IOException e) { Log.d("", "readZipComment: " + e.getMessage()); } } @Test public void WriterZipComment() { try { String name = "app-release1_252_jiagu_sign.apk"; String channelName = "360dev"; File file = new File("E:\\2.5.5\\app\\build\\outputs\\apk\\" + name + ""); PackerNg.Helper.writeMarket(file, "360dev"); Log.d("readZipComment", channelName); } catch (IOException e) { Log.d("", "readZipComment: " + e.getMessage()); } }
进行读写,不会出现乱码问题的,该问题已经联系作者,日后更新,特此更正
具体详细细节可以参照package_ng 作者介绍。
使用中有什么问题可以联系:微信
快速打包原理:
http://pingguohe.net/2016/03/21/Dynimac-write-infomation-into-apk.html?utm_source=tuicool&utm_medium=referral
- Andorid快速打包工具Package_Ng 简介
- make_ext4fs工具快速打包
- Marketer 渠道打包工具,可视化打包工具,快速打包工具
- FatJar打包工具使用简介
- 【Andorid】Gradle多渠道打包
- Andorid 代码打包--aar
- Python打包分发工具setuptools简介
- 自动打包工具Hudson——简介
- Andorid Json 简介
- andorid bionic简介
- Andorid 动画 直观工具
- niu B快速开发工具简介
- install4j与exe4简介——Java应用程序打包工具
- APK文件简介 及 解包 打包 工具 介绍
- Andorid工具类-图片处理工具类
- 打包工具
- 打包工具
- 工具打包
- iOS开发 如何查看真机里的沙盒文件
- jquery Ajax标准写法
- Android主流的图片加载库的使用 - Glide
- qt使用动态库(DLL)
- glDrawArrays
- Andorid快速打包工具Package_Ng 简介
- 学习python的第三十七天-第一章 进入python的世界
- LeetCode #437 - Path Sum III - Medium
- ScrowView和Listview的冲突问题
- Android Studio中keystore的创建、分类
- Length of Last Word
- vue.js实现数据传递的demo
- HttpServletResponse.sendRedirect()与RequestDispatcher.forward()的区别
- arx是什么文件