Android--解包、添加文件、打包、签名

简介: 版权声明:本文为博主原创文章,转载请标明出处。 https://blog.csdn.net/chaoyu168/article/details/79900485 package zip;import java.
版权声明:本文为博主原创文章,转载请标明出处。 https://blog.csdn.net/chaoyu168/article/details/79900485
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;// 根目录
	  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----解压  
	            //apktool路径  
	            //String path = "E:\\apktool\\apktool.bat";  
	            //保存路径  
	            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("解压失败!");
	            
	        	//2----添加json文件
	            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----打包  
	           // 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("打包失败!");  
	             
	            //4----签名 (文件名称中不能包含空格)  
	           
	            //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("签名失败。。。");  
	            }
	        }catch (Exception e)  
	        {  
	            e.printStackTrace();  
	        }finally{  
	           /* br.close();  
	            osw.close();*/  
	        }  
	    }
	  public static void CreateJson(String fPath/*,String json*/) {
		// 标记文件生成是否成功
          boolean flag = true;
          // 拼接文件完整路径
          String fullPath =fPath+ File.separator + "config.json";
          // 生成json格式文件
          try {
              // 保证创建一个新文件
              File file = new File(fullPath);
              if (!file.getParentFile().exists()) { // 如果父目录不存在,创建父目录
                  file.getParentFile().mkdirs();
              }
              if (file.exists()) { // 如果已存在,删除旧文件
                  file.delete();
              }
              file.createNewFile();
              // 格式化json字符串	             
              // 将格式化后的字符串写入文件
              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();
          }
	  }

}

上面是借助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  
 * explain : 文件解压/打包工具 
 */  
public class ZipUtil {  
    private static final int BUFFER = 1024;   
    private static final String BASE_DIR = "";  
    /**符号"/"用来作为目录标识判断符*/  
    private static final String PATH = "/";  
      
    /**签名目录*/  
    private static final String SIGN_PATH_NAME = "META-INF";      
    /**修改文件目录*/  
    private static final String UPDATE_PATH_NAME = "\\res\\raw\\channel";  
    /**解压源文件目录*/  
    private static final String SOURCE_PATH_NAME = "\\source\\";      
    /**打包目录*/  
    private static final String TARGET_PATH_NAME = "\\target\\";  
    /**签名目录*/  
    private static final String RESULT_PATH_NAME = "\\result\\";  
    /**JDK BIN 目录*/  
    private static final String JDK_BIN_PATH = "C:\\Program Files\\Java\\jdk1.6.0_26\\bin";  
    /**密钥 目录*/  
    private static final String SECRET_KEY_PATH = "F:\\document\\APK\\";  
    /**密钥 名称*/  
    private static final String SECRET_KEY_NAME = "sdk.keystore";  
      
    /**  
    * 解压缩zip文件   
    * @param fileName 要解压的文件名 包含路径 如:"c:\\test.zip"  
    * @param filePath 解压后存放文件的路径 如:"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();    
    }    
      
    /** 
     * 压缩文件 
     *  
     * @param srcFile 
     * @param destPath 
     * @throws Exception 
     */  
    public static void compress(String srcFile, String destPath) throws Exception {  
        compress(new File(srcFile), new File(destPath));  
    }  
      
    /** 
     * 压缩 
     *  
     * @param srcFile 
     *            源路径 
     * @param destPath 
     *            目标路径 
     * @throws Exception 
     */  
    public static void compress(File srcFile, File destFile) throws Exception {  
        // 对输出文件做CRC32校验  
        CheckedOutputStream cos = new CheckedOutputStream(new FileOutputStream(  
                destFile), new CRC32());  
  
        ZipOutputStream zos = new ZipOutputStream(cos);  
        compress(srcFile, zos, BASE_DIR);  
  
        zos.flush();  
        zos.close();  
    }  
      
