标签:android签名apk apk签名 apk解压 apk压缩
记得上次在南昌中兴的一个项目中遇到过一个这样的需求:一个app可以给多个渠道商去运营,渠道商推广出去可以获得相应的推广金额。那么这种情况下就必须要使得这个app能够唯一的标志一个渠道商。那个时候我们在这个项目中的解决方案是:让用户在app中手动填入渠道商的工号,我现在想想这种方式也是醉了,真不知道那个时候项目经理是怎么想的,竟然会给出这样的方案。
这次的项目中又遇到了这个问题:需求是这个app能够给多个渠道商去推广,渠道商可以获得推广金额。这次我提出的解决方案是:先把打包后的app解压,然后在assets目录中写入渠道商的唯一标识id,然后压缩app,压缩完毕重新签名app,之后就大工告成。用户在第一次进入app的时候,会把assets中的id读出来,提交到服务器,就完美的解决了这个用户是此渠道商的推广所获得的用户。
首先第一步:把app解压,删除META-INF文件夹中的CERT.RSA和CERT.SF两个文件
第二步:读取解压后的assets目录中的id.txt文件,写入渠道商的id
<span style="white-space:pre"> </span>File file = new File("d:/app/assets/id.txt"); OutputStream outputStream = new FileOutputStream(file); outputStream.write(user.getId().toString().getBytes()); outputStream.flush(); outputStream.close();第三步:压缩写入渠道商id后的所有app文件
<span style="white-space:pre"> </span>ZipCompressor zc = new ZipCompressor("d:/play.apk"); zc.compressExe("d:/app/");具体的压缩代码如下:
package com.xyc.signSystem.utils; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.util.zip.CRC32; import java.util.zip.CheckedOutputStream; import org.apache.tools.zip.ZipEntry; import org.apache.tools.zip.ZipOutputStream; /** * @ClassName: ZipCompressor * @author :andywuchuanlong QQ:312037487 * @Description: 压缩文件的通用工具类-采用org.apache.tools.zip.ZipOutputStream实现,较复杂。 * */ public class ZipCompressor { static final int BUFFER = 8192; private File zipFile; /** * 压缩文件构造函数 * * @param pathName * 压缩的文件存放目录 */ public ZipCompressor(String pathName) { zipFile = new File(pathName); } /** * 执行压缩操作 * * @param srcPathName * 被压缩的文件/文件夹 */ public void compressExe(String srcPathName) { File file = new File(srcPathName); if (!file.exists()) { throw new RuntimeException(srcPathName + "不存在!"); } try { FileOutputStream fileOutputStream = new FileOutputStream(zipFile); CheckedOutputStream cos = new CheckedOutputStream(fileOutputStream, new CRC32()); ZipOutputStream out = new ZipOutputStream(cos); String basedir = ""; compressByType(file, out, basedir); out.close(); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } } /** * 判断是目录还是文件,根据类型(文件/文件夹)执行不同的压缩方法 * * @param file * @param out * @param basedir */ private void compressByType(File file, ZipOutputStream out, String basedir) { if (basedir.equals("play/")) { basedir = ""; } /* 判断是目录还是文件 */ if (file.isDirectory()) { this.compressDirectory(file, out, basedir); } else { this.compressFile(file, out, basedir); } } boolean isFirst = true; /** * 压缩一个目录 * * @param dir * @param out * @param basedir */ private void compressDirectory(File dir, ZipOutputStream out, String basedir) { if (!dir.exists()) { return; } if (basedir.equals("play/")) { basedir = ""; } File[] files = dir.listFiles(); for (int i = 0; i < files.length; i++) { /* 递归 */ compressByType(files[i], out, basedir + dir.getName() + "/"); } } /** * 压缩一个文件 * * @param file * @param out * @param basedir */ private void compressFile(File file, ZipOutputStream out, String basedir) { if (!file.exists()) { isFirst = false; return; } if (basedir.equals("play/")) { basedir = ""; } try { BufferedInputStream bis = new BufferedInputStream( new FileInputStream(file)); ZipEntry entry = new ZipEntry(basedir + file.getName()); out.putNextEntry(entry); int count; byte data[] = new byte[BUFFER]; while ((count = bis.read(data, 0, BUFFER)) != -1) { out.write(data, 0, count); } bis.close(); } catch (Exception e) { throw new RuntimeException(e); } } }
第四步:压缩完毕之后,此时的包是没有签名过的,所以还需要签名,签名可以使用jarsigner工具,首先我们要寻找到java的安装目录
<span style="white-space:pre"> </span>public String getJavaPath() { String javaPath = (String) System.getenv("Path"); String paths[]= javaPath.split(";"); String myPath = null; for(String path:paths){ if (path.contains("Java")&&!path.contains("jre") &&path.contains("bin") ){ myPath = path; break; } } return myPath+"\\"; }
签名:
<span style="white-space:pre"> </span>String javaPath = getJavaPath(); Runtime rt = Runtime.getRuntime(); String cmd = javaPath + "jarsigner -verbose" + " -keystore "+ keystorePath + " -storepass player"// 密码 + " -signedjar "+signedApkPath // 签名后的apk存放位置 + " -digestalg SHA1 -sigalg MD5withRSA " + unsignedApkPath//未签名的apk + " player";// 别名 Process child = rt.exec(cmd);
OK,签名成功。
项目解决方案:解压app — 写入文件 — 压缩app — jarsigner重新签名app — 安装app
标签:android签名apk apk签名 apk解压 apk压缩
原文地址:http://blog.csdn.net/andywuchuanlong/article/details/46673879