ANT自动打包U3D安卓项目研究笔记

时间:2023-03-08 17:55:47

概述

因项目使用Atlassian Stash作为项目源码管理端,且其支持Ant命令自动编译,可使其根据最新的代码自动打包,故产生该研究Ant打包的任务。在此将研究过程及一些相关知识整理记录在此。

本文部分内容可以说就是Android和Ant自动打包的配置,只是在其基础上扩充了Unity3D的部分。

阅读本文需要:知道Android开发环境大概需要哪些东西,知道Unity3D编辑器的基本使用方法。

本文并不是系统学习Ant以及Android自动打包的文章,只是笔者通过网络搜索一系列文章,然后通过自己测试通过后的一篇文章总结,搜索时关键词变化大致如下:

Unity Ant -> Android Ant -> Unity Android Studio -> Eclipse Ant -> Android Ant。

这些关键词一定程度上反应了笔者研究Ant和Unity Android打包的思路,通过这些关键字搜到的比较有用的文章链接也会在下面列出来。

0.准备环境

主要介绍使用软件及环境的相关配置。

个人使用系统为Windows 10。

0.1 使用软件

下面介绍使用相关软件,每个软件都链接到其官方的下载页面,这些页面至少在公元2016年2月份是可用的。

1.Unity3D

2.JDK

3.ADT BUNDLE (ADT Bundle包括Eclipse、ADT插件和SDK Tools)

4.Apache Ant

这里需要特别说明的是ADT BUNDLE我给的是国内android studio社区中的ADT下载页面,个人认为该社区的Android环境资源可以说是国内比较全的。开始其实准备是用Android Studio做开发,但是没太接触过Android Studio,貌似U3D导出的Android工程不能直接使用,所以暂时放弃。

其他相关软件如有失效请到其官网下载。

0.2 环境配置

主要介绍软件安装完成后的配置,包括一些插件的下载安装。这里就不介绍上一小节提到的软件安装流程了,基本都是点击exe默认安装或者解压即可用的软件。

0.2.1 环境变量配置

1.右击桌面【此电脑(这台电脑、计算机、我的电脑)】,然后点击【属性】-【高级系统设置】-【高级】-【环境变量】

ANT自动打包U3D安卓项目研究笔记

2.通过点击下方的新建,添加ANDROID_HOME,ANT_HOME,CLASSPATH,JAVA_HOME几个变量(变量值请根据自己安装软件的位置决定),其中ANDROID_HOME设置的是ADT Bundle压缩包中的sdk目录,这里列出我个人系统设置的值作为参考。

ANDROID_HOME
D:\developtools\Android\sdk ANT_HOME
D:\developtools\apache-ant-1.9. CLASSPATH
.;%JAVA_HOME%lib;%JAVA_HOME%lib\tools.jar JAVA_HOME
D:\developtools\Java\jdk1..0_74

3.扩充Path环境变量,使得一些命令能在命令行执行

%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin;%ANT_HOME%\bin;%ANT_HOME%/lib;%ANDROID_HOME%/tools;%ANDROID_HOME%/platform-tools

4.添加完成后,点击确定关闭环境变量对话框,Win+R,输入CMD打开命令行,输入java -version,ant -version,android -h等命令,如果能得到类似下面的显示,那么环境配置基本通过,否则请检查环境变量配置是否有误。

C:\Windows\System32>java -version
java version "1.8.0_74"
Java(TM) SE Runtime Environment (build 1.8.0_74-b02)
Java HotSpot(TM) -Bit Server VM (build 25.74-b02, mixed mode) C:\Windows\System32>ant -version
Apache Ant(TM) version 1.9. compiled on June C:\Windows\System32>android -h Usage:
android [global options] action [action options]
Global options:

0.2.2 SDK下载

打开ADT BUNDLE中的 SDK Manager.exe,下载需要的SDK,一般下载Android一个版本就够了,在写本文的时候谷歌还没有回归天朝,所以下载SDK需要*。如果还没有*的能力,那么可以参考国内Android Studio社区的代理镜像页面:

http://tools.android-studio.org/index.php/proxy

