Android笔记之:App自动化之使用Ant编译项目多渠道打包的使用详解

随着工程越来越复杂,项目越来越多,以及平台的迁移(我最近就迁了2回),还有各大市场的发布,自动化编译android项目的需求越来越强烈,后面如果考虑做持续集成的话,会更加强烈。
    经过不断的尝试,在ubuntu环境下,以花界为例,我将一步一步演示如何使用命令行,使用ant编译android项目,打包多渠道APK。
    要点:
    (1). 编译android的命令使用
    (2). ant基本应用
    (3). 多项目如何编译(包含android library)
    (4). 如何多渠道打包
    ps:我将以最原始的方式来实现,而不是使用android自带的ant编译方式,并尽量详细解释,这样有益于我们彻底搞懂android打包的基本原理。

1. Android编译打包的整体过程
    使用ant,ant的参考文档:http://ant.apache.org/manual/index.html
    首先,假设现在已经有这样的一个项目(多工程的,简单的单工程就更简单了):

world
├── baseworld                                               //android library,基础类库,共享于其他主应用
├── floworld                                                   //android project,花界应用
├── healthworld                                             //android project,健康视线应用
├── speciality                                                 //android project,其它应用
├── starworld                                                 //android project,其它应用
├── build.xml                                                 //ant编译脚本,可用于整个项目的编译,也可只编译某个工程
├── code_checks.xml
├── kaiyuanxiangmu_world.keystore             //密钥
└── README.md

一个大的项目world,下面有1个基础Android Library和4个Android Project。我们要做的就是编译这4个人project成对应的一系列各市场APK。
    那么我们在来看看baseworld和floworld的工程结构:
    Android Library,baseworld:

baseworld
├── assets                                                       //assets目录,其中文件可能会被主应用覆盖
├── libs                                                           //存放第三方jar库
├── res                                                            //类库资源,其中文件可能会被主应用覆盖
├── src                                                            //源码,可直接供主应用使用
├── AndroidManifest.xml
├── lint.xml
├── proguard.cfg
├── project.properties
└── README.md

和Android Project,floworld:

floworld/
├── assets                                                       //assets目录,主应用优先级高
├── build
├── data
├── libs                                                           //存放第三方jar库
├── res                                                            //主应用资源,主应用优先级高
├── src                                                            //源码,可直接供主应用使用
├── AndroidManifest.xml
├── build.xml                                                   //ant编译脚本,可用于整个项目的编译,也可只编译某个工程
├── default.properties
├── lint.xml
├── proguard.cfg
├── project.properties
└── README.md

结构已经出来了,那么android打包主要是在做什么?
    说白了,先编译java成class,再把class和jar转化成dex,接着打包aaset和res等资源文件为res.zip(以res.zip示例),再把dex和res.zip合并为一个未签名apk,再对它签名,最终是一个带签名的apk文件。
    当然这么说忽略了很多细节。
    下面我把这些步骤用一句话分别列举如下,脑子里先有一个整体的流程,后续再结合ant详细展开:
    (1). 生成用于主应用的R.java;
    (2). 生成用于库应用的R.java(如果有库应用);
    (3). 编译所有java文件为class文件;
    (4). 打包class文件和jar包为classes.dex;
    (5). 打包assets和res资源为资源压缩包(如res.zip,名字可以自己定义);
    (6). 组合classes.dex和res.zip生成未签名的APK;
    (7). 生成有签名的APK;
    针对多项目同步发布和多渠道打包问题,我们需要额外增加三个处理:
    (1). 各个工程下建立一个build.xml,然后在整个项目的根目录下建立一个build.xml,用于统一编译各个工程的;
    (2). 各个工程的build.xml,通过传入市场ID和应用Version参数生成对应的版本
    (3). 针对(1),(2)问题,建立一个批处理支持一键生成所有版本
    大概流程即是如此。

2. 建立各个工程的ant脚本文件build.xml(位置:floworld/build.xml)
    因为需要创建一些基本的文件目录和清理上次生成的文件,所以我们简单的定义一下几个目标吧:init,main,clean。
    代码模板如下:


代码如下:

