通过Java实现apk 解压、修改、打包、签名

安度博客?通过Java实现apk 解压、修改、打包、签名

通过Runtime.getRuntime().exec 调用命令的方式对APK进行 解压、打包、签名。此文不同之处在于应用java.util.zip对APK进行解压、打包,感觉说得有点多,直接上代码。

    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 : 文件解压/打包工具 */publicclassZipUtil{privatestaticfinalint BUFFER =1024;privatestaticfinalString BASE_DIR ="";/**符号"/"用来作为目录标识判断符*/privatestaticfinalString PATH ="/";/**签名目录*/privatestaticfinalString SIGN_PATH_NAME ="META-INF";/**修改文件目录*/privatestaticfinalString UPDATE_PATH_NAME ="\\res\\raw\\channel";/**解压源文件目录*/privatestaticfinalString SOURCE_PATH_NAME ="\\source\\";/**打包目录*/privatestaticfinalString TARGET_PATH_NAME ="\\target\\";/**签名目录*/privatestaticfinalString RESULT_PATH_NAME ="\\result\\";/**JDK BIN 目录*/privatestaticfinalString JDK_BIN_PATH ="C:\\Program Files\\Java\\jdk1.6.0_26\\bin";/**密钥 目录*/privatestaticfinalString SECRET_KEY_PATH ="F:\\document\\APK\\";/**密钥 名称*/privatestaticfinalString SECRET_KEY_NAME ="sdk.keystore";/** * 解压缩zip文件 * @param fileName 要解压的文件名 包含路径 如:"c:\\test.zip" * @param filePath 解压后存放文件的路径 如:"c:\\temp" * @throws Exception */@SuppressWarnings("rawtypes")publicstaticvoid unZip(String fileName,String filePath)throwsException{ZipFile zipFile =newZipFile(fileName);Enumeration emu = zipFile.getEntries();while(emu.hasMoreElements()){ZipEntry entry =(ZipEntry) emu.nextElement();if(entry.isDirectory()){newFile(filePath+entry.getName()).mkdirs();continue;}BufferedInputStream bis =newBufferedInputStream(zipFile.getInputStream(entry));File file =newFile(filePath + entry.getName());File parent = file.getParentFile();if(parent !=null&&(!parent.exists())){ parent.mkdirs();}FileOutputStream fos =newFileOutputStream(file);BufferedOutputStream bos =newBufferedOutputStream(fos,BUFFER);byte[] buf =newbyte[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 */publicstaticvoid compress(String srcFile,String destPath)throwsException{compress(newFile(srcFile),newFile(destPath));}/** * 压缩 * * @param srcFile * 源路径 * @param destPath * 目标路径 * @throws Exception */publicstaticvoid compress(File srcFile,File destFile)throwsException{// 对输出文件做CRC32校验CheckedOutputStream cos =newCheckedOutputStream(newFileOutputStream(destFile),new CRC32());ZipOutputStream zos =newZipOutputStream(cos);compress(srcFile, zos, BASE_DIR);zos.flush();zos.close();}/** * 压缩 * * @param srcFile * 源路径 * @param zos * ZipOutputStream * @param basePath * 压缩包内相对路径 * @throws Exception */privatestaticvoid compress(File srcFile,ZipOutputStream zos,String basePath)throwsException{if(srcFile.isDirectory()){compressDir(srcFile, zos, basePath);}else{compressFile(srcFile, zos, basePath);}}/** * 压缩目录 * * @param dir * @param zos * @param basePath * @throws Exception */privatestaticvoid compressDir(File dir,ZipOutputStream zos,String basePath)throwsException{File[] files = dir.listFiles();// 构建空目录if(files.length <1){ZipEntry entry =newZipEntry(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 */privatestaticvoid compressFile(File file,ZipOutputStream zos,String dir)throwsException{/** * 压缩包内文件名定义 * * * 如果有多级目录,那么这里就需要给出包含目录的文件名 * 如果用WinRAR打开压缩包,中文名将显示为乱码 **/if("/".equals(dir))dir="";elseif(dir.startsWith("/"))dir=dir.substring(1,dir.length());ZipEntry entry =newZipEntry(dir + file.getName());zos.putNextEntry(entry);BufferedInputStream bis =newBufferedInputStream(newFileInputStream(file));int count;byte data[]=newbyte[BUFFER];while((count = bis.read(data,0, BUFFER))!=-1){zos.write(data,0, count);}bis.close();zos.closeEntry();}publicstaticvoid main(String[] args)throwsException{StringBuffer buffer =newStringBuffer();BufferedReader br =null;OutputStreamWriter osw =null;String srcPath ="F:\\document\\APK\\new\\iGouShop.apk";String content="channel_id=LD20120926";File srcFile =newFile(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 =newFile(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 =newBufferedReader(newInputStreamReader(newFileInputStream(path)));while((br.readLine())!=null){osw =newOutputStreamWriter(newFileOutputStream(path));osw.write(content,0,content.length());osw.flush();}//------打包String targetPath = parentPath+TARGET_PATH_NAME;//判断创建文件夹File targetFile =newFile(targetPath);if(!targetFile.exists()){targetFile.mkdir();}compress(parentPath+SOURCE_PATH_NAME+prefixName,targetPath+fileName);//------签名File ff =newFile(JDK_BIN_PATH);String resultPath = parentPath+RESULT_PATH_NAME;//判断创建文件夹File resultFile =newFile(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("文件打包失败!!!");}}

有事者,事竟成;破釜沉舟,百二秦关终归楚;苦心人,

通过Java实现apk 解压、修改、打包、签名

相关文章:

你感兴趣的文章:

标签云: