ANT自动打包U3D安卓项目研究笔记
概述
因项目使用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月份是可用的。
3.ADT BUNDLE (ADT Bundle包括Eclipse、ADT插件和SDK Tools)
这里需要特别说明的是ADT BUNDLE我给的是国内android studio社区中的ADT下载页面,个人认为该社区的Android环境资源可以说是国内比较全的。开始其实准备是用Android Studio做开发,但是没太接触过Android Studio,貌似U3D导出的Android工程不能直接使用,所以暂时放弃。
其他相关软件如有失效请到其官网下载。
0.2 环境配置
主要介绍软件安装完成后的配置,包括一些插件的下载安装。这里就不介绍上一小节提到的软件安装流程了,基本都是点击exe默认安装或者解压即可用的软件。
0.2.1 环境变量配置
1.右击桌面【此电脑(这台电脑、计算机、我的电脑)】,然后点击【属性】-【高级系统设置】-【高级】-【环境变量】
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.6 CLASSPATH .;%JAVA_HOME%lib;%JAVA_HOME%lib\tools.jar JAVA_HOME D:\developtools\Java\jdk1.8.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) 64-Bit Server VM (build 25.74-b02, mixed mode) C:\Windows\System32>ant -version Apache Ant(TM) version 1.9.6 compiled on June 29 2015 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需要FQ。如果还没有FQ的能力,那么可以参考国内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 相关参考链接
这里放置一些其他的环境搭建、相关知识的链接(有些将来可能失效)。本文部分内容也参考了这些文章。
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】:
2.点击Player Settings,点击Other Settings,设置下包信息:
3.勾上Building Setting界面的Google Android Project,然后点击Export,选择一个可用的项目空目录,完成Android工程的导出。
1.2 Eclipse部分
1.打开ADT BUNDLE中的Eclipse,导入上一小节最终生成的Android工程。即右击Package Explorer,点击【Import】,选择【Android】下的【Existing Android Code Into Workspace】,点击【Next】,点击【Browse】选择上一小节最终生成的工程目录。
2.打开命令行,定位到Android工程目录,下面以我的工程目录作为示例:
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 20000 -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>(.*)</UnityAnimatorControllerMaker_server" /> <substitution expression="UnityAnimatorControllerMaker_server>${server_url}</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>(.*)</UnityAnimatorControllerMaker_img_server" /> <substitution expression="UnityAnimatorControllerMaker_img_server>${server_image_url}</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>(.*)</UnityAnimatorControllerMaker_url" /> <substitution expression="UnityAnimatorControllerMaker_url>${UnityAnimatorControllerMaker_url}</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="(.*)" android:name="UMENG_CHANNEL"" /> <substitution expression="android:value="${channel}" android:name="UMENG_CHANNEL"" /> <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中第四篇文章,该文章写的较为详细,一些扩展点可以直接浏览该文章得到答案。