標籤: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