Android--解包、添加文件、打包、签名
package zip; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.Writer; public class ziptest { private static File apktool = null; private static File signapk = null; private static File testkey_pk8 = null; private static File testkey_x509_pem = null; private static File dirFile;// 根目录 public static void main(String args[]) throws IOException{ Process process = null; apktool = new File(dirFile.getAbsolutePath(), "apktool.bat"); dirFile = new File(System.getProperty("user.dir")); signapk = new File(dirFile.getAbsolutePath(), "signapk.jar"); testkey_pk8 = new File(dirFile.getAbsolutePath(), "testkey.pk8"); testkey_x509_pem = new File(dirFile.getAbsolutePath(), "testkey.x509.pem"); try { //1----解压 //apktool路径 //String path = "E:\\apktool\\apktool.bat"; //保存路径 String appPath = "E:\\newapk\\"; //process = Runtime.getRuntime().exec("cmd.exe /c"+path+" apktool d "+appPath+"lvping.apk -o"+appPath+"apk"); process = Runtime.getRuntime().exec("cmd.exe /c"+apktool.getPath() + " d –f "+appPath+"lvping.apk -o"+appPath+"apk"); if(process.waitFor()!=0)System.out.println("解压失败!"); //2----添加json文件 String filePath ="E:\\newapk\\apk"; File f = new File(filePath); File[] fis = f.listFiles(); for(File ff:fis) { String paths = ff.getAbsolutePath(); if(paths.contains("assets")) { String fPath = "E:\\newapk\\apk\\assets"; CreateJson(fPath); }else { String fPath =filePath+"\\assets"; File fs = new File(fPath); CreateJson(fPath); fs.mkdirs(); } } //3----打包 // process = Runtime.getRuntime().exec("cmd.exe /c"+path+" b "+appPath+"apk -o"+appPath+"app.apk"); process = Runtime.getRuntime().exec("cmd.exe /c"+apktool.getPath() +" b "+appPath+"apk -o"+appPath+"app.apk"); if(process.waitFor()!=0)System.out.println("打包失败!"); //4----签名 (文件名称中不能包含空格) //String cmd = "cmd.exe /c E:\\apktool\\signapk.jar E:\\apktool\\testkey.x509.pem E:\\apktool\\testkey.pk8 "+appPath+"app.apk"+ appPath; String cmd = "cmd.exe /c java -jar" + signapk.getPath() + " " + testkey_x509_pem.getPath() + " " + testkey_pk8.getPath() + " " +appPath+"app.apk " + appPath+ "appt.apk"; process = Runtime.getRuntime().exec(cmd); System.out.println("111213"); if(process.waitFor()!=0) { System.out.println("签名失败。。。"); } }catch (Exception e) { e.printStackTrace(); }finally{ /* br.close(); osw.close();*/ } } public static void CreateJson(String fPath/*,String json*/) { // 标记文件生成是否成功 boolean flag = true; // 拼接文件完整路径 String fullPath =fPath+ File.separator + "config.json"; // 生成json格式文件 try { // 保证创建一个新文件 File file = new File(fullPath); if (!file.getParentFile().exists()) { // 如果父目录不存在,创建父目录 file.getParentFile().mkdirs(); } if (file.exists()) { // 如果已存在,删除旧文件 file.delete(); } file.createNewFile(); // 格式化json字符串 // 将格式化后的字符串写入文件 Writer write = new OutputStreamWriter(new FileOutputStream(file), "UTF-8"); write.write("{\"user\":\"test1\",\"direction\":\"3.24\"}"); write.flush(); write.close(); } catch (Exception e) { flag = false; e.printStackTrace(); } } }
上面是借助apktool,下面试纯代码:
import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.util.Enumeration; import java.util.zip.CRC32; import java.util.zip.CheckedOutputStream; import java.util.zip.ZipOutputStream; import org.apache.tools.zip.ZipEntry; import org.apache.tools.zip.ZipFile; /** * @author showlike * @version v1.0 * 2012-9-28 上午11:03:36 * explain : 文件解压/打包工具 */ public class ZipUtil { private static final int BUFFER = 1024; private static final String BASE_DIR = ""; /**符号"/"用来作为目录标识判断符*/ private static final String PATH = "/"; /**签名目录*/ private static final String SIGN_PATH_NAME = "META-INF"; /**修改文件目录*/ private static final String UPDATE_PATH_NAME = "\\res\\raw\\channel"; /**解压源文件目录*/ private static final String SOURCE_PATH_NAME = "\\source\\"; /**打包目录*/ private static final String TARGET_PATH_NAME = "\\target\\"; /**签名目录*/ private static final String RESULT_PATH_NAME = "\\result\\"; /**JDK BIN 目录*/ private static final String JDK_BIN_PATH = "C:\\Program Files\\Java\\jdk1.6.0_26\\bin"; /**密钥 目录*/ private static final String SECRET_KEY_PATH = "F:\\document\\APK\\"; /**密钥 名称*/ private static final String SECRET_KEY_NAME = "sdk.keystore"; /** * 解压缩zip文件 * @param fileName 要解压的文件名 包含路径 如:"c:\\test.zip" * @param filePath 解压后存放文件的路径 如:"c:\\temp" * @throws Exception */ @SuppressWarnings("rawtypes") public static void unZip(String fileName, String filePath) throws Exception{ ZipFile zipFile = new ZipFile(fileName); Enumeration emu = zipFile.getEntries(); while(emu.hasMoreElements()){ ZipEntry entry = (ZipEntry) emu.nextElement(); if (entry.isDirectory()){ new File(filePath+entry.getName()).mkdirs(); continue; } BufferedInputStream bis = new BufferedInputStream(zipFile.getInputStream(entry)); File file = new File(filePath + entry.getName()); File parent = file.getParentFile(); if(parent != null && (!parent.exists())){ parent.mkdirs(); } FileOutputStream fos = new FileOutputStream(file); BufferedOutputStream bos = new BufferedOutputStream(fos,BUFFER); byte [] buf = new byte[BUFFER]; int len = 0; while((len=bis.read(buf,0,BUFFER))!=-1){ fos.write(buf,0,len); } bos.flush(); bos.close(); bis.close(); } zipFile.close(); } /** * 压缩文件 * * @param srcFile * @param destPath * @throws Exception */ public static void compress(String srcFile, String destPath) throws Exception { compress(new File(srcFile), new File(destPath)); } /** * 压缩 * * @param srcFile * 源路径 * @param destPath * 目标路径 * @throws Exception */ public static void compress(File srcFile, File destFile) throws Exception { // 对输出文件做CRC32校验 CheckedOutputStream cos = new CheckedOutputStream(new FileOutputStream( destFile), new CRC32()); ZipOutputStream zos = new ZipOutputStream(cos); compress(srcFile, zos, BASE_DIR); zos.flush(); zos.close(); } /** * 压缩 * * @param srcFile * 源路径 * @param zos * ZipOutputStream * @param basePath * 压缩包内相对路径 * @throws Exception */ private static void compress(File srcFile, ZipOutputStream zos, String basePath) throws Exception { if (srcFile.isDirectory()) { compressDir(srcFile, zos, basePath); } else { compressFile(srcFile, zos, basePath); } } /** * 压缩目录 * * @param dir * @param zos * @param basePath * @throws Exception */ private static void compressDir(File dir, ZipOutputStream zos, String basePath) throws Exception { File[] files = dir.listFiles(); // 构建空目录 if (files.length < 1) { ZipEntry entry = new ZipEntry(basePath + dir.getName() + PATH); zos.putNextEntry(entry); zos.closeEntry(); } String dirName = ""; String path = ""; for (File file : files) { //当父文件包名为空时,则不把包名添加至路径中(主要是解决压缩时会把父目录文件也打包进去) if(basePath!=null && !"".equals(basePath)){ dirName=dir.getName(); } path = basePath + dirName + PATH; // 递归压缩 compress(file, zos, path); } } /** * 文件压缩 * * @param file * 待压缩文件 * @param zos * ZipOutputStream * @param dir * 压缩文件中的当前路径 * @throws Exception */ private static void compressFile(File file, ZipOutputStream zos, String dir) throws Exception { /** * 压缩包内文件名定义 * * <pre> * 如果有多级目录,那么这里就需要给出包含目录的文件名 * 如果用WinRAR打开压缩包,中文名将显示为乱码 * </pre> */ if("/".equals(dir))dir=""; else if(dir.startsWith("/"))dir=dir.substring(1,dir.length()); ZipEntry entry = new ZipEntry(dir + file.getName()); zos.putNextEntry(entry); BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file)); int count; byte data[] = new byte[BUFFER]; while ((count = bis.read(data, 0, BUFFER)) != -1) { zos.write(data, 0, count); } bis.close(); zos.closeEntry(); } public static void main(String[] args)throws Exception{ StringBuffer buffer = new StringBuffer(); BufferedReader br =null; OutputStreamWriter osw =null; String srcPath = "F:\\document\\APK\\new\\iGouShop.apk"; String content= "channel_id=LD20120926"; File srcFile = new File(srcPath); String parentPath = srcFile.getParent(); //源文件目录 String fileName = srcFile.getName(); //源文件名称 String prefixName = fileName.substring(0, fileName.lastIndexOf(".")); //解压源文件保存路径 String sourcePath = buffer.append(parentPath).append(SOURCE_PATH_NAME). append(prefixName).append("\\").toString(); //------解压 unZip(srcPath, sourcePath); //------删除解压后的签名文件 String signPathName = sourcePath+SIGN_PATH_NAME; File signFile = new File(signPathName); if(signFile.exists()){ File sonFiles[] = signFile.listFiles(); if(sonFiles!=null && sonFiles.length>0){ //循环删除签名目录下的文件 for(File f : sonFiles){ f.delete(); } } signFile.delete(); } //------修改内容 buffer.setLength(0); String path = buffer.append(parentPath).append(SOURCE_PATH_NAME) .append(prefixName).append(UPDATE_PATH_NAME).toString(); br = new BufferedReader(new InputStreamReader(new FileInputStream(path))); while((br.readLine())!=null) { osw = new OutputStreamWriter(new FileOutputStream(path)); osw.write(content,0,content.length()); osw.flush(); } //------打包 String targetPath = parentPath+TARGET_PATH_NAME; //判断创建文件夹 File targetFile = new File(targetPath); if(!targetFile.exists()){ targetFile.mkdir(); } compress(parentPath+SOURCE_PATH_NAME+prefixName,targetPath+fileName); //------签名 File ff =new File(JDK_BIN_PATH); String resultPath = parentPath+RESULT_PATH_NAME; //判断创建文件夹 File resultFile = new File(resultPath); if(!resultFile.exists()){ resultFile.mkdir(); } //组合签名命令 buffer.setLength(0); buffer.append("cmd.exe /c jarsigner -keystore ") .append(SECRET_KEY_PATH).append(SECRET_KEY_NAME) .append(" -storepass winadsdk -signedjar ") .append(resultPath).append(fileName).append(" ") //签名保存路径应用名称 .append(targetPath).append(fileName).append(" ") //打包保存路径应用名称 .append(SECRET_KEY_NAME); //利用命令调用JDK工具命令进行签名 Process process = Runtime.getRuntime().exec(buffer.toString(),null,ff); if(process.waitFor()!=0)System.out.println("文件打包失败!!!"); } }
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
mac下如何使用appledoc生成文档
前言 近期手头项目需要出一下文档,方便使用者查阅。调研了目前比较流行的三款文档生成工具HeaderDoc,Doxygen,appledoc。 Doxygen Doxygen是C++源码生成文档的标准工具,同时也支持很多其它语言如:C,Objective-C,C#,PHP,Java,Python等等。然而,它生成的文档风格和官方文档的风格差了十万八千里,并且配置复杂。 HeaderDoc HeaderDoc是苹果官方的文档生成工具。Xcode9以前在安装完Xcode后就可以使用,Xcode9是个重构版本,并没有继承这个。该工具对注释生成规则比较特别,只生成以/*! */ 的格式的注释。生成文档是分散的,并没有一个汇总文件。 appledoc appledoc只专注Objective-C源代码,并且能生成和苹果官方相同风格的文档。同时支持生成html和直接编译成docset安装进Xcode。代码开源在github上,作者会及时跟开发者沟通。 安装 官方推荐做法是克隆GitHub项目并从Xcode编译该工具。由于克隆GitHub项目将创建与主存储库的链接,它也极大地简化了未来的升级。要进行安...
- 下一篇
【翻译】V8 JavaScript 引擎之延迟反序列化
原文链接 Lazy deserialization 延迟反序列化(Lazy deserialization) 延迟反序列化(Lazy deserialization)功能在 V8 6.4 中默认打开了,带来的好处就是平均每个 Chrome 的选项卡可以节约500KB左右的内存消耗。 如果你对这个话题感兴趣,可以继续往下读,否则就不用浪费时间了。 V8 快照介绍 首先,我们回顾一下 V8 是如何堆快照来加速 Isolate(基本上等同于Chrome里面的选项卡)创建的。google的郭扬有个很好的介绍文章自定义启动快照: JavaScript 规范包含许多内置功能,例如从数学函数到全功能的正则表达式引擎。每个新创建的 V8 上下文(V8 context)从开始就可以使用这些功能。为此,必须在创建上下文时在 V8 的堆上初始化这些功能,将全局对象
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
-
Docker使用Oracle官方镜像安装(12C,18C,19C)
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS8编译安装MySQL8.0.19
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
推荐阅读
最新文章
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS8编译安装MySQL8.0.19
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- SpringBoot2整合Redis,开启缓存,提高访问速度
- CentOS关闭SELinux安全模块
- Hadoop3单机部署,实现最简伪集群
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- SpringBoot2全家桶,快速入门学习开发网站教程
- SpringBoot2更换Tomcat为Jetty,小型站点的福音