如果该页面或者该页面上的资源失效且谷歌还存在墙的问题,那么,请自行寻找其他源。

0.2.3 扩展包ant-contrib

ant-contrib包可以让ant支持较为复杂的逻辑功能,比如循环和流程判断。下载地址:https://sourceforge.net/projects/ant-contrib/files/ant-contrib/

下面环境中使用的是1.0b3的zip版本。(Linux可以通过命令安装,具体请自行查找)。

下载完成后将zip包中ant-contrib-1.0b3.jar解压到ant目录中的lib目录下。

0.2.4 相关参考链接

这里放置一些其他的环境搭建、相关知识的链接(有些将来可能失效)。本文部分内容也参考了这些文章。

1.android开发环境配置

2.Android ant自动打包脚本

3.Unity3D研究院之Android使用ANT自动打包

4.windows下Android利用ant自动编译、修改配置文件、批量多渠道,打包生成apk文件

1.项目主体

这里介绍U3D创建项目、Eclipse导入项目的生成Ant的相关内容。

1.1 U3D部分

这里测试的Unity3D版本为5.3。

下面操作中可能会要求选择Android SDK目录,请选择ADT BUNDLE中的SDK目录。

1.打开Unity3D创建一个新项目,创建完成后直接保存默认的场景。然后点击菜单【File】-【Build Settings...】,点击【Add Open Scenes】,选择Android并点击【Switch Platform】:

ANT自动打包U3D安卓项目研究笔记

2.点击Player Settings,点击Other Settings,设置下包信息:

ANT自动打包U3D安卓项目研究笔记

3.勾上Building Setting界面的Google Android Project,然后点击Export,选择一个可用的项目空目录,完成Android工程的导出。

ANT自动打包U3D安卓项目研究笔记

1.2 Eclipse部分

1.打开ADT BUNDLE中的Eclipse,导入上一小节最终生成的Android工程。即右击Package Explorer,点击【Import】,选择【Android】下的【Existing Android Code Into Workspace】,点击【Next】,点击【Browse】选择上一小节最终生成的工程目录。

2.打开命令行,定位到Android工程目录,下面以我的工程目录作为示例:

ANT自动打包U3D安卓项目研究笔记

3.执行android生成bulid.xml的命令(projectname改为自己项目的名称):

android update project -n projectname -p . 

输出大致如下:

D:\projects\Unity\UnityAnimatorControllerMaker\AndroidProject\UnityAnimatorControllerMaker>android update project -n UnityAnimatorControllerMaker -p .
Updated local.properties
Updated file D:\projects\Unity\UnityAnimatorControllerMaker\AndroidProject\UnityAnimatorControllerMaker\build.xml
Updated file D:\projects\Unity\UnityAnimatorControllerMaker\AndroidProject\UnityAnimatorControllerMaker\proguard-project.txt
It seems that there are sub-projects. If you want to update them
please use the --subprojects parameter.

4.在项目目录下运行命令行,使用keytool生成一个keystore。命令示例:

keytool -genkey -alias test.keystore -keyalg RSA -validity  -keystore test.keystore

根据提示设置密码和其他信息,上面的示例命令中test.keystore即为最终生成文件名。

5.根目录下添加添加名为ant.properties以及名为custom_rules.xml的两个文件,添加这两个文件是因为本节第三步生成的bulid.xml中需要这两个文件。

ant.properties内容示例:

#keystore文件存放目录

key.store=./test.keystore

#keystore别名

key.alias=test.keystore

#keystore密码

key.store.password=111111

#组织密码

key.alias.password=111111

#如果还没有生成keystore证书,可以使用下面命令在项目目录下生成一个test.keystore证书文件