<project default="main" basedir=".">
     <!-- 初始化:创建目录,清理目录等 -->
     <target name="init">
           <echo>start initing ... </echo> 
           <!-- ... ... -->
           <echo>finish initing. </echo>
     </target>
     <!-- 打包过程,默认值 -->
     <target name="main" depends="init">
     </target>
     <!-- 清理不需要的生成文件等-->
     <target name="clean">
     </target>
</project>

3. 初始化
    在正式打包之前,有必要说明一下可能需要用到的初始化变量和操作。
    前面已经讲述了打包的大概流程,现在,第一, 打包需要你使用哪个版本android.jar; 第二, 生成的R文件放到gen目录下; 第三, 生成的classes文件放到bin目录下; 第四, 生成的打包文件放到out目录下; 第五, 生成的各市场版本放到build目录下。目录完全可以自定义。
    所以,如下的初始化必须先要做好,不然后面会提示找不到目录:


代码如下:

<project default="main" basedir=".">
    <!-- 这个是android.jar路径,具体情况具体配置 -->
    <property name="android-jar" value="/usr/lib/android-sdk/platforms/android-10/android.jar" />
    <!-- 用于生成多渠道版本的APK文件名,提供了默认值,后面会讲到 -->
    <property name="apk-name" value="product" />
    <property name="apk-version" value="latest" />
    <property name="apk-market" value="dev" />
    <target name="init">
        <echo>start initing ... </echo>
        <mkdir dir="out" />
        <delete>
            <fileset dir="out"></fileset>
        </delete>
        <mkdir dir="gen" />
        <delete>
            <fileset dir="gen"></fileset>
        </delete>
        <mkdir dir="bin/classes" />
        <delete>
            <fileset dir="bin/classes"></fileset>
        </delete>
        <!-- ${apk-version}表示版本,后面会详细讲到 -->
        <mkdir dir="build/${apk-version}" />
        <echo>finish initing. </echo>
    </target>
     ... ...
</project>

4. 生成R.java
    Android Library和Android Project应用的R.java是来自不同的package的。比如:
    (1). baseworld中导入的包是import com.tianxia.lib.baseworld.R;
    (2). floworld中导入的包是import com.tianxia.lib.baseworld.R;
    但是他们最终是调用统一的资源,所以这两个R.java文件必须一致。
    下面是主应用的R.java的生成脚本:


代码如下:

<echo>generating R.java for project to dir gen (using aapt) ... </echo>
<exec executable="aapt">
    <arg value="package" /> <!-- package表示打包-->
    <arg value="-m" /> <!--m,J,gen表示创建包名的目录和R.java到gen目录下 -->
    <arg value="-J" />
    <arg value="gen" />
    <arg value="-M" /> <!-- M指定AndroidManifest.xml文件-->
    <arg value="AndroidManifest.xml" />
    <arg value="-S" /> <!-- S指定res目录,生成对应的ID,可多个-->
    <arg value="res" />
    <arg value="-S" />
    <arg value="../baseworld/res" /><!-- 注意点:同时需要调用Library的res-->
    <arg value="-I" /> <!-- I指定android包的位置-->
    <arg value="${android-jar}" />
    <arg value="--auto-add-overlay" /> <!-- 这个重要,覆盖资源,不然报错-->
</exec>

注意res和../baseworld/res两个顺序不能搞反,写在前面具有高优先级,我们当然优先使用主应用的资源了,这样就能正确覆盖库应用的资源,实现重写。
    库应用的R.java的生成脚本差不多,区别是指定库应用的AndroidManifest.xml,以用于生成的是不同的包和目录。
    另外,aapt的使用中特别说明了,为了库应用的资源更好的可重用,库应用生成的R.java字段不需要修饰为final,加上参数--non-constant-id即可。


代码如下:

<echo>generating R.java for library to dir gen (using aapt) ... </echo>
<exec executable="aapt">
    <arg value="package" />
    <arg value="-m" />
    <arg value="--non-constant-id" /> <!-- 加了这个参数-->
    <arg value="--auto-add-overlay" />
    <arg value="-J" />
    <arg value="gen" />
    <arg value="-M" />
    <arg value="../baseworld/AndroidManifest.xml" /> <!-- 库应用的manifest-->
    <arg value="-S" />
    <arg value="res" />
    <arg value="-S" />
    <arg value="../baseworld/res" />
    <arg value="-I" />
    <arg value="${android-jar}" />
