Eclipse下使用Ant多渠道批量打包

在上一篇文章《eclipse下Ant自動打包,混淆和簽名》中,我們已經可以使用ant進行打包了,但是很多情況下我們需要批量打包,比如發佈到平臺上時需要上傳每個市場的渠道包,每個apk都包含了不同的渠道號,具體數值寫在AndroidManifest.xml的meta元素中,比如在AndroidManifest.xml中添加一個渠道名和渠道號可以加入<meta android:name="UMENG_CHANNEL" android:value="UMENG"></meta>。然後再打包。所以,如果渠道號有很多,在版本更新之後又要重新打包的時候,誰都不想手動將一個個不同渠道的apk導出。這時,ant批量打包就能節省好多時間了。

        首先,我們在配置文件中寫好需要用到的渠道名和渠道號,用ant構建時將會讀取我們寫好的渠道,動態替換AndroidManifest.xml中的meta節點的name和value,每替換完一個就打出一個apk包,用一個for循環不斷地重複打包直到導出所有的渠道包爲止。

        爲了方便替換,在AndroidManifest.xml中添加一個meta節點如下:

 

 <meta-data
            android:name="channelname"
            android:value="channelkey" >
        </meta-data>

待會兒我們在打包的時候就會把channelname替換成渠道名,把channelkey替換成渠道號。

上一篇文章講到local.properties,我們把參數都寫在這裏

如下local.properties:

#下面這句是自動生成的
sdk.dir=D:\\Program Files\\Android\\android-sdk
#數字簽名文件
key.store=jingchen.keystore
#別名alias
key.alias=jingchen
#數字簽名的密碼
key.store.password=111111
#alias的密碼
key.alias.password=111111
#這裏設置混淆代碼
proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
#寫上所有的渠道,格式 渠道名:渠道號
market_channels=UMENG_CHANNEL:UMENG,JPUSH_CHANNEL:AAA,BAIDU_CHANNEL:BAIDU
#版本
version=1.0.0

上面的兩個參數market_channels和version我們在custom_rules.xml會獲取,無論有多少渠道都可以寫上,用","分隔。下面看一下我們的custom_rules.xml的內容

新建一個custom_rules.xml

         在這裏來看一下build.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project
    name="MainActivity"
    default="help" >

    <property file="local.properties" />

    <property file="ant.properties" />

    <property environment="env" />

    <condition
        property="sdk.dir"
        value="${env.ANDROID_HOME}" >

        <isset property="env.ANDROID_HOME" />
    </condition>

    <loadproperties srcFile="project.properties" />

    <fail
        message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
        unless="sdk.dir" />

    <import
        file="custom_rules.xml"
        optional="true" />

    <import file="${sdk.dir}/tools/ant/build.xml" />

</project>


它會導入當前目錄下的custom_rules.xml,所以我們在當前工程目錄下新建一個custom_rules.xml,裏面寫上我們的打包規則。所有的替換,打包和輸出操作都寫在custom_rules.xml中。這裏面,替換渠道號的寫法有兩種:

注意:雙引號用“&quot;”,由於貼代碼的時候網頁自動把“&quot;”替換成“"”了。。

寫法1

 custom_rules.xml:

 

<?xml version="1.0" encoding="UTF-8"?>
<!-- 渠道包打包腳本  ant deploy -->
<project name="custom_rules" >

    <!-- 引用支持循環的jar包ant-contrib-1.0b3.jar -->

    <taskdef resource="net/sf/antcontrib/antcontrib.properties" >

        <classpath>

            <pathelement location="lib/ant-contrib-1.0b3.jar" />
        </classpath>
    </taskdef>

    <!-- 循環打包,target名爲deploy,構建的時候必須選擇deploy -->

    <target name="deploy" >

        <!-- 進來的時候先clean一下項目 -->

        <antcall target="clean" />
        <!-- for循環內容傳進來的參數爲market_channels,以","爲分隔構建list,循環讀取list,並將讀取到的字符串以參數channel傳進modify_manifest中 -->

        <foreach
            delimiter=","
            list="${market_channels}"
            param="channel"
            target="modify_manifest" >
        </foreach>
    </target>

    <target name="modify_manifest" >

        <!-- 按正則匹配獲取渠道名字,賦給channelname -->

        <propertyregex
            input="${channel}"
            override="true"
            property="channelname"
            regexp="(.*):"
            select="\1" />
        <!-- 按正則匹配獲取渠道號碼,賦給channelkey -->

        <propertyregex
            input="${channel}"
            override="true"
            property="channelkey"
            regexp=":(.*)"
            select="\1" />
        <!-- 將AndroidManifest.xml中的android:name="channelname"替換成爲android:name="${channelname}",這裏的${channelname}是我們上面正則匹配出來的內容 -->

        <replaceregexp
            byline="true"
            encoding="utf-8"
            file="AndroidManifest.xml"
            match="android:name="channelname""
            replace="android:name="${channelname}"" />
        <!-- 將AndroidManifest.xml中的android:value="channelkey"替換成爲android:value="${channelkey}" -->

        <replaceregexp
            byline="true"
            encoding="utf-8"
            file="AndroidManifest.xml"
            match="android:value="channelkey""
            replace="android:value="${channelkey}"" />

        <!-- 用release打包 -->

        <antcall target="release" />
        <!-- 拷貝渠道包到指定目錄下,out.absolute.dir在自帶的build.xml中定義了,爲bin目錄,如果要修改,可以在local.properties中添加一行out.absolute.dir=指定目錄 -->

        <copy
            file="${out.absolute.dir}/${ant.project.name}-release.apk"
            tofile="${out.absolute.dir}/out/${ant.project.name}-v${version}-${channelkey}.apk" />

        <!-- 打包完一個渠道包後把渠道名和渠道號替換回原來格式,這樣可以進行下一次替換,AndroidManifest.xml裏所有匹配的東西都會被替換 -->

        <replaceregexp
            byline="true"
            encoding="utf-8"
            file="AndroidManifest.xml"
            match="android:name="${channelname}""
            replace="android:name="channelname"" />

        <replaceregexp
            byline="true"
            encoding="utf-8"
            file="AndroidManifest.xml"
            match="android:value="${channelkey}""
            replace="android:value="channelkey"" />
    </target>