#generate test.keystore
#keytool -genkey -alias test.keystore -keyalg RSA -validity 20000 -keystore test.keystore #apk.dir表示存放最终生成apk的目录 apk.dir=./apk #定义项目名称 app.name=UnityAnimatorControllerMaker
#渠道号,多个渠道号用逗号分隔,每个渠道号不要使用违规字符例如/:等,因为渠道号会在打包的时候放在apk的文件名中,所以包含#违规字符将无法生成最终的apk,哥就是被这个细节给坑了一个下午。这里定义了两个渠道号myapp-12345和BAI-3s322d
market_channels=UnityAnimatorControllerMaker,baidu,91 #测试环境服务器配置
test.server.url=192.168.1.10/UnityAnimatorControllerMaker
test.server.image.url=192.168.1.9
test.UnityAnimatorControllerMaker.url=192.168.1.10
#生产环境服务器配置
rel.server.url=111.111.111.222/UnityAnimatorControllerMaker
rel.server.image.url=111.111.111.229
rel.UnityAnimatorControllerMaker.url=www.UnityAnimatorControllerMaker.com #测试环境标识 给apk命名的时候用
test.tag.name=test
#生产环境标识 给apk命名的时候用
release.tag.name=release

custom_rules.xml内容示例:

<?xml version="1.0" encoding="UTF-8"?>
<project name="custom_rules" > <!-- 引用ant-contlib这个扩展包,声明一下 --> <taskdef resource="net/sf/antcontrib/antcontrib.properties" > <classpath> <pathelement location="${ant.ANT_HOME}/lib/ant-contrib-1.0b3.jar" />
</classpath>
</taskdef> <!-- 定义一个时间变量,打完包后跟渠道号一起命名apk --> <tstamp> <format
pattern="yyyyMMddhhmm"
property="pktime"
unit="hour" />
</tstamp>
<!-- 创建apk存放目录 --> <mkdir dir="${apk.dir}" >
</mkdir> <!-- 替换参数 然后打包APK --> <target name="replace_parameter" > <!-- 替换服务器配置 --> <replaceregexp
byline="false"
encoding="UTF-8"
flags="g" > <!-- 这个是正则表达式匹配hostconfig中UnityAnimatorControllerMaker_server的值 --> <regexp pattern="UnityAnimatorControllerMaker_server>(.*)&lt;/UnityAnimatorControllerMaker_server" /> <substitution expression="UnityAnimatorControllerMaker_server>${server_url}&lt;/UnityAnimatorControllerMaker_server" /> <fileset
dir=""
includes="res/xml/hostconfig.xml" />
</replaceregexp> <replaceregexp
byline="false"
encoding="UTF-8"
flags="g" > <!-- 这个是正则表达式匹配hostconfig中UnityAnimatorControllerMaker_img_server的值 --> <regexp pattern="UnityAnimatorControllerMaker_img_server>(.*)&lt;/UnityAnimatorControllerMaker_img_server" /> <substitution expression="UnityAnimatorControllerMaker_img_server>${server_image_url}&lt;/UnityAnimatorControllerMaker_img_server" /> <fileset
dir=""
includes="res/xml/hostconfig.xml" />
</replaceregexp> <replaceregexp
byline="false"
encoding="UTF-8"
flags="g" > <!-- 这个是正则表达式匹配hostconfig中UnityAnimatorControllerMaker_url的值 --> <regexp pattern="UnityAnimatorControllerMaker_url>(.*)&lt;/UnityAnimatorControllerMaker_url" /> <substitution expression="UnityAnimatorControllerMaker_url>${UnityAnimatorControllerMaker_url}&lt;/UnityAnimatorControllerMaker_url" /> <fileset
dir=""
includes="res/xml/hostconfig.xml" />
</replaceregexp>
</target> <!-- 打包测试环境命令就用这个 --> <target name="deploytest" > <!-- 传服务器配置参数到 replace_parameter这个打包target --> <antcall target="replace_parameter" > <param
name="server_url"
value="${test.server.url}" /> <param
name="server_image_url"
value="${test.server.image.url}" /> <param
name="UnityAnimatorControllerMaker_url"
value="${test.UnityAnimatorControllerMaker.url}" />
</antcall>
<!-- 执行循环打包target foreach_replacechannel --> <antcall target="foreach_replacechannel" > <!-- apk命名时候用到的参数 --> <param
name="deploy_environment"
value="${test.tag.name}" />
</antcall>
</target> <!-- 打包生产环境命令就用这个 --> <target name="deployrel" > <!-- 传服务器配置参数到 replace_parameter这个打包target --> <antcall target="replace_parameter" > <param
name="server_url"
value="${rel.server.url}" /> <param
name="server_image_url"
value="${rel.server.image.url}" /> <param
name="UnityAnimatorControllerMaker_url"
value="${rel.UnityAnimatorControllerMaker.url}" />
</antcall>
<!-- 执行循环打包target foreach_replacechannel --> <antcall target="foreach_replacechannel" > <!-- apk命名时候用到的参数 --> <param
name="deploy_environment"
value="${release.tag.name}" />
</antcall>
</target> <!-- 循环打包的target --> <target name="foreach_replacechannel" > <!-- 开始循环打包,从market_channels参数中取出一个渠道号用channel标识,然后通过正则修改manifest文件 -->
<foreach
delimiter=","
list="${market_channels}"
param="channel"
target="AndroidManifest" >
</foreach>
</target> <target name="AndroidManifest" > <replaceregexp
byline="false"
encoding="UTF-8"
flags="g" > <!--
这个是正则表达式匹配manifest中meta,我 AndroidManifest中的配置为:
<meta-data android:value="360shichang" android:name="UMENG_CHANNEL" --> <regexp pattern="android:value=&quot;(.*)&quot; android:name=&quot;UMENG_CHANNEL&quot;" /> <substitution expression="android:value=&quot;${channel}&quot; android:name=&quot;UMENG_CHANNEL&quot;" /> <fileset
dir=""
includes="AndroidManifest.xml" />
</replaceregexp>
<!-- 这里设置最终生成包的存放目录以及apk的名称,注意这里是文件名称,所以变量中不允许出现违规字符,否则将无法生成最终的apk(会出现output is not valid 的错误) --> <property
name="out.final.file"
location="${apk.dir}/${app.name}_${channel}_${deploy_environment}_${pktime}.apk" /> <antcall target="clean" /> <antcall target="release" />
</target> </project>