    /** 
     * 压缩 
     *  
     * @param srcFile 
     *            源路径 
     * @param zos 
     *            ZipOutputStream 
     * @param basePath 
     *            压缩包内相对路径 
     * @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);  
        }  
    }  
      
    /** 
     * 压缩目录 
     *  
     * @param dir 
     * @param zos 
     * @param basePath 
     * @throws Exception 
     */  
    private static void compressDir(File dir, ZipOutputStream zos,  
            String basePath) throws Exception {  
        File[] files = dir.listFiles();  
        // 构建空目录  
        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) {  
            //当父文件包名为空时,则不把包名添加至路径中(主要是解决压缩时会把父目录文件也打包进去)  
            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 
     */  
    private static void compressFile(File file, ZipOutputStream zos, String dir)  
            throws Exception {  
        /** 
         * 压缩包内文件名定义 
         *  
         * <pre> 
         * 如果有多级目录,那么这里就需要给出包含目录的文件名 
         * 如果用WinRAR打开压缩包,中文名将显示为乱码 
         * </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();    //源文件目录  
        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 = new File(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 = 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();    
        }  
          
        //------打包  
        String targetPath = parentPath+TARGET_PATH_NAME;  
        //判断创建文件夹  
        File targetFile = new File(targetPath);  
        if(!targetFile.exists()){  
            targetFile.mkdir();  
        }  
        compress(parentPath+SOURCE_PATH_NAME+prefixName,targetPath+fileName);  
          
        //------签名  
        File ff =new File(JDK_BIN_PATH);  
        String resultPath = parentPath+RESULT_PATH_NAME;  
        //判断创建文件夹  
        File resultFile = new File(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("文件打包失败!!!");  
    }  
}  

目录
相关文章
|
1月前
|
ARouter Android开发
Android不同module布局文件重名被覆盖
Android不同module布局文件重名被覆盖
|
3月前
|
Java Android开发 C++
Android Studio JNI 使用模板:c/cpp源文件的集成编译,快速上手
本文提供了一个Android Studio中JNI使用的模板,包括创建C/C++源文件、编辑CMakeLists.txt、编写JNI接口代码、配置build.gradle以及编译生成.so库的详细步骤,以帮助开发者快速上手Android平台的JNI开发和编译过程。
283 1
|
3月前
|
Android开发
基于android-11.0.0_r39,系统应用的手动签名方法和过程
本文介绍了基于Android 11.0.0_r39版本进行系统应用手动签名的方法和解决签名过程中遇到的错误,包括处理`no conscrypt_openjdk_jni-linux-x86_64`和`RegisterNatives failed`的问题。
187 2
|
3月前
|
安全 Java Android开发
【Android P】OTA升级包定制,移除不需要更新的分区,重新打包签名
如何解压OTA升级包、编辑升级包内容(例如移除不需要更新的分区)、重新打包、签名以及验证OTA文件的过程。
304 2
【Android P】OTA升级包定制,移除不需要更新的分区,重新打包签名
|
1月前
|
ARouter Android开发
Android不同module布局文件重名被覆盖
Android不同module布局文件重名被覆盖
119 0
|
3月前
|
开发工具 git 索引
repo sync 更新源码 android-12.0.0_r34, fatal: 不能重置索引文件至版本 ‘v2.27^0‘。
本文描述了在更新AOSP 12源码时遇到的repo同步错误,并提供了通过手动git pull更新repo工具来解决这一问题的方法。
132 1
|
3月前
|
Java Android开发 Windows
使用keytool查看Android APK签名
本文介绍了如何使用Windows命令行工具和keytool查看APK的签名信息,并提供了使用AOSP环境中的signapk.jar工具对APK进行系统签名的方法。
387 0
使用keytool查看Android APK签名
|
3月前
|
Android开发 数据安全/隐私保护
Android Studio创建JKS签名遇到的坑
Android Studio创建JKS签名遇到的坑
142 1
|
3月前
|
Android开发 开发者
Android、Flutter为不同的CPU架构包打包APK(v7a、v8a、x86)
Android、Flutter为不同的CPU架构包打包APK(v7a、v8a、x86)
295 1
|
3月前
|
存储 监控 数据库
Android经典实战之OkDownload的文件分段下载及合成原理
本文介绍了 OkDownload,一个高效的 Android 下载引擎,支持多线程下载、断点续传等功能。文章详细描述了文件分段下载及合成原理,包括任务创建、断点续传、并行下载等步骤,并展示了如何通过多种机制保证下载的稳定性和完整性。
118 0