zoukankan      html  css  js  c++  java
  • Android打包之Ant多渠道打包的实现

    在Android打包时,不同的应用市场会有不同的配置,特别是当有广告里,里面要有相应的市场标识,如果还是一个一个的生成,显然耗时又耗力,还易出错,所以面对各应用市场的多种渠道打包必须要依赖于脚本实现。这里是ant多渠道打包的实现。直接上脚本代码。

    build_mulity_channel.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <project
        name="AntDemo"
        default="loop-pack" >
    
        <property
            name="sdk-folder"
            value="D:android-sdk-windows" />
    
        <property
            name="platform-folder"
            value="${sdk-folder}platformsandroid-8" />
    
        <property
            name="platform-tools-folder"
            value="${sdk-folder}platform-tools" />
    
        <property
            name="jdk-folder"
            value="D:Program Files (x86)Javajdk1.6.0_45" />
    
        <property
            name="ant-lib"
            value="D:Antlib" />
    
        <!-- tools -->
    
        <property
            name="android-jar"
            value="${platform-folder}android.jar" />
    
        <property
            name="tools.aapt"
            value="${platform-tools-folder}aapt.exe" />
    
        <property
            name="tools.javac"
            value="${jdk-folder}injavac.exe" />
    
        <property
            name="tools.dx"
            value="${platform-tools-folder}dx.bat" />
    
        <property
            name="tools.apkbuilder"
            value="${sdk-folder}	oolsapkbuilder.bat" />
    
        <property
            name="tools.zipalign"
            value="${sdk-folder}	oolszipalign.exe" />
    
        <property
            name="tools.jarsigner"
            value="${jdk-folder}injarsigner.exe" />
    
        <!-- dir -->
    
        <property
            name="project-dir"
            value="G:CodeAndroidWorkspaceAntDemo" />
    
        <property
            name="res"
            value="${project-dir}
    es" />
    
        <property
            name="gen"
            value="${project-dir}gen" />
    
        <property
            name="src"
            value="${project-dir}src" />
    
        <property
            name="bin"
            value="${project-dir}in" />
    
        <property
            name="assets"
            value="${project-dir}assets" />
    
        <property
            name="libs"
            value="${project-dir}libs" />
    
        <!-- files -->
    
        <property
            name="manifest"
            value="${project-dir}AndroidManifest.xml" />
    
        <property
            name="java-file-gen"
            value="${gen}comexampleantdemo*.java" />
    
        <property
            name="java-file-src"
            value="${src}comexampleantdemo*.java" />
    
        <property
            name="keystore-name"
            value="${project-dir}my.keystore" />
    
        <property
            name="keystore-alias"
            value="ant_test" />
    
        <!-- multi-channel -->
    
        <property
            name="channels"
            value="BaiDu:baidu,Lenovo:lenovo,XiaoMi:xiaomi" />
    
        <property
            name="channelname"
            value="" />
    
        <!-- task -->
    
        <!-- loop pack -->
    
        <taskdef resource="net/sf/antcontrib/antlib.xml" >
    
            <classpath>
    
                <fileset dir="${ant-lib}" />
            </classpath>
        </taskdef>
    
        <target name="loop-pack" >
    
            <echo>
    Initialize...
    
            </echo>
    
            <delete dir="${bin}" />
    
            <mkdir dir="${bin}" />
    
            <echo>
    loop package...
    
            </echo>
    
            <foreach
                delimiter=","
                list="${channels}"
                param="nameandchannel"
                target="modify_manifest" >
            </foreach>
        </target>
    
        <target name="modify_manifest" >
    
            <!-- fetch channel name -->
    
            <propertyregex
                input="${nameandchannel}"
                override="true"
                property="channelname"
                regexp="(.*):"
                select="1" />
            <!-- fetch channel number -->
    
            <propertyregex
                input="${nameandchannel}"
                override="true"
                property="channelkey"
                regexp=":(.*)"
                select="1" />
            <!-- match and replace channel info -->
    
            <replaceregexp
                byline="false"
                encoding="utf-8"
                flags="g" >
      
                <regexp pattern="meta-data android:name="APP_PID" android:value="(.*)"" />
    
                <substitution expression="meta-data android:name="APP_PID" android:value="${channelkey}"" />
    
                <fileset
                    dir="${project-dir}"
                    includes="AndroidManifest.xml" />
            </replaceregexp>
    
            <antcall target="release" />
        </target>
    
        <target name="init-channel" >
    
            <echo>
    Initialize channel...
    
    
    
    
    
    
            </echo>
    
            <var
                name="out-dir"
                value="${bin}${channelname}" />
    
            <var
                name="dex-name"
                value="${out-dir}classes.dex" />
    
            <var
                name="pakcage-temp-name"
                value="${out-dir}${ant.project.name}" />
    
            <var
                name="unsigned-apk-name"
                value="${ant.project.name}_unsigned.apk" />
    
            <var
                name="unsigned-apk-path"
                value="${out-dir}${unsigned-apk-name}" />
    
            <var
                name="signed-apk-name"
                value="${ant.project.name}_signed.apk" />
    
            <var
                name="signed-apk-path"
                value="${out-dir}${signed-apk-name}" />
    
            <var
                name="dest-apk"
                value="${out-dir}/${ant.project.name}_${channelname}.apk" />
    
            <delete dir="${out-dir}" />
    
            <mkdir dir="${out-dir}" />
        </target>
    
        <target
            name="gen-R"
            depends="init-channel" >
    
            <echo>
    Generating R.java from the resources... 
    
    
    
    
    
    
            </echo>
    
            <exec
                executable="${tools.aapt}"
                failonerror="true" >
    
                <arg value="package" />
    
                <arg value="-f" />
    
                <arg value="-m" />
    
                <arg value="-J" />
    
                <arg value="${gen}" />
    
                <arg value="-S" />
    
                <arg value="${res}" />
    
                <arg value="-M" />
    
                <arg value="${manifest}" />
    
                <arg value="-I" />
    
                <arg value="${android-jar}" />
            </exec>
        </target>
    
        <target
            name="compile"
            depends="gen-R" >
    
            <echo>
    Compile...
    
    
    
    
    
    
            </echo>
    
            <javac
                bootclasspath="${android-jar}"
                compiler="javac1.6"
                destdir="${out-dir}"
                encoding="utf-8"
                includeAntRuntime="true"
                listfiles="true"
                target="1.6" >
    
                <src path="${project-dir}" />
    
                <classpath>
    
                    <fileset
                        dir="${libs}"
                        includes="*.jar" />
                    <!-- 引用第三方jar包需要引用,用于辅助编译,并没有将jar打包进去。jar的打包在dex命令中。 -->
                </classpath>
            </javac>
        </target>
    
        <target
            name="dex"
            depends="compile" >
    
            <echo>
    Generate dex...
    
    
    
    
    
    
            </echo>
    
            <exec
                executable="${tools.dx}"
                failonerror="true" >
    
                <arg value="--dex" />
    
                <arg value="--output=${dex-name}" />
    
                <arg value="${out-dir}" />
                <!-- classes文件位置 -->
    
                <arg value="${libs}" />
                <!-- 把libs下所有jar打包 -->
            </exec>
        </target>
    
        <target
            name="package"
            depends="dex" >
    
            <echo>
       Package resource and assets...
    
    
    
    
    
    
            </echo>
    
            <exec
                executable="${tools.aapt}"
                failonerror="true" >
    
                <arg value="package" />
    
                <arg value="-f" />
    
                <arg value="-A" />
    
                <arg value="${assets}" />
    
                <arg value="-S" />
    
                <arg value="${res}" />
    
                <arg value="-I" />
    
                <arg value="${android-jar}" />
    
                <arg value="-M" />
    
                <arg value="${manifest}" />
    
                <arg value="-F" />
    
                <arg value="${pakcage-temp-name}" />
            </exec>
        </target>
    
        <target
            name="build-unsigned-apk"
            depends="package" >
    
            <echo>
      Build unsigned apk
    
    
    
    
    
    
            </echo>
    
            <exec
                executable="${tools.apkbuilder}"
                failonerror="true" >
    
                <arg value="${unsigned-apk-path}" />
    
                <arg value="-v" />
    
                <arg value="-u" />
    
                <arg value="-z" />
    
                <arg value="${pakcage-temp-name}" />
    
                <arg value="-f" />
    
                <arg value="${dex-name}" />
    
                <arg value="-rf" />
    
                <arg value="${src}" />
            </exec>
        </target>
    
        <target
            name="sign-apk"
            depends="build-unsigned-apk" >
    
            <echo>
      Sign apk
    
    
    
    
    
    
            </echo>
    
            <exec
                executable="${tools.jarsigner}"
                failonerror="true" >
    
                <arg value="-keystore" />
    
                <arg value="${keystore-name}" />
    
                <arg value="-storepass" />
    
                <arg value="123456" />
    
                <arg value="-keypass" />
    
                <arg value="123456" />
    
                <arg value="-signedjar" />
    
                <arg value="${signed-apk-path}" />
    
                <arg value="${unsigned-apk-path}" />
    
                <arg value="${keystore-alias}" />
            </exec>
        </target>
    
        <target
            name="zipalign"
            depends="sign-apk" >
    
            <echo>
    Zipalign...
    
    
    
    
    
    
            </echo>
    
            <exec
                executable="${tools.zipalign}"
                failonerror="true" >
    
                <arg value="-v" />
    
                <arg value="4" />
    
                <arg value="${signed-apk-path}" />
    
                <arg value="${dest-apk}" />
            </exec>
        </target>
    
        <target
            name="release"
            depends="zipalign" >
    
            <delete file="${pakcage-temp-name}" />
    
            <delete file="${unsigned-apk-path}" />
    
            <delete file="${signed-apk-path}" />
    
            <echo>
    APK is released. path:${zipalign-apk-path}_${channelname}
    
    
    
    
    
    
            </echo>
        </target>
    
    </project>

    注:

    1、property是自定义的字段,主要是用于配置,比如sdk、jdk等的路径。

    2、taskdef是引用ant的lib。在多渠道打包时,由于要用到ant-contrib-1.0b3.jar以实现foreah循环等,所以需要下载该jar放到ant的lib文件夹下。开始时,我没有配置这个引用,结果报错"failed to create task or type foreach"。错误截图如下。


    3、loop-pack的target中先初始化bin文件夹(先删除后再创建)。然后再进行foreach循环。

    4、foreach循环是实现循环打包的关键。

    (1)、这里面有一个参数list引用的是property中的一个定义字段channels。channels中将渠道名和渠道标识写成key:value的形式,并且多个之间以逗号来分隔。

    (2)、delimiter参数指的就是多个渠道之间的分隔符号,必须要一致,即使用逗号。所以如果定义时使用了分号,那么这里也要使用分号。

    (3)、param相当于是循环中的一个变量,可以在其他target中引用。比如modify_manifest的target中就用到了该值。

    (4)、target参数是该循环体内要调用的target。

    5、modify_manifest实现AndroidManifest的动态修改。

    (1)、propertyregex是属性的正则表达式,其中的input参数是输入的值(这里引用foreach循环中的param),property参数相当于是定义一个变量名以便其他地方引用(比如后边的init-channel中就引用了channelname)。regexp是正则表达式。

    (2)、replaceregexp是替换的正则表达式,是通过正则表式匹配到要替换的部分。regexp中,由于双引号是xml的特殊标记,所以必须用转义来表达双引号(&quot;)。

    meta-data android:name="APP_PID" android:value="(.*)"
    相当于
    meta-data android:name="APP_PID" android:value="(.*)"
    其中(.*)是正则匹配所有字符。要特别注意这句正则表达式的结构必须要与AndroidManifest.xml中的相一致。如果AndroidManifest.xml中使用了格式化(ctrl+shift+f),那么表达式的格造会有所不同,因为在格式化后,xml中自动补上一些空格。具体可以参看下面的未格式化和格式化的数据区别。我开始就是习惯性的进行格式化,结果怎么都无法匹配到对应的APP_PID。如果需要使用格式化的,需要修改正则表达式,同时还要将替换数据substitution也作相应的修改。



    (3)、substitution是正则匹配替换的数值,这里可以使用变量,比如${channelkey}。

    (4)、fileset是引用需要修改的文件。

    (5)、antcall是修改之后需要继续执行的任务target。这里调用的是release.

    6、在init-channel中定义了var变量,以便于后面的引用。使用var可以动态的使用foreach计算出来的值(比如channelname)。

    转载请注明出处:http://blog.csdn.net/xxdddail/article/details/21384995

    源码下载


  • 相关阅读:
    Hibernate4与Spring3的不兼容问题
    关于Struts2框架下jsp获取action的布尔值问题
    js 操作select和option常见用法
    用socaket编写客户端与服务端程序相互发送消息
    Web编程
    第二篇
    java基础
    GeoServer style标注中文乱码配置
    RabbitMQ高可用方案总结
    Visual Studio 2019 注册KEY
  • 原文地址:https://www.cnblogs.com/sparkleDai/p/7605018.html
Copyright © 2011-2022 走看看