Ant自動打包(可動態修改包名、資源等)生成不同簽字不同包名的APP

yangxi_001發表於2014-03-21
Ant自動打包(可動態修改包名、資源等)生成不同簽名不同包名的APP

上一篇我們介紹了Ant自動生成APK的例子:http://blog.csdn.net/up1up2up3/article/details/19558699

由於公司專案需要,需要實現Ant自動打包(可動態修改包名、資源等)生成不同簽名不同包名的APP。

當然是先搜搜網上有木有相關的實現,發現複製來複制去都是同一個,但是不夠詳細,基本上就是說幾句,然後貼了個build.xml(叫我們這些新手、很少搞指令碼的人情何以堪 = =!),我主要參考了這個:http://www.zdyc.net/html/diary/newWrite/showlog_vm/sid=1/cat_id=-1/log_id=283,要了解的就是利用ant執行編寫的指令碼程式

指令碼實現的主要步驟如下:

1、拷貝當前專案到臨時目錄

2、修改 AndroidManifest.xml包名以及java檔案涉及到的包名(import、package等)


3、生成新的R檔案(androidSDK/platform-tools\aapt.exe)

4、專案編譯

5、生成dex檔案(androidSDK\platform-tools\dx.bat)


6、打包資原始檔(打包資原始檔 androidSDK\platform-tools\aapt.exe)


7、APK打包(androidSDK\apkbuilder.bat)

PS:建議先行去了解下Ant指令碼執行

先看下下面的build.xml(各個步驟都有進行說明):

<?xml version="1.0" encoding="UTF-8"?>
<project name="BQPUBLIC" default="ZWTH">



    <!-- The local.properties file is created and updated by the 'android' tool.
         It contains the path to the SDK. It should *NOT* be checked into
         Version Control Systems. -->
    <property file="local.properties" />

    <!-- The ant.properties file can be created by you. It is only edited by the
         'android' tool to add properties to it.
         This is the place to change some Ant specific build properties.
         Here are some properties you may want to change/update:

         source.dir
             The name of the source directory. Default is 'src'.
         out.dir
             The name of the output directory. Default is 'bin'.

         For other overridable properties, look at the beginning of the rules
         files in the SDK, at tools/ant/build.xml

         Properties related to the SDK location or the project target should
         be updated using the 'android' tool with the 'update' action.

         This file is an integral part of the build system for your
         application and should be checked into Version Control Systems.

         -->
    <property file="ant.properties" />

    <!-- if sdk.dir was not set from one of the property file, then
         get it from the ANDROID_HOME env var.
         This must be done before we load project.properties since
         the proguard config can use sdk.dir -->
    <property environment="env" />
    <condition property="sdk.dir" value="${env.ANDROID_HOME}">
        <isset property="env.ANDROID_HOME" />
    </condition>

    <!-- The project.properties file is created and updated by the 'android'
         tool, as well as ADT.

         This contains project specific properties such as project target, and library
         dependencies. Lower level build properties are stored in ant.properties
         (or in .classpath for Eclipse projects).

         This file is an integral part of the build system for your
         application and should be checked into Version Control Systems. -->
    <loadproperties srcFile="project.properties" />

    <!-- quick check on sdk.dir -->
    <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 per project custom build rules if present at the root of the project.
        This is the place to put custom intermediary targets such as:
            -pre-build
            -pre-compile
            -post-compile (This is typically used for code obfuscation.
                           Compiled code location: ${out.classes.absolute.dir}
                           If this is not done in place, override ${out.dex.input.absolute.dir})
            -post-package
            -post-build
            -pre-clean
    -->
    <import file="custom_rules.xml" optional="true" />

    <!-- Import the actual build file.

         To customize existing targets, there are two options:
         - Customize only one target:
             - copy/paste the target into this file, *before* the
               <import> task.
             - customize it to your needs.
         - Customize the whole content of build.xml
             - copy/paste the content of the rules files (minus the top node)
               into this file, replacing the <import> task.
             - customize to your needs.

         ***********************
         ****** IMPORTANT ******
         ***********************
         In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
         in order to avoid having your file be overridden by tools such as "android update project"
    -->
    <!-- version-tag: 1 -->
    <import file="${sdk.dir}/tools/ant/build.xml" />