</project>
以上是其中一種寫法,在替換AndroidManifest.xml中的內容的時候比較靈活,不用在乎AndroidManifest.xml的格式問題,比如android:name和android:value間多一個空格或者換行啥的,都不會影響到結果(下面的寫法2就必須要求android:name和android:value間必須有且只有一個空格符)。但是也有一個缺點:AndroidManifest.xml中如果出現其他內容與替換內容一樣的話也會被替換掉,不過這個概率是微乎其微的。重新選擇運行選項,如下:


寫法2

<?xml version="1.0" encoding="UTF-8"?>
<!-- 渠道包打包腳本  ant deploy -->
<project name="custom_rules" >

    <taskdef resource="net/sf/antcontrib/antcontrib.properties" >

        <classpath>

            <pathelement location="lib/ant-contrib-1.0b3.jar" />
        </classpath>
    </taskdef>

    <!-- 循環打包 -->

    <target name="deploy" >

        <antcall target="clean" />

        <foreach
            delimiter=","
            list="${market_channels}"
            param="channel"
            target="modify_manifest" >
        </foreach>
    </target>

    <target name="modify_manifest" >

        <!-- 獲取渠道名字 -->

        <propertyregex
            input="${channel}"
            override="true"
            property="channelname"
            regexp="(.*):"
            select="\1" />
        <!-- 獲取渠道號碼 -->

        <propertyregex
            input="${channel}"
            override="true"
            property="channelkey"
            regexp=":(.*)"
            select="\1" />
		
        <replaceregexp
            byline="false"
            flags="g" >

            <!-- 匹配的內容是 android:name="channelname" android:value="(.*)" -->

            <regexp pattern="android:name="channelname" android:value="(.*)"" />
            <!-- 匹配之後將其替換爲 android:name="${channelname}" android:value="channelkey" -->

            <substitution expression="android:name="${channelname}" android:value="${channelkey}"" />
            <!-- 正則表達式需要匹配的文件爲AndroidManifest.xml -->

            <fileset
                dir=""
                includes="AndroidManifest.xml" />
        </replaceregexp>

        <!-- 打包 -->

        <antcall target="release" />
        <!-- 拷貝渠道包到指定目錄下 -->

        <copy
            file="${out.absolute.dir}/${ant.project.name}-release.apk"
            tofile="${out.absolute.dir}/out/${ant.project.name}-v${version}-${channelkey}.apk" />

        <!-- 打包完一個渠道包後把渠道名和渠道號替換回原來格式,這樣可以進行下一次替換 -->

        <replaceregexp
            byline="false"
            flags="g" >

            <regexp pattern="android:name="${channelname}" android:value="(.*)"" />

            <substitution expression="android:name="channelname" android:value="channelkey"" />
            <!-- 正則表達式需要匹配的文件爲AndroidManifest.xml -->

            <fileset
                dir=""
                includes="AndroidManifest.xml" />
        </replaceregexp>

    </target>

</project>
這時候AndroidManifest.xml中的渠道meta節點就要改爲下面這樣了:
<meta-data
            android:name="channelname" android:value="channelkey" >
        </meta-data>
android:name="channelname"和android:value="channelkey"之間的那個空格符不能多也不能少!
其他的和寫法1差不多,可以看上面的註釋。

打包結果

經過上面執行ant構建完成之後,刷新輸出目錄bin,可以看到有帶有渠道號的apk包啦!

下面,我們將三個包反編譯看看AndroidManifest.xml中的渠道信息到底有沒有被替換呢?可以看到,三個apk中的渠道信息都成功被替換了!


好啦,Ant批量打包就講完啦!大家動手試試吧~


 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章