您的位置:首页 > 移动开发 > Android开发

关于android的程序签名

2011-02-13 19:45 417 查看
http://www.cnblogs.com/jeromeliu/archive/2010/11/23/1885244.html

 

 

我以前在做android杂志时候遇到一个需求,要求是开发人员开发完第一版本杂志后,后面的版本只需要通过工具改变文字内容和图片重新签名就可以出第二个版本,不用重新改源码进行编译打包。我把所有可能改变的资源都放在assets 目录下,在程序中通过名字来获取资源,这样就不用重新编译了,但是签名呢?怎样通过工具来程序签名呢?

一: 生成未签名的apk包.

  把res, resources.arsc, classes.dex, AndroidMainfest.xml, assets等资源打包成apk。   apk 是采用的zip压缩方式,但是资源中图片和音乐是不压缩的,也就是图片和音乐要保持原大小。

 


代码

 1 private void zip(String zipFileName) throws Exception {
2 ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFileName));
3 File resFile = new File("d:/res");
4 File resourceFile = new File("d:/resources.arsc");
5 File manifestFile = new File("d:/AndroidManifest.xml");
6 File classFile = new File("d:/classes.dex");
7 File assetsFile = new File("d:/assets");
8 zip(out, resFile, resFile.getName());
9 zip(out, resourceFile, resourceFile.getName());
10 zip(out, manifestFile, manifestFile.getName());
11 zip(out, classFile, classFile.getName());
12 zip(out, assetsFile, assetsFile.getName());
13 System.out.println("zip done");
14 out.close();
15 }
16
17 private void zip(ZipOutputStream out, File f, String base) throws Exception {
18 if (f.isDirectory()) {
19 File[] fl = f.listFiles();
20 out.setMethod(ZipOutputStream.DEFLATED);
21 out.putNextEntry(new ZipEntry(base + "/"));
22 base = base.length() == 0 ? "" : base + "/";
23 for (int i = 0; i < fl.length; i++) {
24 zip(out, fl[i], base + fl[i].getName());
25 }
26 }else {
27 FileInputStream in = new FileInputStream(f);
28 byte []data = new byte[in.available()];
29 in.read(data);
30 in.close();
31 if(f.getName().endsWith(".jpg") || f.getName().endsWith(".png") || f.getName().endsWith(".mp3") || f.getName().endsWith(".arsc")){
32 //图片和音乐不压缩
33   out.setMethod(ZipOutputStream.STORED);
34 ZipEntry zip = new ZipEntry(base);
35 zip.setMethod(ZipEntry.STORED);
36 zip.setSize(data.length);
37 CRC32 tempCrc = new CRC32();
38 tempCrc.update(data);
39 zip.setCrc(tempCrc.getValue());
40 out.putNextEntry(zip);
41
42 }else{
43 out.setMethod(ZipOutputStream.DEFLATED);
44 out.putNextEntry(new ZipEntry(base));
45
46 }
47
48 out.write(data);
49 }
50 }

 

 

二.  对apk包进行签名.
看了博文;,下面是我的解决方法,希望有朋友用的着。
首先需要android自带的私钥 和公钥testkey.zip 
还有SignApk.java.

在signApk.java中的main(String []args)方法中 参数args这里我们无法传入,我们只有到程序中自己赋值。

 


代码

public static void main(String[] args) {
2 args = new String[]{"d:/testkey.x509.pem","d:/testkey.pk8", "d:/lyl.apk", "d:/lyl1.apk"}; //第一个参数是公钥,第二个参数是私钥, 第三个参数是需要签名的apk, 第四个参数是签名后生成的apk
3
4 JarFile inputJar = null;
5 JarOutputStream outputJar = null;
6
7 try {
8 X509Certificate publicKey = readPublicKey(new File(args[0]));
9 PrivateKey privateKey = readPrivateKey(new File(args[1]));
10 inputJar = new JarFile(new File(args[2]), false); // Don't verify.
11 outputJar = new JarOutputStream(new FileOutputStream(args[3]));
12 outputJar.setLevel(9);
13
14 // MANIFEST.MF
15 Manifest manifest = addDigestsToManifest(inputJar);
16 manifest.getEntries().remove("META-INF/CERT.SF");
17 manifest.getEntries().remove("META-INF/CERT.RSA");
18 outputJar.putNextEntry(new JarEntry(JarFile.MANIFEST_NAME));
19 manifest.write(outputJar);
20
21 // CERT.SF
22 Signature signature = Signature.getInstance("SHA1withRSA");
23 signature.initSign(privateKey);
24 outputJar.putNextEntry(new JarEntry("META-INF/CERT.SF"));
25 writeSignatureFile(manifest,
26 new SignatureOutputStream(outputJar, signature));
27
28 // CERT.RSA
29 outputJar.putNextEntry(new JarEntry("META-INF/CERT.RSA"));
30 writeSignatureBlock(signature, publicKey, outputJar);
31
32 // Everything else
33 copyFiles(manifest, inputJar, outputJar);
34 } catch (Exception e) {
35 e.printStackTrace();
36 System.exit(1);
37 } finally {
38 try {
39 if (inputJar != null) inputJar.close();
40 if (outputJar != null) outputJar.close();
41 } catch (IOException e) {
42 e.printStackTrace();
43 System.exit(1);
44 }
45 }
46 }

执行完signApk后签名完成,可以安装应用程序了,呵呵。

 

 源代码:SignApkUtil.zip
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息