<!--修改包名等-->
<!--相關環境及工具配置-->
 <property name="sdk.platformtools" value="${sdk.dir}/platform-tools" />
 <property name="sdk.tools" value="${sdk.dir}/tools" />
 <property name="aapt" value="${sdk.platformtools}/aapt.exe" />
  <property name="adb" value="${sdk.platformtools}/adb.exe" />
 <property name="dx" value="${sdk.platformtools}/dx.bat" />
 <property name="apkbuilder" value="${sdk.tools}/apkbuilder.bat" />
 <property name="android.jar" value="${sdk.dir}/platforms/android-10/android.jar" />



 <property name="old_package_name" value="com.zzx.xxxxxxic" />
 <property name="new_package_name" value="com.zwtx.xxxxxxic" />
 <property name="project_new">ZWTH</property>
 <property name="reasedAPK" value="${project_new}.apk" />
 <property name="org_project.dir" value="D:/test/xxPUBLIC" /><!--原工程目錄-->


 <!--新工程各個目錄-->
  <property name="build.dir" value="${org_project.dir}/build" />
 <property name="project.dir" value="${org_project.dir}/temp" /><!--新工程目錄-->
 <property name="classes.dir" value="${project.dir}/bin/classes" />
 <property name="buildtemp.dir" value="${project.dir}/build" />
 <property name="src.dir" value="${project.dir}/src" />
 <property name="res.dir" value="${project.dir}/res" />
 <property name="gen.dir" value="${project.dir}/gen" />
 <property name="asset.dir" value="${project.dir}/asset" />

 <target name="init">
     <delete dir="${build.dir}"></delete>
     <mkdir dir="${build.dir}"/>
     <delete dir="${project.dir}"></delete>
     <mkdir dir="${project.dir}"/>

	  <copy todir="${project.dir}">
         <fileset dir="${org_project.dir}" includes="**/*"/>
     </copy>


     <!--替換工程中出現的包名 -->
  <replaceregexp flags="g" encoding="UTF-8" byline="true">
      <regexp pattern="package(.*)${old_package_name}"/>
         <substitution expression="package="${new_package_name}"/>
            <fileset dir="${project.dir}" includes="AndroidManifest.xml"/>
     </replaceregexp>

  <replaceregexp flags="g" encoding="UTF-8" byline="true">
      <regexp pattern="import(.*)${old_package_name}.R"/>
         <substitution expression="import ${new_package_name}.R"/>
            <fileset dir="${project.dir}/src" includes="**/*.java"/>
     </replaceregexp>
    </target>


  <!--生成R.java檔案 ${sdk.dir}\platform-tools\aapt.exe-->
    <target name="genRJava">
        <exec executable="${aapt}" failonerror="true">
            <arg value="package"/>
            <arg value="-m"/>
            <arg value="-J"/>
            <arg value="${project.dir}/gen"/>
            <arg value="-M"/>
            <arg value="${project.dir}/AndroidManifest.xml"/>
            <arg value="-S"/>
            <arg value="${res.dir}"/>
            <arg value="-I"/>
            <arg value="${android.jar}"/>
        </exec>
    </target>
    <!-- 專案編譯 -->
    <target name="compile" >
        <javac encoding="UTF-8" target="1.5" debug="true" extdirs="" 
         srcdir="${gen.dir};${src.dir}" 
         destdir="${classes.dir}" bootclasspath="${android.jar}">
            <classpath>
                <fileset dir="${project.dir}/libs" includes="*.jar">
                </fileset>
            </classpath>
        </javac>
    </target>
