天天看點

Ant自動編譯打包android項目

1.  背景:

    Eclipse用起來雖然友善,但是編譯打包android項目還是比較慢,尤其當要将應用打包釋出到各個管道時,用Eclipse手動打包各種管道包就有點不切實際了,這時候我們用到Ant幫我們自動編譯打包了。

2.  Ant 安裝:

     ant的安裝比較簡單,下載下傳ant壓縮包(最新的為1.9.3版本),下載下傳之後将其解壓到某個目錄(本人解壓到E:\Program Files\apache-ant-1.9.3) ,然後配置環境變量(建立ANT_HOME環境變量,值為ant所在的目錄,然後将ANT_HOME/bin添加到path中),如圖:

Ant自動編譯打包android項目
Ant自動編譯打包android項目

     打開指令行工具,輸入 ant  -version ,如果出現如下結果,說明ant 安裝成功。

Ant自動編譯打包android項目

3. 對已存在的Android項目提供Ant支援:

   打開指令行工具,切換路徑到項目所在的目錄(比如我在E:\GitHub\likebamboo\android-menudrawer\menudrawer-samples下有一個android項目),輸入指令" android update project --name MenudrawSample -p ./ " 如下圖:(其中 --name 參數是指定項目名稱,可自己根據需要替換)。

Ant自動編譯打包android項目

     這時候我們可以看到在我們的項目根目錄下多了build.xml,以及local.properties兩個檔案。

     其中local.properties寫明了我們的android SDK的目錄(其實是環境變量ANDROID_HOME的值,是以如果環境變量中沒有這個的,請增加)。

      build.xml則是ant建構的最重要腳本,打開一看,發現裡面其實大部分都是寫注釋,有用的沒幾行,這是因為生成的這個build.xml引用了android SDK自帶的建構腳本,具體目錄是{sdk目錄}/tools/ant/build.xml 。

Ant自動編譯打包android項目
Ant自動編譯打包android項目

      這樣,我們項目就支援ant編譯打包了,但是,有人可能會說了,我的項目有引用第三方的jar包,而且還引用了其他的android library 項目,該怎麼辦呢? 請往下看:

4. 項目引用了其他library項目:

      如果項目隻是引用了第三方jar包,隻要将jar包放在libs檔案夾下就ok了,ant會在編譯打包過程中會自動将第三方jar加進去的。但是當我們的android 項目參考了其他library項目,這時候我們最初在輸入android update 指令的時候應該多一個參數 --subprojects : 

Ant自動編譯打包android項目

      你發現報錯了,不要着急,這是因為那個library 還不支援ant自動編譯,我們需要先讓它也支援。

      進入到library項目所在的目錄,輸入指令 android update lib-project -p ./  (注意是 lib-project);

Ant自動編譯打包android項目

   再回到原項目,輸入指令” android update project --name MenudrawSample -p ./ --subprojects ",這下就OK了。

5. 編譯打包項目:

       ant debug : 生成一個測試版apk,預設使用 debug key 進行簽名,生成的apk(your_project_name-debug.apk)在bin目錄下。

       ant release : 生成一個未簽名和未aligned的apk包,生成的apk(your_project_name-release-unsigned.apk和your_project_name-release-unaligned.apk)在bin目錄下

繼續介紹如果如何在ant打包應用的時候加入簽名資訊以及自動打包管道包。

6. 加入簽名資訊:

在項目的根目錄下建一個ant.properties檔案,輸入如下内容,其中keystore密碼和alias密碼可以不指定(防洩漏),那麼在指令執行的過程中會要求你輸入。

[html]  view plain  copy  

Ant自動編譯打包android項目
Ant自動編譯打包android項目
  1. #keystore的路徑,必須使用正斜杠  
  2. key.store=./me.key  
  3. #keystore的密碼  
  4. #key.store.password=*****  
  5. #alias名  
  6. key.alias=me  
  7. #alias密碼  
  8. #key.alias.password=******       

在項目根目錄下運作 ant release 指令就會幫你生成一個經過簽名和aligned的apk,生成的apk(your_project_name-release.apk)在bin目錄下

