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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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月份是可用的。

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

技术分享

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 相关参考链接

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

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】:

技术分享

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>(.*)&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中第四篇文章,该文章写的较为详细,一些扩展点可以直接浏览该文章得到答案。

以上是关于ANT自动打包U3D安卓项目研究笔记的主要内容,如果未能解决你的问题,请参考以下文章

Ant(蚂蚁搬家)

cocos2d-x学习笔记(android自动化打包bat脚本)

Android Gradle 插件Gradle 构建工具简介 ② ( Android 项目构建打包流程 | 构建工具发展 -> 手动配置 -> Ant -> Maven -> Gradle )

Eclipse下配置Ant脚本 自动打包带签名的Android apk

ant的安装及项目的发布

使用Ant项目打包