程序发布前的准备

    

首先,需要准备的工作:

  1   用户协议(可以是本地html资源,也可以是通过webview调用远程url链接地址)。

  2    签名文件(打包签名文件,可以是公司以前这个项目的签名文件)。

  3    程序logo图标。

  4    其他东西(版本代号,应用截图,宣传文案,宣传视频,合作首发相关信息)。

需要配置的项目:

  1    清理日志调用(log日志如果发版时不清处,影响应用性能),版本代号,,版本名称。

  2    编译程序,签名程序(签名文件一定要保留,记住是一定)。

  3    发布前彻底检查一般程序。

  4    检查资源是否是最新的。

  5    确保远程服务器已经准备就绪。

  6    其他检查项(比如地图key,用户协议,公司以及logo)。

差异化功能的检查:

  1    不同渠道应用功能的检查。

  2    不同android版本的业务功能检查。

  3    不同机型的业务功能检查。

代码混淆:

优点:

1    字节码优化。

2    保护代码,防止篡改和安全保护。

3     压缩APK体积,清除无用代码。

4    减少jar包体积。

5    将代码变为功能等价但是难以阅读的代码。

缺点:

调试变得困难(混淆后,反馈的异常信息中是混淆后的逻辑代码,当然有办法解决的啦,后面讲)。

如何混淆代码: 混淆器通过删除从未用过的代码和使用晦涩名字重命名类、字段和方法,对代码进行压缩,优化和混淆。

修改project.properties

