众所周知,给apk进行签名,使用

jarsigner -verbose -keystore android.keystore -signedjar 签名后.apk 待签名.apk 

命令

这是有android.keystore文件时,给apk签名,签名时,要输入密码

还有一种情况,就是有platform.pk8和platform.x509.pem这两个文件时,给apk签名(让apk有系统签名),这个时候用

java -jar signapk.jar  platform.x509.pem  platform.pk8 待签名.apk 签名后.apk

这个需要signapk.jar包,这个jar包可以从android源码编译得到,

网上进行自动批量签名,都是采用第二种方式,但前提是得有 pem 和 pk8文件

所以第一步就是把keystore文件转换成 pem 和 pk8 文件

转换过程见        keystore文件转换格式为pk8+x509.pem    日记

接下来,就是要做批量处理代码,我看网上的,大都是采用脚本来处理,基本思路是先得到所有待签名的apk,再循环对每个apk进行签名,本人对脚本不是很在行,于是就用java来写了个批处理文件

批量签名采用的是都是signapk.jar,但是如果用java来写的话,那么就会有一个问题:如何在java文件中,调用jar文件?

不好意思,这个问题我也没解决,如果有哪位高人知道,请指教。

我的处理方式是绕过了这个问题,因为signapk.jar文件是由android源码文件生成的,我找到了SignApk.java源码

SignApk.java路径:

    android\jb_4.2\build\tools\signapk

有了源码,那什么都好办了,但还有个问题,SignApk.java引用到了两个jar包:

LOCAL_STATIC_JAVA_LIBRARIES := bouncycastle-host bouncycastle-bcpkix-host

(在 Android.mk文件中有指出)

那么我就在源码中,全局搜这两个包,

./external/bouncycastle/Android.mk:81:    LOCAL_MODULE := bouncycastle-hostdex

./external/bouncycastle/Android.mk:102:    LOCAL_MODULE := bouncycastle-bcpkix-host

bouncycastle-host.jar    bouncycastle-bcpkix-host.jar    就可以了

这两个包在android\jb_4.2\out\host\linux-x86\framework 目录下

源文件都准备好了,开干:

先建立一个java工程

里面有一个Main.java文件,

public class Main {
 
 
 public static void main(String[] args) {
 
  // TODO Auto-generated method stub
 
  // 当前目录用"./"
 
  File dist = new File("./签名后的apk");
 
  // 创建目录
 
  if (!dist.exists()) {
 
   dist.mkdirs();
 
   System.out.print("创建目录:  签名后的apk");
 
  }
 
 
  ArrayList<File> list = FileTools.getAllApks("./");
 
  System.out.print(list.size());
 
 
  String pem = FileTools.getPem("./");
 
  String pk8 = FileTools.getPk8("./");
 
 
  if (pem == null || pk8 == null) {
 
   System.out.print("没找到密钥和公钥文件!!!");
 
   return;
 
  }
 
 
  for (File file : list) {
 
   // 签名参数
 
   System.out.print("创建签名参数");
 
   String[] tem = new String[] { pem, pk8, file.getName(),
 
     dist.getAbsolutePath() + "/" + file.getName() };
 
   System.out.print("签名参数=" + Arrays.toString(tem));
 
   // 对每个apk文件进行签名
 
   SignApk.signApkMain(tem);
 
   System.out.print("签名完成");
 
  }
 
 
 }
 
 
}

这里引用到了一个工具类:FileToos.java

package com.ytmfdw.sign;
 
 
import java.io.File;
 
import java.io.FileFilter;
 
import java.util.ArrayList;
 
 
public class FileTools {
 
 
 public static ArrayList<File> getAllApks(String path) {
 
  ArrayList<File> files = new ArrayList<>();
 
 
  File file = new File(path);
 
  if (file.exists() && file.isDirectory()) {
 
   File[] list = file.listFiles(new FileFilter() {
 
 
    @Override
 
    public boolean accept(File pathname) {
 
     // TODO Auto-generated method stub
 
     if (pathname.getName().toLowerCase().endsWith(".apk")) {
 
      return true;
 
     }
 
     return false;
 
    }
 
   });
 
 
   for (File f : list) {
 
    files.add(f);
 
 
   }
 
  }
 
 
  return files;
 
 }
 
 
 /**
 
  * 获取cert.x509.pem 如果有两个后缀为pem,则以第一个为准
 
  * */
 
 public static String getPem(String path) {
 
 
  File file = new File(path);
 
  if (file.exists()) {
 
   if (file.isDirectory()) {
 
    File[] files = file.listFiles(new FileFilter() {
 
 
     @Override
 
     public boolean accept(File pathname) {
 
      // TODO Auto-generated method stub
 
      if (pathname.getName().toLowerCase().endsWith(".pem")) {
 
       return true;
 
      }
 
      return false;
 
     }
 
    });
 
 
    if (files.length > 0) {
 
     return files[0].getName();
 
    }
 
   }
 
  }
 
 
  return null;
 
 }
 
 
 /**
 
  * 获取private.pk8 如果有两个后缀为pk8,则以第一个为准
 
  * */
 
 public static String getPk8(String path) {
 
 
  File file = new File(path);
 
  if (file.exists()) {
 
   if (file.isDirectory()) {
 
    File[] files = file.listFiles(new FileFilter() {
 
 
     @Override
 
     public boolean accept(File pathname) {
 
      // TODO Auto-generated method stub
 
      if (pathname.getName().toLowerCase().endsWith(".pk8")) {
 
       return true;
 
      }
 
      return false;
 
     }
 
    });
 
 
    if (files.length > 0) {
 
     return files[0].getName();
 
    }
 
   }
 
  }
 
 
  return null;
 
 }
 
}

  SignApk.signApkMain 这个方法是没有的,其实这个方法就是SignApk中的main()函数

java文件中,只要有一个main()函数,所以这个名字我改了下

除了这个地方报错外,SignApk的引用,也报错,源码中,定义是这样写的:class SignApk {

所以其他包中,没有权限引用这个类,所以要改成        

        public class SignApk{

bouncycastle-host.jar     bouncycastle-bcpkix-host.jar  引用进来就可以了,基本上大功告成

bouncycastle-host.jar , bouncycastle-bcpkix-host.jar这三个文件,然后是修改SignApk.java文件:

改两处:

类权限:      class SignApk {     ===改成==>      public class SignApk{

                       

主方法:    public static void main(String[] args) {       =改成==>        public static void signApkMain(String[] args) {

其他基本上没什么问题