Java 服务器端修改apk并重新打包签名

/ AndroidJava / 没有评论 / 2521浏览

前言:因项目需要,需要对已有的app进行一部分修改,所以花费了一天时间来研究这个东西,在网上查了很多资料,发现大多数都是简单的说明或雷同,所以特此把成果分享下,希望对大家有用。

1. 环境要求 jdk.17

2. 需要工具 apktool

2.1 这个是Google推出的工具,就只为了针对这种情况,因为apk相当于一个压缩包,可以用压缩工具就可以打开,可能很多人都试过直接用压缩软件打开apk并修改保存,但是最后却不能安装

2.2 下载地址:http://www.softpedia.com/get/Programming/Debuggers-Decompilers-Dissasemblers/ApkTool.shtml

2.3 需要下载apktool2.0.2.jar 和apktool-install-windows-r05-ibot.tar.bz2

2.4下载下来之后会发现有三个文件aapt.exe你,apktool.bat,apktool.jar(将前面的apktool2.0.2.jar改名成apktool.jar),然后将这三个文件放到C:\Windows下面

2.5打开doc窗口 输入cmd 进入后输入apktool 就可以看见对应的命令

3. 一个Android app 和对应的签名秘钥文件(可以找Android开发人员要)

3.1将其放入一个文件夹下E:\apkTest

3.2不放心的可以先把这两个文件备份下

  1. Java 代码部分
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

/**
* @author showlike
* @version v1.0 
* 2012-6-29 下午12:05:10 
*/
public class Test {

    public static void main(String args[]) throws IOException{

        BufferedReader br =null;
        OutputStreamWriter osw =null;
        Process process = null;
        try {

            //1----解压
            //apktool路径
            String newApppath ="E:\\apkTest\";
            //保存路径
            String appPath ="E:\\apkTest\";
            //File file =new File(path);
            String cmd_d="cmd.exe /c apktool d "+appPath
                +"Taximeter_1.apk -o "+newApppath+"app";
            System.out.println(cmd_d);
            process = Runtime.getRuntime().exec(cmd_d);

            if(process.waitFor()!=0)System.out.println("解压失败。。。");

            //2----内容修改
            String targetPath = newApppath+"app\\assets\\presenter.txt";
            String content="15926322029";
            System.out.println(targetPath);
            br = new BufferedReader(new InputStreamReader(
                new FileInputStream(targetPath)));
            osw = new OutputStreamWriter(new FileOutputStream(targetPath)); 
            osw.write(content,0,content.length());
            osw.flush();

            //3----打包
            process = Runtime.getRuntime().exec(
                "cmd.exe /c apktool b "+newApppath+"app -o "+newApppath+"app.apk");
            if(process.waitFor()!=0)System.out.println("打包失败。。。");
            //4----签名 (文件名称中不能包含空格)
            String jdkBinPath="D:\\Program Files\\Java\\jdk1.7.0_79\\bin";
            File bin =new File(jdkBinPath);

            /**
              *E:\\apkTest\\taximeter.jks  表示签名的秘钥包
               \* 54546645   是签名包的密码
                *E:\\apkTest\\app.apk 修改原有app并重新打包成app的文件
               *E:\\apkTest\\appT.apk 签名后的apk名字和位置
            **/
            String cmd="cmd.exe /c jarsigner -verbose -keystore E:\\apkTest\\taximeter.jks -storepass 54546645 -keypass 54546645 -signedjar E:\\apkTest\\appT.apk -digestalg SHA1 -sigalg MD5withRSA E:\\apkTest\\app.apk taximeter";
            process = Runtime.getRuntime().exec(cmd,null,bin);
            //Runtime.getRuntime().exec执行的时候有时候会阻塞了,
            // 就是你运行了但一直不结束,所以就增加下面的功能来处理
            StreamGobbler errorGobbler = new StreamGobbler(
                process.getErrorStream(), "ERROR");              
            // kick off stderr  
            errorGobbler.start();  
            StreamGobbler outGobbler = new StreamGobbler(
                process.getInputStream(), "STDOUT");  
            // kick off stdout  
            outGobbler.start(); 
            process=Runtime.getRuntime().exec(cmdArray);
            if(process.waitFor()!=0)System.out.println("签名失败。。。");
        }catch (Exception e){
            e.printStackTrace();
        }finally{
            br.close();
            osw.close();
            System.out.println("结束。。。");
        }
    }
}

      
import java.io.BufferedReader;  
import java.io.IOException;  
import java.io.InputStream;  
import java.io.InputStreamReader;  
import java.io.OutputStream;  
import java.io.PrintWriter;  

/** 
  \* 用于处理Runtime.getRuntime().exec产生的错误流及输出流 
  \* @author ybqin
  \* 
  */  
public class StreamGobbler extends Thread {  
    InputStream is;  
    String type;  
    OutputStream os;  

    StreamGobbler(InputStream is, String type) {  
        this(is, type, null);  
    }  

    StreamGobbler(InputStream is, String type, OutputStream redirect) {  
        this.is = is;  
        this.type = type;  
        this.os = redirect;  
    }  

    public void run() {  
        try {
            InputStreamReader isr = null;  
            BufferedReader br = null;  
            PrintWriter pw = null;  
            try {  
                if (os != null)  
                    pw = new PrintWriter(os);  

                isr = new InputStreamReader(is);  
                br = new BufferedReader(isr);  
                String line=null;  
                while ( (line = br.readLine()) != null) {  
                    if (pw != null)  
                        pw.println(line);  
                    System.out.println(type + ">" + line);      
                }  

                if (pw != null)  
                    pw.flush();  
            } catch (IOException ioe) {  
                ioe.printStackTrace();    
            } finally{  
                pw.close();
                br.close();
                isr.close();
            }  
        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        }

    }  
}   

以上功能希望对大家有用,谢谢