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;// root directory 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---- decompress //apktool path //String path = "E:\\apktool\\apktool.bat"; //save route 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("Failed to decompress!"); //2----Add json file 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----Package // 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("Packaging failed!"); //4----Signature (file name cannot contain spaces) //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("Signature failed..."); } }catch (Exception e) { e.printStackTrace (); }finally{ /* br.close(); osw.close (); * / } } public static void CreateJson(String fPath/*,String json*/) { // mark whether the file was generated successfully boolean flag = true; // The full path of the concatenated file String fullPath =fPath+ File.separator + "config.json"; // Generate json format file try { // Make sure to create a new file File file = new File(fullPath); if (!file.getParentFile().exists()) { // If the parent directory does not exist, create the parent directory file.getParentFile().mkdirs(); } if (file.exists()) { // if it already exists, delete the old file file.delete(); } file.createNewFile(); // format json string // write formatted string to file 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 (); } } }
The above is the pure code with the help of 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 am * explain : file decompression/packaging tool */ public class ZipUtil { private static final int BUFFER = 1024; private static final String BASE_DIR = ""; /**The symbol "/" is used as a directory identifier */ private static final String PATH = "/"; /**Signature directory*/ private static final String SIGN_PATH_NAME = "META-INF"; /**Modify file directory*/ private static final String UPDATE_PATH_NAME = "\\res\\raw\\channel"; /**Extract source file directory*/ private static final String SOURCE_PATH_NAME = "\\source\\"; /**Packaging directory*/ private static final String TARGET_PATH_NAME = "\\target\\"; /**Signature directory*/ private static final String RESULT_PATH_NAME = "\\result\\"; /**JDK BIN directory*/ private static final String JDK_BIN_PATH = "C:\\Program Files\\Java\\jdk1.6.0_26\\bin"; /**Key directory*/ private static final String SECRET_KEY_PATH = "F:\\document\\APK\\"; /**Key name*/ private static final String SECRET_KEY_NAME = "sdk.keystore"; /** * Unzip the zip file * @param fileName The file name to be decompressed contains the path such as: "c:\\test.zip" * @param filePath The path to store the file after decompression, such as: "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(); } /** * Compressed file * * @param srcFile * @param destPath * @throws Exception */ public static void compress(String srcFile, String destPath) throws Exception { compress(new File(srcFile), new File(destPath)); } /** * Compression * * @param srcFile * source path * @param destPath * Target path * @throws Exception */ public static void compress(File srcFile, File destFile) throws Exception { // Do CRC32 check on the output file CheckedOutputStream cos = new CheckedOutputStream(new FileOutputStream( destFile), new CRC32()); ZipOutputStream zos = new ZipOutputStream(cos); compress(srcFile, zos, BASE_DIR); zos.flush (); zos.close(); } /** * Compression * * @param srcFile * source path * @param zos * ZipOutputStream * @param basePath * Relative path in the compressed package * @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); } } /** * compressed directory * * @param dir * @param zos * @param basePath * @throws Exception */ private static void compressDir(File dir, ZipOutputStream zos, String basePath) throws Exception { File[] files = dir.listFiles(); // build empty directory 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) { //When the parent file package name is empty, the package name will not be added to the path (mainly to solve the compression, the parent directory file will also be packaged) if(basePath!=null && !"".equals(basePath)){ dirName=dir.getName(); } path = basePath + dirName + PATH; // recursive compression compress(file, zos, path); } } /** * File compression * * @param file * file to be compressed * @param zos * ZipOutputStream * @param dir * The current path in the compressed file * @throws Exception */ private static void compressFile(File file, ZipOutputStream zos, String dir) throws Exception { /** * Definition of file name in the compressed package * * <pre> * If there are multiple levels of directories, then the file name of the containing directory needs to be given here * If you open the archive with WinRAR, the Chinese name will be displayed as garbled characters * </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(); //Source file directory String fileName = srcFile.getName(); //source file name String prefixName = fileName.substring(0, fileName.lastIndexOf(".")); / / Extract the source file save path String sourcePath = buffer.append(parentPath).append(SOURCE_PATH_NAME). append(prefixName).append("\\").toString(); //------ decompress unZip(srcPath, sourcePath); //------Delete the decompressed signature file String signPathName = sourcePath+SIGN_PATH_NAME; File signFile = new File(signPathName); if(signFile.exists()){ File sonFiles[] = signFile.listFiles(); if(sonFiles!=null && sonFiles.length>0){ / / Loop delete files in the signature directory for(File f : sonFiles){ f.delete(); } } signFile.delete(); } //------ Modify the content 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(); } //------Pack String targetPath = parentPath+TARGET_PATH_NAME; // Judge to create a folder File targetFile = new File(targetPath); if(!targetFile.exists()){ targetFile.mkdir(); } compress(parentPath+SOURCE_PATH_NAME+prefixName,targetPath+fileName); //------sign File ff =new File(JDK_BIN_PATH); String resultPath = parentPath+RESULT_PATH_NAME; // Judge to create a folder File resultFile = new File(resultPath); if(!resultFile.exists()){ resultFile.mkdir(); } // Combine the signature command 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(" ") //Signature save path application name .append(targetPath).append(fileName).append(" ") //Package save path application name .append(SECRET_KEY_NAME); //Use the command to call the JDK tool command to sign Process process = Runtime.getRuntime().exec(buffer.toString(),null,ff); if(process.waitFor()!=0)System.out.println("File packaging failed!!!"); } }