其中需要注意修改的是项目名称、keystore的存放目录名称密码等信息的修改。其他修改信息可自行根据需要修改。ant.properties和custom_rules.xml可以在许多项目中通用。

6.在AndroidManifest.xml文件中添加名为UMENG_CHANNEL的meta项,示例:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.Company.MyTest"
android:versionName="1.0"
android:versionCode="1"
android:installLocation="preferExternal">
<supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:xlargeScreens="true" android:anyDensity="true" />
<application
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:icon="@drawable/app_icon"
android:label="@string/app_name"
android:isGame="true"
android:banner="@drawable/app_banner">
<activity
android:label="@string/app_name"
android:screenOrientation="fullSensor"
android:launchMode="singleTask"
android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|uiMode|screenSize|smallestScreenSize|fontScale"
android:name="com.Company.MyTest.UnityPlayerActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.LEANBACK_LAUNCHER" />
</intent-filter>
<meta-data android:name="unityplayer.UnityActivity" android:value="true" />
</activity> <meta-data android:value="test" android:name="UMENG_CHANNEL" />
</application>
<uses-sdk android:minSdkVersion="19" android:targetSdkVersion="23" />
<uses-feature android:glEsVersion="0x00020000" />
<uses-feature android:name="android.hardware.touchscreen" android:required="false" />
<uses-feature android:name="android.hardware.touchscreen.multitouch" android:required="false" />
<uses-feature android:name="android.hardware.touchscreen.multitouch.distinct" android:required="false" />
</manifest>

7.完成以上配置后,可以使用以下两个命令分别打测试环境和生产环境的包

ant deploytest
ant deployrel

总结

总体研究过程所花的时间不算太多,但还是遇到一些问题。首先是Android Studio这块,因为时间关系没有深入研究,以后条件允许的话还会研究Unity3D生成Android Studio项目,且可联合Ant的方法;其次最开始使用ant deploytest命令打包时遇到两个错误,开始一个错误是我忽略了ant-contrib这个扩展包(custom_rules.xml中的循环体报错),另一个是没有正确生成keystore文件(提示找不到keystore文件)。最终项目配置项目文件比较多的参考了0.2.4中第四篇文章,该文章写的较为详细,一些扩展点可以直接浏览该文章得到答案。