更改已经签名的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
- File file = new File("d:/app/assets/id.txt");
- OutputStream outputStream = new FileOutputStream(file);
- outputStream.write(user.getId().toString().getBytes());
- outputStream.flush();
- outputStream.close();
第三步:压缩写入渠道商id后的全部app文件
- ZipCompressor zc = new ZipCompressor("d:/play.apk");
- zc.compressExe("d:/app/");
详细的压缩代码例如以下:
- package com.xyc.signSystem.utils;
- import java.io.BufferedInputStream;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.FileOutputStream;
- import java.util.zip.CRC32;
- import java.util.zip.CheckedOutputStream;
- import org.apache.tools.zip.ZipEntry;
- import org.apache.tools.zip.ZipOutputStream;
- /**
- * @ClassName: ZipCompressor
- * @author :andywuchuanlong QQ:312037487
- * @Description: 压缩文件的通用工具类-採用org.apache.tools.zip.ZipOutputStream实现。较复杂。
- *
- */
- public class ZipCompressor {
- static final int BUFFER = 8192;
- private File zipFile;
- /**
- * 压缩文件构造函数
- *
- * @param pathName
- * 压缩的文件存放文件夹
- */
- public ZipCompressor(String pathName) {
- zipFile = new File(pathName);
- }
- /**
- * 运行压缩操作
- *
- * @param srcPathName
- * 被压缩的文件/目录
- */
- public void compressExe(String srcPathName) {
- File file = new File(srcPathName);
- if (!file.exists()) {
- throw new RuntimeException(srcPathName + "不存在!");
- }
- try {
- FileOutputStream fileOutputStream = new FileOutputStream(zipFile);
- CheckedOutputStream cos = new CheckedOutputStream(fileOutputStream,
- new CRC32());
- ZipOutputStream out = new ZipOutputStream(cos);
- String basedir = "";
- compressByType(file, out, basedir);
- out.close();
- } catch (Exception e) {
- e.printStackTrace();
- throw new RuntimeException(e);
- }
- }
- /**
- * 推断是文件夹还是文件。依据类型(文件/文件夹)运行不同的压缩方法
- *
- * @param file
- * @param out
- * @param basedir
- */
- private void compressByType(File file, ZipOutputStream out, String basedir) {
- if (basedir.equals("play/")) {
- basedir = "";
- }
- /* 推断是文件夹还是文件 */
- if (file.isDirectory()) {
- this.compressDirectory(file, out, basedir);
- } else {
- this.compressFile(file, out, basedir);
- }
- }
- boolean isFirst = true;
- /**
- * 压缩一个文件夹
- *
- * @param dir
- * @param out
- * @param basedir
- */
- private void compressDirectory(File dir, ZipOutputStream out, String basedir) {
- if (!dir.exists()) {
- return;
- }
- if (basedir.equals("play/")) {
- basedir = "";
- }
- File[] files = dir.listFiles();
- for (int i = 0; i < files.length; i++) {
- /* 递归 */
- compressByType(files[i], out, basedir + dir.getName() + "/");
- }
- }
- /**
- * 压缩一个文件
- *
- * @param file
- * @param out
- * @param basedir
- */
- private void compressFile(File file, ZipOutputStream out, String basedir) {
- if (!file.exists()) {
- isFirst = false;
- return;
- }
- if (basedir.equals("play/")) {
- basedir = "";
- }
- try {
- BufferedInputStream bis = new BufferedInputStream(
- new FileInputStream(file));
- ZipEntry entry = new ZipEntry(basedir + file.getName());
- out.putNextEntry(entry);
- int count;
- byte data[] = new byte[BUFFER];
- while ((count = bis.read(data, 0, BUFFER)) != -1) {
- out.write(data, 0, count);
- }
- bis.close();
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
- }
第四步:压缩完成之后。此时的包是没有签名过的,所以还须要签名。签名能够使用jarsigner工具,首先我们要寻找到java的安装文件夹
- <span style="white-space:pre"> </span>public String getJavaPath() {
- String javaPath = (String) System.getenv("Path");
- String paths[]= javaPath.split(";");
- String myPath = null;
- for(String path:paths){
- if (path.contains("Java")&&!path.contains("jre")
- &&path.contains("bin") ){
- myPath = path;
- break;
- }
- }
- return myPath+"\\";
- }
签名:
- <span style="white-space:pre"> </span>String javaPath = getJavaPath();
- Runtime rt = Runtime.getRuntime();
- String cmd = javaPath
- + "jarsigner -verbose"
- + " -keystore "+ keystorePath
- + " -storepass player"// password
- + " -signedjar "+signedApkPath // 签名后的apk存放位置
- + " -digestalg SHA1 -sigalg MD5withRSA "
- + unsignedApkPath//未签名的apk
- + " player";// 别名
- Process child = rt.exec(cmd);
OK,签名成功。
更改已经签名的app中的内容的更多相关文章
- 解决“iOS 7 app自动更新,无法在app中向用户展示更新内容”问题
转自cocoachina iOS 7能在后台自动app,这对开发者来说和用户都很方便,但是还是有一些缺点.用户不会知道app本次更新的内容,除非他们上到app的App Store页面去查看.开发者也会 ...
- 嵌入式表单字段中的内容可能被server更改以删除不安全的内容。是否要又一次载入您的页面以查看保存结果?
嵌入式表单字段中的内容可能被server更改以删除不安全的内容.是否要又一次载入您的页面以查看保存结果? 近期有朋友问到,当他在SharePoint首页上进行编辑时.插入一段代码. 完 ...
- android APP 中微信分享功能实现 的总结
//花了很长时间最终完成了微信分享功能,中间走了很多弯路,在此做一下小结,希望对在应用中使用到微信分享的朋友有所帮助. 主要问题就是下面两个: 1.为什么运行了项目之后,微信分享只是闪了一下就没有了? ...
- [Phonegap+Sencha Touch] 移动开发77 Cordova Hot Code Push插件实现自己主动更新App的Web内容
原文地址:http://blog.csdn.net/lovelyelfpop/article/details/50848524 插件地址:https://github.com/nordnet/cord ...
- 全面分析:APP中的消息功能设计
一.定义 APP的“消息”模块,是通过APP或手机这个客户端,围绕某个产品的功能进行交流.沟通的重要方式.这种沟通,一方是运营人员或商家,也可以是产品或系统本身,为方便说明笔者这里姑且统一简称为B端, ...
- ViewPager封装工具类: 轻松实现APP导航或APP中的广告栏
相信做app应用开发的,绝对都接触过ViewPager,毕竟ViewPager的应用可以说无处不在:APP第一次启动时的新手导航页,APP中结合Fragment实现页面滑动,APP中常见的广告栏的自动 ...
- 替换excel模板中的内容并使用JavaMail发送邮件
由于在公司工作,常年出差,每天都要以日报的形式向公司汇报当天的工作内容.而日报的内容大体上就只有当天工作的主要内容时变化的,其余的都是不变 的. 而我的电脑刚打开excel有点卡,因此决定使用Java ...
- 分享 Ionic 开发 Hybrid App 中遇到的问题以及后期发布 iOS/Android 的方方面面
此篇文章主要整理了最近在使用 Ionic 开发 Hybrid App 过程中遇到的一些疑难点以及后期发布生成 iOS 和 Android 版本过程中的种种问题. 文章目录 Ionic 简介和项目需求介 ...
- 【iOS开发】在 App 中加入 AdMob 广告 - 入门介绍与编程技巧
前言 虽然在App中加入广告来盈利是比较低级的商业化方式,但对于个人开发者或者小团队开发者来说,做出一个简单易用的免费小工具(举个栗子),在里面加入一些广告,如果用的人多,也是可以带来一些可观的收入的 ...
随机推荐
- 简单检测CDN链接是否有效
CDN链接经常是使用的.但是,CDN链接挂了怎么办,因此,就要调用使用本站点的库,那么怎么实现呢? 检测CDN的jquery链接是否有效(这种方法比较简单) <script src=" ...
- Selenium WebDriver- 指定页面加载时间
#encoding=utf-8 import unittest import time from selenium import webdriver from selenium.webdriver i ...
- hashlib.md5加密
对一个字符串拼接时间,然后对其进行md5加密: import hashlib,time a='123absg' b=time.time() c='%s|%s'%(a,b) print(c) m=has ...
- FastText 介绍
FastText 介绍 在面试百度的NLP工程师时,被问及常用的词向量表示学习方法有哪些,我说知道word2vec,然后大佬又问我知道FastText么... 这就很尴尬了,不会! 不同于word2v ...
- js时间格式化工具,时间戳格式化,字符串转时间戳
在开发中经常会用到时间格式化,有时候在网上搜索一大堆但不是自己想要的,自己总结一下,写一个时间格式化工具方便以后直接使用,欢迎大家来吐槽…… 1 2 3 4 5 6 7 8 9 10 11 12 13 ...
- python操redis
Python操作redis python连接方式:点击 下面介绍详细使用 1.String 操作 redis中的String在在内存中按照一个name对应一个value来存储 set() #在Redi ...
- hibernate缓存机制【转】
一.why(为什么要用Hibernate缓存?) Hibernate是一个持久层框架,经常访问物理数据库. 为了降低应用程序对物理数据源访问的频次,从而提高应用程序的运行性能. 缓存内的数据是对物理数 ...
- Android获取当前应用版本号
代码改变世界 获取当前应用的版本号 private String getVersionName() throws Exception { // 获取packagemanager的实例 PackageM ...
- hdu6103[尺取法] 2017多校6
/*hdu6103[尺取法] 2017多校6*/ #include <bits/stdc++.h> using namespace std; int T, m; ]; void solve ...
- 【Luogu】P2155沙拉公主的困惑(数论)
题目链接 数论果然是硬伤qwq 还是智商上的硬伤 我们来讲两个道理 No.1 求1~i!中与i!互质的数的个数 实际上就是求i!的欧拉函数 有如下递推式: f[1]=1 if(i为合数) f[i]=f ...