zoukankan      html  css  js  c++  java
  • 更改已经签名的app中的内容

    转载请说明出处http://blog.csdn.net/andywuchuanlong

    记得上次在南昌中兴的一个项目中遇到过一个这种需求:一个app能够给多个渠道商去运营,渠道商推广出去能够获得对应的推广金额。

    那么这种情况下就必需要使得这个app能够唯一的标志一个渠道商。

    那个时候我们在这个项目中的解决方式是:让用户在app中手动填入渠道商的工号。我如今想想这种方式也是醉了,真不知道那个时候项目经理是怎么想的,居然会给出这种方案。

    这次的项目中又遇到了这个问题:需求是这个app可以给多个渠道商去推广。渠道商可以获得推广金额。这次我提出的解决方式是:先把打包后的app解压,然后在assets文件夹中写入渠道商的唯一标识id。然后压缩app,压缩完成又一次签名app,之后就大工告成。用户在第一次进入app的时候。会把assets中的id读出来,提交到server,就完美的攻克了这个用户是此渠道商的推广所获得的用户。

    首先第一步:把app解压。删除META-INF目录中的CERT.RSA和CERT.SF两个文件

    第二步:读取解压后的assets文件夹中的id.txt文件,写入渠道商的id

    [java] view plaincopy
    1. File file = new File("d:/app/assets/id.txt");  
    2.         OutputStream outputStream = new FileOutputStream(file);  
    3.         outputStream.write(user.getId().toString().getBytes());  
    4.         outputStream.flush();  
    5.         outputStream.close();  
    第三步:压缩写入渠道商id后的全部app文件

    [java] view plaincopy
    1. ZipCompressor zc = new  ZipCompressor("d:/play.apk");    
    2.         zc.compressExe("d:/app/");  
    详细的压缩代码例如以下:

    [java] view plaincopy
    1. package com.xyc.signSystem.utils;  
    2. import java.io.BufferedInputStream;  
    3. import java.io.File;  
    4. import java.io.FileInputStream;  
    5. import java.io.FileOutputStream;  
    6. import java.util.zip.CRC32;  
    7. import java.util.zip.CheckedOutputStream;  
    8.   
    9. import org.apache.tools.zip.ZipEntry;  
    10. import org.apache.tools.zip.ZipOutputStream;  
    11.   
    12. /** 
    13.  * @ClassName: ZipCompressor 
    14.  * @author :andywuchuanlong   QQ:312037487 
    15.  * @Description: 压缩文件的通用工具类-採用org.apache.tools.zip.ZipOutputStream实现。较复杂。 
    16.  * 
    17.  */  
    18. public class ZipCompressor {  
    19.     static final int BUFFER = 8192;  
    20.     private File zipFile;  
    21.   
    22.     /** 
    23.      * 压缩文件构造函数 
    24.      *  
    25.      * @param pathName 
    26.      *            压缩的文件存放文件夹 
    27.      */  
    28.     public ZipCompressor(String pathName) {  
    29.         zipFile = new File(pathName);  
    30.     }  
    31.   
    32.     /** 
    33.      * 运行压缩操作 
    34.      *  
    35.      * @param srcPathName 
    36.      *            被压缩的文件/目录 
    37.      */  
    38.     public void compressExe(String srcPathName) {  
    39.         File file = new File(srcPathName);  
    40.         if (!file.exists()) {  
    41.             throw new RuntimeException(srcPathName + "不存在!");  
    42.         }  
    43.         try {  
    44.             FileOutputStream fileOutputStream = new FileOutputStream(zipFile);  
    45.             CheckedOutputStream cos = new CheckedOutputStream(fileOutputStream,  
    46.                     new CRC32());  
    47.             ZipOutputStream out = new ZipOutputStream(cos);  
    48.             String basedir = "";  
    49.             compressByType(file, out, basedir);  
    50.             out.close();  
    51.         } catch (Exception e) {  
    52.             e.printStackTrace();  
    53.             throw new RuntimeException(e);  
    54.         }  
    55.     }  
    56.   
    57.     /** 
    58.      * 推断是文件夹还是文件。依据类型(文件/文件夹)运行不同的压缩方法 
    59.      *  
    60.      * @param file 
    61.      * @param out 
    62.      * @param basedir 
    63.      */  
    64.     private void compressByType(File file, ZipOutputStream out, String basedir) {  
    65.         if (basedir.equals("play/")) {  
    66.             basedir = "";  
    67.         }  
    68.         /* 推断是文件夹还是文件 */  
    69.         if (file.isDirectory()) {  
    70.             this.compressDirectory(file, out, basedir);  
    71.         } else {  
    72.             this.compressFile(file, out, basedir);  
    73.         }  
    74.     }  
    75.   
    76.     boolean isFirst = true;  
    77.   
    78.     /** 
    79.      * 压缩一个文件夹 
    80.      *  
    81.      * @param dir 
    82.      * @param out 
    83.      * @param basedir 
    84.      */  
    85.     private void compressDirectory(File dir, ZipOutputStream out, String basedir) {  
    86.         if (!dir.exists()) {  
    87.             return;  
    88.         }  
    89.         if (basedir.equals("play/")) {  
    90.             basedir = "";  
    91.         }  
    92.         File[] files = dir.listFiles();  
    93.         for (int i = 0; i < files.length; i++) {  
    94.             /* 递归 */  
    95.             compressByType(files[i], out, basedir + dir.getName() + "/");  
    96.         }  
    97.     }  
    98.   
    99.     /** 
    100.      * 压缩一个文件 
    101.      *  
    102.      * @param file 
    103.      * @param out 
    104.      * @param basedir 
    105.      */  
    106.     private void compressFile(File file, ZipOutputStream out, String basedir) {  
    107.         if (!file.exists()) {  
    108.             isFirst = false;  
    109.             return;  
    110.         }  
    111.         if (basedir.equals("play/")) {  
    112.             basedir = "";  
    113.         }  
    114.         try {  
    115.             BufferedInputStream bis = new BufferedInputStream(  
    116.                     new FileInputStream(file));  
    117.             ZipEntry entry = new ZipEntry(basedir + file.getName());  
    118.             out.putNextEntry(entry);  
    119.             int count;  
    120.             byte data[] = new byte[BUFFER];  
    121.             while ((count = bis.read(data, 0, BUFFER)) != -1) {  
    122.                 out.write(data, 0, count);  
    123.             }  
    124.             bis.close();  
    125.         } catch (Exception e) {  
    126.             throw new RuntimeException(e);  
    127.         }  
    128.     }  
    129. }  

    第四步:压缩完成之后。此时的包是没有签名过的,所以还须要签名。签名能够使用jarsigner工具,首先我们要寻找到java的安装文件夹

    [java] view plaincopy
    1. <span style="white-space:pre">    </span>public  String getJavaPath() {  
    2.         String javaPath = (String) System.getenv("Path");  
    3.         String paths[]= javaPath.split(";");  
    4.         String myPath = null;  
    5.         for(String path:paths){  
    6.             if (path.contains("Java")&&!path.contains("jre")  
    7.                     &&path.contains("bin") ){  
    8.                 myPath = path;  
    9.                 break;  
    10.             }  
    11.         }  
    12.         return myPath+"\";  
    13.     }  

    签名:

    [java] view plaincopy
    1. <span style="white-space:pre">    </span>String javaPath = getJavaPath();  
    2.     Runtime rt = Runtime.getRuntime();  
    3.     String cmd = javaPath  
    4.             + "jarsigner -verbose"  
    5.             + " -keystore "+ keystorePath  
    6.             + " -storepass player"// password  
    7.             + " -signedjar "+signedApkPath // 签名后的apk存放位置  
    8.             + " -digestalg SHA1  -sigalg  MD5withRSA "  
    9.             + unsignedApkPath//未签名的apk  
    10.             + " player";// 别名  
    11.     Process child = rt.exec(cmd);  

    OK,签名成功。

  • 相关阅读:
    shell读取或者修改ini文件
    Linux--查询文件的第几行到第几行命令
    python读写修改配置文件(ini)
    Django REST framework 的TokenAuth认证及外键Serializer基本实现
    vue2.0+webpack+vuerouter+vuex+axios构建项目基础
    Zabbix 监控Windows磁盘IO
    磁盘 I/O 性能监控指标和调优方法
    linux查看与修改交换内存配置(解决zabbix-agent启动报错)
    js中的Map对象的简单示例
    Idea 怎么远程debug
  • 原文地址:https://www.cnblogs.com/yfceshi/p/6852208.html
Copyright © 2011-2022 走看看