</exec>

这样的话就可以生成2个正确的R.java文件了(如果你引用了两个库,则需要生成3个R.java,以此类推)。
    结果如下:


代码如下:

gen
└── com
    └── tianxia
        ├── app
        │   └── floworld
        │       └── R.java
        └── lib
            └── baseworld
                └── R.java

5. 编译java文件为class文件
    使用javac命令把src目录,baseworld/src目录,gen/*/R.java这些java编译成class文件:
    命令原型是:


代码如下:

//示例
javac -bootclasspath <android.jar> -s <src> -s <src> -s <gen> -d bin/classes *.jar

转化成ant脚本为:


代码如下:

<!-- 第三方jar包需要引用,用于辅助编译 -->
<path id="project.libs">
    <fileset dir="libs">
        <include name="*.jar" />
    </fileset>
</path>
<echo>compiling java files to class files (include R.java, library and the third-party jars) ... </echo>
<!-- 生成的class文件全部保存到bin/classes目录下 -->
<javac destdir="bin/classes" bootclasspath="${android-jar}">
    <src path="../baseworld/src" />
    <src path="src" />
    <src path="gen" />
    <classpath refid="project.libs" />
</javac>

6. 打包class文件为classes.dex
    这步简单,用dx命令把上步生成的classes和第三方jar包打包成一个classes.dex。
    命令原型是:


代码如下:

//示例
//后面可以接任意个第三方jar路径
dx --dex --output=out/classes.dex bin/classes libs/1.jar libs/2.jar

转化成ant脚本为:


代码如下:

<echo>packaging class files (include the third-party jars) to calsses.dex ... </echo>
<exec executable="dx">
    <arg value="--dex" />
    <arg value="--output=out/classes.dex" /><!-- 输出 -->
    <arg value="bin/classes" /> <!-- classes文件位置 -->
    <arg value="libs" /> <!-- 把libs下所有jar打包 -->
</exec>

7. 打包res,assets为资源压缩包(暂且命名为res.zip)
    还是使用aapt命令,如生成R.java最大的不同是参数-F,意思是生成res.zip文件。
    命令原型和ant脚本差不多:


代码如下:

<echo>packaging resource (include res, assets, AndroidManifest.xml, etc.) to res.zip ... </echo>
<exec executable="aapt">
    <arg value="package" />
    <arg value="-f" /> <!-- 资源覆盖重写 -->
    <arg value="-M" />
    <arg value="AndroidManifest.xml" />
    <arg value="-S" />
    <arg value="res" />
    <arg value="-S" />
    <arg value="../baseworld/res" />
    <arg value="-A" /> <!-- 与R.java不同,需要asset目录也打包 -->
    <arg value="assets" />
    <arg value="-I" />
    <arg value="${android-jar}" />
    <arg value="-F" /> <!-- 输出资源压缩包 -->
    <arg value="out/res.zip" />
    <arg value="--auto-add-overlay" />
</exec>

8. 使用apkbuilder命令组合classes.dex,res.zip和AndroidManifest.xml为未签名的apk
    apkbuilder命令能把class类,资源等文件打包成一个未签名的apk,原型命令和ant脚本类似:


代码如下:

<echo>building unsigned.apk ... </echo>
<exec executable="apkbuilder">
    <arg value="out/unsigned.apk" /> <!-- 输出 -->
    <arg value="-u" /> <!-- u指创建未签名的包-->
    <arg value="-z" /> <!-- 资源压缩包 -->
    <arg value="out/res.zip" />
    <arg value="-f" /> <!-- dex文件 -->
    <arg value="out/classes.dex" />
</exec>

  这个命令比较简单。

9. 签名未签名的apk
    使用jarsigner命令对上步中产生的apk签名。这是个传统的java命令,非android专用。
    原型命令和ant脚本差不多:


代码如下:

<!-- 生成apk文件到build目录下 -->
<!-- 其中${apk-version/name/market}用户多渠道打包,后面会讲到 -->
<echo>signing the unsigned apk to final product apk ... </echo>
<exec executable="jarsigner">
    <arg value="-keystore" />
    <arg value="../xxx.keystore" />
    <arg value="-storepass" />
    <arg value="xxx" />  <-- 验证密钥完整性的口令,创建时建立的 -->
    <arg value="-keypass" />
    <arg value="xxx" /> <-- 专用密钥的口令,就是key密码 -->
    <arg value="-signedjar" />
    <arg value="build/${apk-version}/${apk-name}_${apk-version}_${apk-market}.apk" /> <!-- 输出 -->
    <arg value="out/unsigned.apk" /> <!-- 未签名的apk -->
    <arg value="xxx" /> <!-- 别名,创建时建立的 -->
</exec>

至此,完整具有打包功能了,最后的build.xml为:


代码如下:

<project default="main" basedir=".">

<property name="apk-name" value="product" />
    <property name="apk-version" value="latest" />
    <property name="apk-market" value="dev" />

<property name="android-jar" value="/usr/lib/android-sdk/platforms/android-10/android.jar" />

<target name="init">
        <echo>start initing ... </echo>

<mkdir dir="out" />
        <delete>
            <fileset dir="out"></fileset>
        </delete>

<mkdir dir="gen" />
        <delete>
            <fileset dir="gen"></fileset>
        </delete>

<mkdir dir="bin/classes" />
        <delete>
            <fileset dir="bin/classes"></fileset>
        </delete>

<mkdir dir="build/${apk-version}" />

<echo>finish initing. </echo>
    </target>

<target name="main" depends="init">
        <echo>generating R.java for project to dir gen (using aapt) ... </echo>
        <exec executable="aapt">
            <arg value="package" />
            <arg value="-m" />
            <arg value="-J" />
            <arg value="gen" />
            <arg value="-M" />
            <arg value="AndroidManifest.xml" />
            <arg value="-S" />
            <arg value="res" />
            <arg value="-S" />
            <arg value="../baseworld/res" />
            <arg value="-I" />
            <arg value="${android-jar}" />
            <arg value="--auto-add-overlay" />
        </exec>

<echo>generating R.java for library to dir gen (using aapt) ... </echo>
        <exec executable="aapt">
            <arg value="package" />
            <arg value="-m" />
            <arg value="--non-constant-id" />
            <arg value="--auto-add-overlay" />
            <arg value="-J" />
            <arg value="gen" />
            <arg value="-M" />
            <arg value="../baseworld/AndroidManifest.xml" />
            <arg value="-S" />
            <arg value="res" />
            <arg value="-S" />
            <arg value="../baseworld/res" />
            <arg value="-I" />
            <arg value="${android-jar}" />
        </exec>

<path id="project.libs">
            <fileset dir="libs">
                <include name="*.jar" />
            </fileset>
        </path>
        <echo>compiling java files to class files (include R.java, library and the third-party jars) ... </echo>
        <javac destdir="bin/classes" bootclasspath="${android-jar}">
            <src path="../baseworld/src" />
            <src path="src" />
            <src path="gen" />
            <classpath refid="project.libs" />
        </javac>

<echo>packaging class files (include the third-party jars) to calsses.dex ... </echo>
        <exec executable="dx">
            <arg value="--dex" />
            <arg value="--output=out/classes.dex" />
            <arg value="bin/classes" />
            <arg value="libs" />
        </exec>

<echo>packaging resource (include res, assets, AndroidManifest.xml, etc.) to res.zip ... </echo>
        <exec executable="aapt">
            <arg value="package" />
            <arg value="-f" />
            <arg value="-M" />
            <arg value="AndroidManifest.xml" />
            <arg value="-S" />
            <arg value="res" />
            <arg value="-S" />
            <arg value="../baseworld/res" />
            <arg value="-A" />
            <arg value="assets" />
            <arg value="-I" />
            <arg value="${android-jar}" />
            <arg value="-F" />
            <arg value="out/res.zip" />
            <arg value="--auto-add-overlay" />
        </exec>

<echo>building unsigned.apk ... </echo>
        <exec executable="apkbuilder">
            <arg value="out/unsigned.apk" />
            <arg value="-u" />
            <arg value="-z" />
            <arg value="out/res.zip" />
            <arg value="-f" />
            <arg value="out/classes.dex" />
        </exec>

<echo>signing the unsigned apk to final product apk ... </echo>
        <exec executable="jarsigner">
            <arg value="-keystore" />
            <arg value="xxx.keystore" />
            <arg value="-storepass" />
            <arg value="xxxx" />
            <arg value="-keypass" />
            <arg value="xxx" />
            <arg value="-signedjar" />
            <arg value="build/${apk-version}/${apk-name}_${apk-version}_${apk-market}.apk" />
            <arg value="out/unsigned.apk" />
            <arg value="xxx" />
        </exec>

<echo>done.</echo>
    </target>
</project>

在工程目录下运行ant:


代码如下:

$ant
Buildfile: build.xml

init:
     [echo] start initing ... 
    [mkdir] Created dir: /home/openproject/world/floworld/build/latest
     [echo] finish initing.

main:
     [echo] generating R.java for project to dir gen (using aapt) ... 
     [echo] generating R.java for library to dir gen (using aapt) ... 
     [echo] compiling java files to class files (include R.java, library and the third-party jars) ... 
    [javac] Compiling 75 source files to /home/openproject/world/floworld/bin/classes
    [javac] 注意:某些输入文件使用或覆盖了已过时的 API。
    [javac] 注意:要了解详细信息,请使用 -Xlint:deprecation 重新编译。
     [echo] packaging class files (include the third-party jars) to calsses.dex ... 
     [echo] packaging resource (include res, assets, AndroidManifest.xml, etc.) to res.zip ... 
     [echo] building unsigned.apk ... 
     [exec] 
     [exec] THIS TOOL IS DEPRECATED. See --help for more information.
     [exec] 
     [echo] signing the unsigned apk to final product apk ... 
     [echo] done.

BUILD SUCCESSFUL
Total time: 28 seconds

成功的在build/latest目录下生成一个product_latest_dev.apk,这就是默认的生成的最终的APK,可以导入到手机上运行。

10. 多渠道打包
    目前主流的多渠道打包方法是在AndroidManifest.xml中的Application下添加一个渠道元数据节点。
    比如,我使用的是友盟统计,它配置AndroidManifest.XML添加下面代码:


代码如下:

<application ……>
    <meta-data android:value="Channel ID" android:name="UMENG_CHANNEL"/>
    <activity ……/>
</application>

通过修改不同的Channel ID值,标识不同的渠道,有米广告提供了一个不错的渠道列表:http://wiki.youmi.net/PromotionChannelIDs.
    实现多渠道自动打包,就是实现自动化过程中替换Channel ID,然后编译打包。
    这个替换需要用到正则表达式实现。
    ant中提供的replace方法,功能太简单了,replaceregrex又需要添加另外的jar包,而且我们后面我们实现ant传参需要写另外的linux shell脚本,所以我干脆使用我熟悉的sed-i命令来实现替换。
    替换命令:


代码如下:

#-i 表示直接修改文件
#$market是Channel ID, 后面会讲到,是来自循环一个数组
#\1,\3分别表示前面的第1,3个括号的内容,这样写很简洁
sed -i "s/\(android:value=\)\"\(.*\)\"\( android:name=\"UMENG_CHANNEL\"\)/\1\"$market\"\3/g" AndroidManifest.xml

渠道修改的问题解决了。
    还记得前面定义的${apk-version},${apk-name},${apk-market}吗?
    ant提供了额外的参数形式可以修改build.xml中定义的属性的值:ant -Dapk-version=1.0,则会修改${apk-version}值为1.0,而不是latest了,其他属性类似。
    所以,在工程下面这条命令会生成:


代码如下:

#结合前面讲打build.xml
#会在build/1.0/目录下生成floworld_1.0_appchina.apk
ant -Dapk-name=floworld -Dapk-version=1.0 -Dapk-market=appchina

命令问题通过ant的参数传值也解决了。
    现在需要的是批量生产N个市场的版本,既替换AndroidManifest.xml,又生成对应的apk文件,我结合上面说的亮点,写了一个shell脚本(位置:world/floworld/build.sh):


代码如下:

#定义市场列表,以空格分割
markets="dev appchina gfan"
#循环市场列表,分别传值给各个脚本
for market in $markets
do
    echo packaging floworld_1.0_$market.apk ...
    #替换AndroidManifest.xml中Channel值(针对友盟,其他同理)
    sed -i "s/\(android:value=\)\"\(.*\)\"\( android:name=\"UMENG_CHANNEL\"\)/\1\"$market\"\3/g" AndroidManifest.xml
    #编译对应的版本
    ant -Dapk-name=floworld -Dapk-version=1.0 -Dapk-market=$market
done

好的,在工程目录下执行build.sh:


代码如下:

# ./build.sh 
packaging floworld_1.0_dev.apk ...
Buildfile: build.xml
... ...
packaging floworld_1.0_appchina.apk ...
Buildfile: build.xml
... ...
packaging floworld_1.0_gfan.apk ...
Buildfile: build.xml
... ...

在build下生成了对应的apk文件:


代码如下:

build
├── 1.0
│   ├── floworld_1.0_appchina.apk
│   ├── floworld_1.0_dev.apk
│   └── floworld_1.0_gfan.apk
└── README.md

 成功生成!

11. 工程脚本的执行目录问题
    上面的脚本执行之后的确很cool,但是有一个问题,我必须在build.sh目录下执行,才能正确编译,这个和build.xml中定义的相对路径有关。
    我们必须在任何目录执行工程目录下的build.sh都不能出错,改进build.sh为如下:


代码如下:

#!/bin/bash
#添加如下两行简单的代码
#1. 获取build.sh文件所在的目录
#2. 进入该build.sh所在目录,这样执行起来就没有问题了
basedir=$(cd "$(dirname "$0")";pwd)
cd $basedir

markets="dev appchina gfan"
for market in $markets
do
    echo packaging floworld_1.0_$market.apk ...
    sed -i "s/\(android:value=\)\"\(.*\)\"\( android:name=\"UMENG_CHANNEL\"\)/\1\"$market\"\3/g" AndroidManifest.xml
    ant -Dapk-name=floworld -Dapk-version=1.0 -Dapk-market=$market
done

现在你在项目根目录下执行也没有问题:./floworld/build.sh,不会出现路径不对,找不到文件的错误了。

12. 建立整个项目的自动化编译脚本(位置:world/build.sh)
   单个工程的自动化打包没有问题了,但是一个项目下有N个工程,他们往往需要同步发布(或者daily build也需要同步编译),所以有必要建立一个项目级别的编译脚本:
   build.sh(项目根目录下,位置:/world/build.sh)
   最简单的傻瓜式的做法就是,遍历项目下的工程目录,如果包含工程编译的build.sh,则编译该工程.
   shell脚本如下:


代码如下:

#!/bin/bash
#确保进入项目跟目录
basedir=$(cd "$(dirname "$0")";pwd)
cd $basedir
#遍历项目下各工程目录
for file in ./*
do
if test -d $file
then
    #进入工程目录
    cd $basedir/$file
    #查找该工程目录下是否存在编译脚本build.sh
    if test -f build.sh
    then
        echo found build.sh in project $file.
        echo start building project $file ...
        ./build.sh
    fi
    #重要,退出工程目录到项目根目录下
    cd $basedir
fi
done

执行该脚本:


代码如下:

# ./build.sh
found build.sh in project ./floworld.
start building project ./floworld ...
packaging floworld_1.0_dev.apk ...
Buildfile: build.xml
...
...

found build.sh in project ./healthworld.
start building project ./healthworld ...
Buildfile: build.xml
...

成功自动寻找,并编译打包。

13. 其他细节
    为了尽量详细,我一再解说,但是还有一些细节未包括其中,如编译后清理clean目标,apk对齐优化,java代码混淆等,请参考其他资料,在此省略。
    另外,我反编译生成的apk,查看Androidmanifest.xml均正确对应,验证通过。

14. 小结
    自动化编译多渠道打包这个功能是Android产品发布的重要环节,能大大节省人力和出错的概率。

(0)

相关推荐

  • 怎么发布打包并发布自己的Android应用(APP)

    第一步,在Eclipse中选择需要打包的项目,然后右键--选择Export,会弹出一个打包的提示框,如下图所示. 按Next之后,会继续出现一个提示框,这里你可以选择自己需要打包的项目(默认是刚才选中的)如下图: 按Next之后,会弹出一个关于"Keystore"的提示,选择"Create new Keystore",并浏览.选择签名文件要保存的路径, (关于Keystore的原理.作用等这里暂时不细说,请大家发布前务必保存好该签名文件,非常重要的.) 如下图所示:

  • Android aapt自动打包工具详细介绍

    Android aapt自动打包工具 概念 在Android.mk中有LOCAL_AAPT_FLAGS配置项,在gradle中也有aaptOptions,那么aapt到底是干什么的呢? aapt即Android Asset Packaging Tool(Android 打包工具),在SDK的build-tools目录下.我们可以查 看,创建, 更新ZIP格式的文档附件(zip, jar, apk).也可将资源文件编译成二进制文件,尽管你可能没有直接使用过aapt工具,但是build script

  • Android开发apk反编译和二次打包教程

    作为Android开发者,工作中少不了要反编译别人的apk,当然主要目的还是为了学习到更多,取彼之长,补己之短.今天就来总结一下Android反编译和二次打包的一些知识.首先声明本文的目的是为了通过例子讲解反编译和二次打包的原理和方法,继而作为后续讲解防止二次打包和App安全的依据,并不是鼓励大家去重新打包别人的App,盗取他人劳动成果. 本文首先介绍几种Android反编译工具的使用,然后实现在不需要知道源代码的情况下,仅通过修改反编译得到的smali文件实现修改apk逻辑功能的目的. And

  • 在Android打包中区分测试和正式环境浅析

    前言 本文主要介绍了关于Android打包中区分测试和正式环境的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍: APK打包正式环境和测试环境注意 最近在项目打包中,遇到一个问题,每次打包都要区分正式发布包和测试版本的包,主要是修改一下配置 public static final boolean EXTERNAL_RELEASE = true; 当变量为true的时候,就是正式包,反之就是测试包.每次上线的时候我就提醒自己要小心,千万不能出错了,然而终于湿脚了,一个渠道打

  • ANDROID应用程序的混淆打包分享

    android应用程序的混淆打包1 . 在工程文件project.properties中加入下proguard.config=proguard.cfg , 如下所示:target=android-8 proguard.config=proguard.cfg Eclipse会通过此配置在工程目录生成proguard.cfg文件 2 . 生成keystore (如已有可直接利用) 按照下面的命令行 在D:\Program Files\Java\jdk1.6.0_07\bin>目录下,输入keytoo

  • Android笔记之:App自动化之使用Ant编译项目多渠道打包的使用详解

    随着工程越来越复杂,项目越来越多,以及平台的迁移(我最近就迁了2回),还有各大市场的发布,自动化编译android项目的需求越来越强烈,后面如果考虑做持续集成的话,会更加强烈.    经过不断的尝试,在ubuntu环境下,以花界为例,我将一步一步演示如何使用命令行,使用ant编译android项目,打包多渠道APK.    要点:    (1). 编译android的命令使用    (2). ant基本应用    (3). 多项目如何编译(包含android library)    (4). 如

  • Android几种多渠道打包的步骤详解

    1.什么是多渠道打包 在不同的应用市场可能有不同的统计需求,需要为每个应用市场发布一个安装包,这里就引出了Android的多渠道打包.在安装包中添加不同的标识,以此区分各个渠道,方便统计app在市场的各种. 2.几种打包方式 友盟 UMeng Android Studio自带 美团 Walle 3.开始使用 3.1 友盟UMeng 第一步:在AndroidManifest中添加 <meta-data android:name="UMENG_CHANNEL" android:val

  • Android多渠道打包神器ProductFlavor详解

    目录 一.什么是多渠道打包 1.多版本 2.多环境 3.多渠道 二.多渠道打包的方式(ProductFlavor&&多渠道打包插件) 1.ProductFlavor 1.1 如何是使用ProductFlavor 1.2 如何是使用ProductFlavor加载apk包 1.3 该如何获取不同渠道包的信息 1.4 使用ProductFlavor加载apk包的优缺点 2.多渠道打包插件 一.什么是多渠道打包 在不同的应用市场可能有不同的统计需求,需要为每个应用市场发布一个安装包,这里就引出了A

  • Android 7.0中新签名对多渠道打包的影响详解

    老签名多渠道打包原理 前言 由于Android7.0发布了新的签名机制,加强了签名的加固,导致在新的签名机制下无法通过美团式的方式再继续打多渠道包了.不过在说新的签名机制对打包方案的 影响和为什么会影响我们原有的打包机制之前,需要先简单理解下打包原理和签名在整个打包过程中的作用. Android打包流程 Android打包过程大致如图所示,整个流程就是将Java代码,资源文件以及第三方库整合成一个Apk文件,并对整合后的文件进行签名和优化对齐.整个过程可以简 单分为以下几个步骤: 资源预编译 为

  • Android笔记之:App应用之发布各广告平台版本的详解

    Android的广告平台是很多的,各市场对各平台的接受程度是不一样的,Android的开发者如果想集成广告基本要考虑下面两个问题:(1)集成什么广告,会赚钱?(2)集成什么广告,不会被市场拒绝?最终的结果往往是折中的.第一个问题是广告平台的判断问题,我没有发言权去评论,本文主要是针对第二个问题展开.解决方案就是打包应用的不同广告平台版本,本文接下来逐一展开相关话题. 1. 基础本文其实是针对<Android笔记之:App模块化及工程扩展的应用>和<Android笔记之:App自动化之使用

  • Android从网络中获得一张图片并显示在屏幕上的实例详解

    Android从网络中获得一张图片并显示在屏幕上的实例详解 看下实现效果图: 1:androidmanifest.xml的内容 <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="cn.capinftotech.image" an

  • Android Studio 下自动注释(自定义作者,类作用等)图文详解

    Eclipse 的自动注释相信大家都不会陌生,http://www.jb51.net/article/105094.htm,来到Android Studio之后我们会发现这个有用的功能竟然没有!(其实是被Android Studio隐藏了),鼓捣一番也就那么回事-.- 很简单,首先打开你的Android Studio  在工具栏点击如图小图标 然后在进入页面里搜索:File and Code Templates,如图 再如图 新建一个类试试 总结 以上所述是小编给大家介绍的Android Stu

  • 比ant更丰富Modal组件功能实现示例详解

    目录 有哪些比ant更丰富的功能 render部分 渲染黑色蒙层 渲染弹框主体 设置body overflow:hiiden 有哪些比ant更丰富的功能 普通的modal组件如下: 我们写的modal额外支持,后面没有蒙版,并且Modal框能够拖拽 还支持渲染在文档流里,上面的都是fixed布局,我们这个正常渲染到文档下面: render部分 <RenderDialog {...restState} visible={visible} prefixCls={prefixCls} header={

  • Android应用程序的编译流程及使用Ant编译项目的攻略

    Android 工程构建的持续集成,需要搭建一套编译和打包自动化流程,比如建立每日构建系统.自动生成发布文件等等.这些都需要我们对Android工程的编译和打包有一个比较深入的理解,例如知道它的每一步都做了什么,需要什么环境和工具,输入和输出是什么,等等. 首先,假定你的系统(Windows.Linux.Mac OS都行,本文默认使用Linux系统来举例子,但在 Windows中几乎没有什么差别)已经安装了JDK和Android SDK. 我们重点关心的是:     (1)这个过程的输入是什么?

  • android studio 3.0 gradle 打包脚本配置详解

    本文介绍了android studio 3.0 gradle 打包脚本配置,分享给大家,具体如下: 修改输出的名字 保存输出的文件路径 def fileArray = [] //遍历输出文件 android.applicationVariants.all { variant -> variant.outputs.all { output -> def outputFile = output.outputFile if (outputFile != null && outputF

随机推荐