注意:這裡的keystore路徑使用的是相當路徑,樓主在測試時使用了絕對路徑,出現密碼錯誤的情況,有類似情況(設定的密碼明明是對的,但是還是報Keystore was tampered with, or password was incorrect: Password verification failed)可是嘗試将絕對路徑改為相對路徑。

7. 自動打包管道包:

 實作批量循環打包需要一個類似于for循環的功能,在Ant的核心包裡沒有相關的For循環的Task,即不支援for循環,但是ant支援第三方擴充包,以支援更多的其他功能。

于是我們要下載下傳相應的支援for循環的擴充包。可以使用開源的Ant-contrib包。下載下傳位址:http://ant-contrib.sourceforge.net/  。

注意:如果報錯:

 Could not load definitions from resource net/sf/antcontrib/antcontrib.properties. It could not be found.

就是因為沒有ant-contrib-1.0b3.jar包,(注意這裡的包需要和custom_rules檔案中的相同)

下載下傳後的解壓得到的jar檔案放到ant的lib目錄。接下來我們就可以打包管道包了,具體做法是:

(1)首先在ant.properties檔案中增加屬性 market_channels (管道清單,以逗号分割),version(應用程式版本名) 

#keystore的路徑,必須使用正斜杠
key.store=./test3.key  
#keystore的密碼
key.store.password=bihansheng
#alias名
key.alias=test3
#alias密碼
key.alias.password=bihansheng

#管道市場清單  
market_channels=bihansheng,baidu,91
#版本号
version=1.0.1 
#包名
app.name=test3
#apk所在的檔案名
apk.dir=text3


#下面的配置是區分正式打包和測試環境打包的參數
#測試環境辨別 給apk命名的時候用
test.tag.name=test
#生産環境辨別 給apk命名的時候用
release.tag.name=release

#測試環境伺服器配置
test.server.url=192.168.1.10/bihansheng
test.server.image.url=192.168.1.9
test.bihansheng.url=192.168.1.10
#生産環境伺服器配置
rel.server.url=111.111.111.222/bihansheng
rel.server.image.url=111.111.111.229
rel.bihansheng.url=www.bihansheng.com
           

注意: 管道名稱用逗号分開,并且不允許出現違規的字元如斜杠,否則會打包失敗,同樣的檔案名和檔案路徑也不能出現違規字元

(2)在我們項目中添加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中bihansheng_server的值 -->
<regexp pattern="bihansheng_server>(.*)</bihansheng_server" />
<substitution expression="bihansheng_server>${server_url}</bihansheng_server" />
<fileset
dir=""
includes="res/xml/hostconfig.xml" />
</replaceregexp>
<replaceregexp
byline="false"
encoding="UTF-8"
flags="g" >
<!-- 這個是正規表達式比對hostconfig中bihansheng_img_server的值 -->
<regexp pattern="bihansheng_img_server>(.*)</bihansheng_img_server" />
<substitution expression="bihansheng_img_server>${server_image_url}</bihansheng_img_server" />
<fileset
dir=""
includes="res/xml/hostconfig.xml" />
</replaceregexp>
<replaceregexp
byline="false"
encoding="UTF-8"
flags="g" >
<!-- 這個是正規表達式比對hostconfig中bihansheng_url的值 -->
<regexp pattern="bihansheng_url>(.*)</bihansheng_url" />
<substitution expression="bihansheng_url>${bihansheng_url}</bihansheng_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="bihansheng_url"
value="${test.bihansheng.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="bihansheng_url"
value="${rel.bihansheng.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="modify_manifest" >
</foreach>
</target>
<target name="modify_manifest" >
<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>
           

(3)custom_rules.xml檔案中是用伺服器ipizne配置檔案hostconfig.xml檔案,内容為: 

<?xml version="1.0" encoding="UTF-8"?>
<!-- Ϊ‹antղѼʱ۲ֽղƥƤìȫһҪٱʽۯكτݾ -->
<hostconfig>
<bihansheng_server>1111.1111.1111.1/bihansheng</bihansheng_server>
<bihansheng_img_server>1111.1111.1111.1</bihansheng_img_server>
<bihansheng_url>www.bihansheng.com</bihansheng_url>
</hostconfig>