# This file is automatically generated by Android Tools.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must be checked in Version Control Systems.
#
# To customize properties used by the Ant build system edit
# "ant.properties", and override values to adapt the script to your
# project structure.
#
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
# Project target.
target=android-19
将proguard.config前面的注释去掉
修改proguard-project.txt
# To enable ProGuard in your project, edit project.properties
# to define the proguard.config property as described in that file.
#
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in ${sdk.dir}/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the ProGuard
# include property in project.properties.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
如果在程序中使用了第三方的jar包,在混淆后导致出错,这时我们需要在proguard-project.txt中去进行相应的配置, 来让其在混淆时不要混淆相应的jar包。对改配置文件中的相关配置解释如下:
-keep public class * extends android.app.Activity  【不进行混淆类名的类,保持其原类名和包名】
-keep public abstract interface com.asqw.android.Listener{
public protected <methods>; 【所有public protected的方法名不进行混淆】
}
-keep public class com.asqw.android{
public void Start(java.lang.String); 【对该方法不进行混淆】
}
-keepclasseswithmembernames class * { 【对所有类的native方法名不进行混淆】
native <methods>;
}
-keepclasseswithmembers class * { 【对所有类的指定方法的方法名不进行混淆】
public <init>(android.content.Context, android.util.AttributeSet);
}
-keepclassmembers class * extends android.app.Activity {【对所有类的指定方法的方法名不进行混淆】
public void *(android.view.View);
}
-keepclassmembers enum * {【对枚举类型enum的所有类的以下指定方法的方法名不进行混淆】
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keep class * implements android.os.Parcelable {【对实现了Parcelable接口的所有类的类名不进行混淆,对其成员变量为Parcelable$Creator类型的成员变量的变量名不进行混淆】
public static final android.os.Parcelable$Creator *;
}
-keepclasseswithmembers class org.jboss.netty.util.internal.LinkedTransferQueue {【对指定类的指定变量的变量名不进行混淆】
volatile transient org.jboss.netty.util.internal.LinkedTransferQueue$Node head;
volatile transient org.jboss.netty.util.internal.LinkedTransferQueue$Node tail;
volatile transient int sweepVotes;
}
-keep public class com.unionpay.** {*; }【对com.unionpay包下所有的类都不进行混淆,即不混淆类名,也不混淆方法名和变量名】
经过上面这两部之后反编译后就能混淆了,但是四大组件还在,为什么四大组件还在呢,因为四大组件是在清单文件中进行配置的, 如果混淆后就不能根据清单文件的配置去寻找了。
如果对于一些自己的代码中要想提供出来让别人通过反射调用的方法时,我们不想让部分代码被混淆,或者是我们使用别人提供的第三方jar包, 因为第三方的jar包一般都是已经混淆过的,我们要是再混淆就会报错了,所以我们要保证这些内容不用混淆,这里我们只需修改这个文件,然后加上后面的一句话, 他就不会混淆我们给出的内容
-keepattributes *Annotation*
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.app.backup.BackupAgent
-keep public class * extends android.preference.Preference
-keep public class * extends android.support.v4.app.Fragment
-keep public class * extends android.app.Fragment
-keep public class com.android.vending.licensing.ILicensingService
-keep class net.youmi.android.** {
*;
}

来源: <AndroidNote/代码混淆.md at master · CharonChui/AndroidNote>

 

混淆中如何清除日志信息:

-assumenosideeffects class android.util.Log {
    public static boolean isLoggable(java.lang.String, int);
        public static int v(...);
        public static int i(...);
        public static int w(...);
        public static int d(...);
        public static int e(...);
    }

  

使用这个配置时,一定要注意-dontoptimize,配置。

don‘t optimize 不要优化;将会会关闭优化,导致日志语句不会被优化掉。

ant多渠道打包:

1

     配置: 通过ant脚本语言进行打包,对安卓打包进行描述。 首先下载ant并进行配置

    ANT环境变量设置

    Windows下ANT用到的环境变量主要有2个,ANT_HOME 、PATH。

    设置ANT_HOME指向ant的安装目录。

    设置方法: ANT_HOME = D:/apache_ant_1.7.0

    将%ANT_HOME%/bin; %ANT_HOME%/lib添加到环境变量的path中。

    设置方法: PATH = %ANT_HOME%/bin; %ANT_HOME%/lib

    配置完成后可以通过cmd窗口进行ant命令检测是否安装成功。

    

    

    

2    将androidManifast.xml做个拷贝为androidManifast.xml.temp文件

3    androidManifast.xml文件中要替换的字符串用@@包围

4     修改ANTTest.java工程

market.txt

K-touch

AppChina

GoogleMarket

5     修改签名信息ant.properties

例如可以修改为:

key.store = "Key的地址"

key.store.password = 123456

key.alias = mykey

key.alias.password = 123456s

6    修改local.properties

sdk.dir = ""指定sdk路径,路径之间是双斜杠

    

7      build文件

8      AntTest.java文件内容修改

package com.cn.ant;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Calendar;

import org.apache.tools.ant.DefaultLogger;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.ProjectHelper;

public class AntTest {
	private Project project;

	public void init(String _buildFile, String _baseDir) throws Exception {
		project = new Project();

		project.init();

		DefaultLogger consoleLogger = new DefaultLogger();
		consoleLogger.setErrorPrintStream(System.err);
		consoleLogger.setOutputPrintStream(System.out);
		consoleLogger.setMessageOutputLevel(Project.MSG_INFO);
		project.addBuildListener(consoleLogger);

		// Set the base directory. If none is given, "." is used.
		if (_baseDir == null)
			_baseDir = new String(".");

		project.setBasedir(_baseDir);

		if (_buildFile == null)
			_buildFile = new String(projectBasePath + File.separator
					+ "build.xml");

		// ProjectHelper.getProjectHelper().parse(project, new
		// File(_buildFile));
		// 关键代码
		ProjectHelper.configureProject(project, new File(_buildFile));
	}

	public void runTarget(String _target) throws Exception {
		// Test if the project exists
		if (project == null)
			throw new Exception(
					"No target can be launched because the project has not been initialized. Please call the ‘init‘ method first !");
		// If no target is specified, run the default one.
		if (_target == null)
			_target = project.getDefaultTarget();

		// Run the target
		project.executeTarget(_target);

	}
       //工程地址
	private final static String projectBasePath = "D:\\android\\workspace3\\VDunHeima2";
                 //工程apk存放地址
	private final static String copyApkPath = "D:\\android\\apktest";
     //打包时临时文件存放地址
	private final static String signApk = "VDunHeima2-release.apk";//这里的文件名必须是准确的项目名!
      //明明前缀
	private final static String reNameApk = "VDunHeima2_";
      //要替换的字符串
	private final static String placeHolder = "@[email protected]";

	public static void main(String args[]) {
		long startTime = 0L;
		long endTime = 0L;
		long totalTime = 0L;
		Calendar date = Calendar.getInstance();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd:HH:mm:ss");
		try {
			System.out.println("---------ant批量自动化打包开始----------");
			startTime = System.currentTimeMillis();
			date.setTimeInMillis(startTime);
			System.out.println("开始时间为:" + sdf.format(date.getTime()));

			BufferedReader br = new BufferedReader(new FileReader("market.txt"));
			String flag = null;
			while ((flag = br.readLine()) != null) {

				// 先修改manifest文件:读取临时文件中的@[email protected]修改为市场标识,然后写入manifest.xml中
				String tempFilePath = projectBasePath + File.separator
						+ "AndroidManifest.xml.temp";
				String filePath = projectBasePath + File.separator
						+ "AndroidManifest.xml";
				write(filePath, read(tempFilePath, flag.trim()));
				// 执行打包命令
				AntTest mytest = new AntTest();
				mytest.init(projectBasePath + File.separator + "build.xml",
						projectBasePath);
				mytest.runTarget("clean");
				mytest.runTarget("release");
				// 打完包后执行重命名加拷贝操作
				File file = new File(projectBasePath + File.separator + "bin"
						+ File.separator + signApk);// bin目录下签名的apk文件

				File renameFile = new File(copyApkPath + File.separator + reNameApk
						+ flag + ".apk");
				boolean renametag = file.renameTo(renameFile);
				System.out.println("rename------>"+renametag);
				System.out.println("file ------>"+file.getAbsolutePath());
				System.out.println("rename------>"+renameFile.getAbsolutePath());
			}
			System.out.println("---------ant批量自动化打包结束----------");
			endTime = System.currentTimeMillis();
			date.setTimeInMillis(endTime);
			System.out.println("结束时间为:" + sdf.format(date.getTime()));
			totalTime = endTime - startTime;
			System.out.println("耗费时间为:" + getBeapartDate(totalTime));

		} catch (Exception e) {
			e.printStackTrace();
			System.out.println("---------ant批量自动化打包中发生异常----------");
			endTime = System.currentTimeMillis();
			date.setTimeInMillis(endTime);
			System.out.println("发生异常时间为:" + sdf.format(date.getTime()));
			totalTime = endTime - startTime;
			System.out.println("耗费时间为:" + getBeapartDate(totalTime));
		}
	}

	/**
	 * 根据所秒数,计算相差的时间并以**时**分**秒返回
	 *
	 * @param d1
	 * @param d2
	 * @return
	 */
	public static String getBeapartDate(long m) {
		m = m / 1000;
		String beapartdate = "";
		int nDay = (int) m / (24 * 60 * 60);
		int nHour = (int) (m - nDay * 24 * 60 * 60) / (60 * 60);
		int nMinute = (int) (m - nDay * 24 * 60 * 60 - nHour * 60 * 60) / 60;
		int nSecond = (int) m - nDay * 24 * 60 * 60 - nHour * 60 * 60 - nMinute
				* 60;
		beapartdate = nDay + "天" + nHour + "小时" + nMinute + "分" + nSecond + "秒";

		return beapartdate;
	}

	public static String read(String filePath, String replaceStr) {
		BufferedReader br = null;
		String line = null;
		StringBuffer buf = new StringBuffer();

		try {
			// 根据文件路径创建缓冲输入流
			br = new BufferedReader(new FileReader(filePath));

			// 循环读取文件的每一行, 对需要修改的行进行修改, 放入缓冲对象中
			while ((line = br.readLine()) != null) {
				// 此处根据实际需要修改某些行的内容
				if (line.contains(placeHolder)) {
					line = line.replace(placeHolder, replaceStr);
					buf.append(line);
				} else {
					buf.append(line);
				}
				buf.append(System.getProperty("line.separator"));
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			// 关闭流
			if (br != null) {
				try {
					br.close();
				} catch (IOException e) {
					br = null;
				}
			}
		}

		return buf.toString();
	}

	/**
	 * 将内容回写到文件中
	 *
	 * @param filePath
	 * @param content
	 */
	public static void write(String filePath, String content) {
		BufferedWriter bw = null;

		try {
			// 根据文件路径创建缓冲输出流
			bw = new BufferedWriter(new FileWriter(filePath));
			// 将内容写入文件中
			bw.write(content);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			// 关闭流
			if (bw != null) {
				try {
					bw.close();
				} catch (IOException e) {
					bw = null;
				}
			}
		}
	}
}

 9查看apk文件 

 

时间: 2024-12-28 20:18:22

程序发布前的准备的相关文章

android apk--程序发布前的准备

摘自:http://www.cnblogs.com/androidsuperman/p/4396889.html 首先,需要准备的工作: 1   用户协议(可以是本地html资源,也可以是通过webview调用远程url链接地址). 2    签名文件(打包签名文件,可以是公司以前这个项目的签名文件). 3    程序logo图标. 4    其他东西(版本代号,应用截图,宣传文案,宣传视频,合作首发相关信息). 需要配置的项目: 1    清理日志调用(log日志如果发版时不清处,影响应用性能

耐撕团队&alpha;发布前的剧透

题记 齐同学终于在这个周一80%血量复活,赞,可喜可贺.复活后的第一件事,干活,干活,干活.因为得努力啊,黄色领骑衫就是动力啊.哈哈.另题外话:耐撕团队副队长昨天中了EI,可喜可贺. 正文 周一,我开始和队友们准备耐撕团队的α发布,我们很认真,因为软件所出品,要值得信赖.(我又傲娇了).周一下午,我搞完了两个技术原型:1.手机客户端监听服务器发出的“开始抢答”口令  2.服务器端监听客户端发出的“我抢”请求.弄完这两个技术原型,我心里大概有数了,α发布指日可待.这两个模块的实现曾是我最担心的.做

发布App,赢iPad mini + 美金100$ - Autodesk Exchange 应用程序发布竞赛

开发牛人们,送你个iPad mini要不要,Autodesk Exchange应用程序发布竞赛开始了. 摘要版:   在2014年9月30日午夜前提交到Autodesk Exchange 应用程序商店上,并在2014年11月30日前成功发布的.每个应用可获得: 收费应用 - 100美刀 免费应用 - 50美刀   云应用竞赛,赢iPad mini,共5个 参赛条件: 你的App是Web服务型的,或者使用了至少一个Web服务 并且在活动期间(北京时间周日 2014年9月21日00:00 am开始,

我的即时通讯系统发布前,先小秀一下

一.开发概要: 开发人员:本人 联系电话:18667102122 开发人数:1人 版权所有:杭州云寻觅网络科技有限公司 开发周期:2014-05-27 至今 备注:就一个人开发的,不要总是拿这个做了2,3个月的东西,跟几千人做了10多年的产品去比较,没有可比性.   所以比较的时候希望大家别失去理智! 二.架构及概述 1.总体架构图 2.服务端功能模块图 3.客户端功能模块图 4.客户端浏览器组件功能模块图 三.组成文件: 服务端:ImServer_5_0_0.exe 大小 88.6MB(含jd

Asp.NetCore程序发布到CentOs(含安装部署netcore)--最佳实践(二)

原文:Asp.NetCore程序发布到CentOs(含安装部署netcore)--最佳实践(二) Asp.NetCore程序发布到CentOs(含安装部署netcore)--最佳实践(一) 接上一篇 3. Nginx配置反向代理 3.1 cnetos 安装nginx 首先,我们需要在服务器上安装Nginx.参考网址 3.1.1:添加Nginx存储库 要添加CentOS 7 EPEL仓库,请打开终端并使用以下命令: sudo yum install epel-release EPEL的全称叫 Ex

winform_使用ClickOnce生成安装程序包页面&amp;程序发布新版本通知客户端更新

好久不用winform了,一用就遇到一些问题,不过好在咱有知识沉淀的好习惯,这里做下记录,网上也有很多关于clickonce的这方面的文章,我这里仅仅只是为了加深印象,做下记录. 对于安装程序包,本人已经写过几篇文章: VS2017中使用组合项目_windows服务+winform管理_项目发布_测试服务器部署 VS2017.VS2019没有Setup安装项目(Visual Studio Installer)_解决方案 这里主要对通知客户端自动更新做下介绍,其实关于该需求还是老大提出的要求,个人

eclipse、eclipse_rcp工程发布前、eclipse_rcp工程发布后

接着上节说到的相对路径问题 eclipse的相对路径是相对于项目工程的路径:在这里可以直接使用Document doc = reader.read(new File("student.xml")); eclipse_rcp产品发布前的相对路径是相对于源码路径 InputStream in = MAC.class.getClassLoader().getResourceAsStream("student.xml"); Document doc = reader.rea

ASP.NET 程序发布详细过程

前言 ASP.NET网站的发布,无论是初学者还是高手,在程序的发布过程中或多或少会存在一些问题,譬如VS发布ASP.NET程序失败.IIS安装失败.IIS发布失败.局域网内不能访问 配置文件错误.权限不足等一系列问题,结合我带领的500技术团队反应的各种问题,我今天花点时间总结一下,方便大家,共同学习,共同进步 为了后文的深入详细分析,我写了一个小Demo,代码附上.本次基于VS2013,OS为WIN10,IIS7等环境讲解.(其他操作系统如WIN7原理也类似,但有细微差别) 1.解决方案整体概

iOS程序发布测试-生成ad hoc证书

转自: http://blog.sina.com.cn/s/blog_68444e230100srdn.html iOS程序发布测试3-生成ad hoc证书 iOS证书分2种,1种是开发证书,用来给你(开发人员)做真机测试的:1种是发布证书,发布证书又分发布到app store的(这里不提及)和发布测试的ad hoc证书. 那ad hoc证书和开发证书区别在哪里?如果你的tester(团队测试人员.客户)都能将测试设备拿到你面前,直接插到你的mac开发机上,你可以直接将程序"灌"进去,