码迷,mamicode.com
首页 > 移动开发 > 详细

项目解决方案:解压app — 写入文件 — 压缩app — jarsigner重新签名app — 安装app

时间:2015-06-29 10:13:46      阅读:182      评论:0      收藏:0      [点我收藏+]

标签: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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!