<!-- 生成dex檔案 ${sdk.dir}\platform-tools\dx.bat -->
    <target name="dex" >
        <apply executable="${dx}" failonerror="true" parallel="true">
            <arg value="--dex"/>
            <arg value="--output=${buildtemp.dir}/classes.dex"/>
            <arg path="${classes.dir}"/>
            <fileset dir="${project.dir}/libs" includes="*.jar"/>
        </apply>
    </target>

 <!-- 打包資原始檔 ${sdk.dir}\platform-tools\aapt.exe -->
    <target name="packageRes">
        <exec executable="${aapt}" failonerror="true">
            <arg value="package"/>
            <arg value="-f"/>
            <arg value="-M"/>
            <arg value="${project.dir}/AndroidManifest.xml"/>
            <arg value="-S"/>
            <arg value="${res.dir}"/>
            <arg value="-A"/>
            <arg value="${asset.dir}"/>
            <arg value="-I"/>
            <arg value="${android.jar}"/>
            <arg value="-F"/>
            <arg value="${buildtemp.dir}/resources.ap_"/>
        </exec>
    </target>

 <!-- 打包Apk -->
    <target name="ZWTH" depends="init,genRJava,compile,dex,packageRes">
        <!-- 打包 -->
        <exec executable="${apkbuilder}" failonerror="true">
            <arg value="${buildtemp.dir}/unsigntest.apk"/>
            <arg value="-u"/>
            <arg value="-z"/>
            <arg value="${buildtemp.dir}/resources.ap_"/>
            <arg value="-f"/>
            <arg value="${buildtemp.dir}/classes.dex"/>
            <arg value="-rf"/>
            <arg value="${src.dir}"/>
            <arg value="-rj"/>
            <arg value="${project.dir}/libs"/>
        </exec>
        <!-- 簽名 -->
        <!--java -jar signapk.jar platform.x509.pem platform.pk8 TVJU.apk new.apk -->
       <!-- <exec executable="java" failonerror="true">
            <arg value="-jar"/>
            <arg value="${project.dir}/STBsign/signapk.jar"/>
            <arg value="${project.dir}/STBsign/platform.x509.pem"/>
            <arg value="${project.dir}/STBsign/platform.pk8"/>
            <arg value="${buildtemp.dir}/unsigntest.apk"/>
            <arg value="${buildtemp.dir}/TVJUSIGN.apk"/>
        </exec> -->
     <!-- -->
    <signjar
         jar="${buildtemp.dir}/unsigntest.apk"
         signedjar="${build.dir}/${reasedAPK}"
         keystore="${key.store}"
         storepass="${key.store.password}"
         alias="${key.alias}"
         keypass="${key.alias.password}"
         verbose="-verbose"/>
   </target>


</project>


接下來說下編譯過程中的出現的一些問題:

1、Ant編譯utf-8非法字元

     

   這個問題可以百度下,很多人出現,也有各式各樣的解決方法,不過這只是廣告,一般不會有什麼問題,我這邊是忽略掉了

2、value for 'keystore' is not valid,這個百度下了,沒有出現啊!!!坑爹了,搞了我很久

     
   後來發現這根本就是個sb的錯誤啊!!TM的,原來我在引用local.properties(或ant.properties)的時候,其中的keystore的path寫錯了

   key.store=D:/test/BPUBLIC/android.keystore寫成key.store=D\:/test/BPUBLIC/android.keystore(剛開始轉義了下,忘記去掉了)

   

3、編譯的時候我執行 ant release發現總是生成原專案的apk,根本就沒有修改完後的新包名的apk,甚至臨時目錄都木有啊!!!

    後來查詢了這篇文章《Ant Buildfile中project標籤的default屬性作用》才發現<project name="BPUBLIC" default="ZWTH">中default以及子標籤<target>標籤的含義我沒注意到,<target>可以由命令列進行顯示的呼叫,也可以在內部使用如可以直接呼叫ant init、ant compile等。如果不寫引數,則預設的build檔案是build.xml,預設的目標是<project>的default屬性定義的目標。

  我們執行的時候可以一步步執行,也可以一次性執行目標,如:ant ZWTH

  根據上面的ant檔案及步驟,可以一步步編譯生成:

  

 

其餘的就不再一一列舉了。

一次性編譯是用如下命令(根據<target name="ZWTH" depends="init,genRJava,compile,dex,packageRes">的依賴關係):

 

build success!!!

相關文章