android 打包流程

首先,android 程序大致分为资源和代码

资源就是assets和res,assets里可以放文件,在打包成akp的过程中,此目录下的文件会原封不动的封入包里。AssetManager am= getAssets(); InputStream is = assset.open("filename");

res目录下有很多种资源:

drawable:这类资源以XML或者Bitmap文件保存在res/drawable目录下,用来描述可绘制对象。例如,我们可以在里面放置一些图片(.png, .9.png, .jpg, .gif),来作为程序界面视图的背景图。注意,保存在这个目录中的Bitmap文件在打包的过程中,可能会被优化的。例如,一个不需要多于256色的真彩色PNG文件可能会被转换成一个只有8位调色板的PNG面板,这样就可以无损地压缩图片,以减少图片所占用的内存资源。

animator:这类资源以XML文件保存在res/animator目录下,用来描述属性动画。属性动画通过改变对象的属性来实现动画效果,例如,通过不断地修改对象的坐标值来实现对象移动动画,又如,通过不断地修改对象的Alpha通道值来实现对象的渐变效果。

anim:这类资源以XML文件保存在res/anim目录下,用来描述补间动画。补间动画和属性动画不同,它不是通过修改对象的属性来实现,而是在对象的原来形状或者位置的基础上实现一个变换来得到的,例如,对对象施加一个旋转变换,就可以获得一个旋转动画,又如,对对象实施一个缩放变换,就可以获得一个缩放动画。从数学上来讲,就是在对象的原来形状或者位置的基础上施加一个变换矩阵来实现动画效果。注意,在动画的执行过程中,对象的属性是始终保持不变的,我们看到的只不过是它的一个变形副本。

color:这类资源以XML文件保存在res/color目录下,用描述对象颜色状态选择子。例如,我们可以定义一个选择子,规定一个对象在不同状态下显示不同的颜色。对象的状态可以划分为pressed、focused、selected、checkable、checked、enabled和window_focused等7种。

layout:这类资源以XML文件保存在res/layout目录下,用来描述应用程序界面布局。

menu:这类资源以XML文件保存在res/menu目录下,用来描述应用程序菜单,例如,Options Menu、Context Menu和Sub Menu。

raw:这类资源以任意格式的文件保存在res/raw目录下,它们和assets类资源一样,都是原装不动地打包在apk文件中的,不过它们会被赋予资源ID,这样我们就可以在程序中通过ID来访问它们。例如,假设在res/raw目录下有一个名称为filename的文件,并且它在编译的过程,被赋予的资源ID为R.raw.filename,那么就可以使用以下代码来访问它:Resources res = getResources();  InputStream is = res .openRawResource(R.raw.filename);  

values:这类资源以XML文件保存在res/values目录下,用来描述一些简单值,例如,数组、颜色、尺寸、字符串和样式值等,一般来说,这六种不同的值分别保存在名称为arrays.xml、colors.xml、dimens.xml、strings.xml和styles.xml文件中。

xml:这类资源以XML文件保存在res/xml目录下,一般就是用来描述应用程序的配置信息。

这些资源是被aapt(Android Asset Package Tool)打包工具打包的。

res/animator、res/anim、res/color、res/drawable(非Bitmap文件,即非.png、.9.png、.jpg、.gif文件)、res/layout、res/menu、res/values和res/xml的资源文件均会从文本格式的XML文件编译成二进制格式的XML文件,assets和res/raw原封不动打包进去。除了assets资源之外,其它的资源都会被赋予一个资源ID。

打包工具负责编译和打包资源,编译完成之后,会生成一个resources.arsc文件和一个R.java,前者保存的是一个资源索引表,后者定义了各个资源ID常量。应用程序配置文件AndroidManifest.xml同样会被编译成二进制的XML文件,然后再打包到APK里面去。应用程序在运行时通过AssetManager来访问资源,或通过资源ID来访问,或通过文件名来访问。

 

代码:则是java->class->dex

 

总结打包流程

1.打包资源文件,生成R.java文件。

打包资源工具aapt位于andorid-sdk\platform-tools目录下,该工具的源码在android系统源码的frameworks\base\tools\aapt目录下,生成的过程主要是调用了aapt源码目录下Resource.cpp文件中的buildResources()函数,该函数首先检查AndroidManifest.xml的合法性,然后对res目录下的资源子目录进行处理,处理的函数为makeFileResources(),处理的内容包括资源文件名的合法性,向资源表table添加条目等,处理完后调用complieResourceFlie()函数编译res与asserts目录下的资源并生成resources.arsc文件,compileResourceFile()函数位于aapt源码目录的ResourceTable.cpp文件中,该甘薯最后会调用parseAndAddEntry()函数生成R.java文件,完成资源编译后,接下来调用compileXmlFile()函数对res目录的子目录下的xml文件分别进行编译,这样处理过得xml文件就简单的被“加密”过了,最后将所有的资源与编译生成的resources.arsc文件以及“加密”过的AndroidManifest.xml文件打包压缩成resources.ap_文件(使用ant工具命令行编译则会生成与buiild.xml中“project name”指定的属性同名的ap_文件)。

2.处理aidl文件,生成相应的java文件。

对于没有使用到aidl的Android工程,这一步可以跳过。这一步使用到的工具为aidl,位于android-sdk\platform-tools目录下,aidl工具解析接口定义文件(aidl为android interface definition language的首字母缩写,即android接口描述语言)并生成相应的java代码供程序调用,源码位于Android源码的frameworks\base\tools\aidl目录下。

3.编译工程源代码,生成相应的class文件。

这一步调用javac编译工程src目录下所有的java源文件,生成的class文件位于工程bin\classes目录下,假使编译工程源码时程序是基于androidsdk开发的,实际开发过程中,也有可能会使用android NDK来编译native代码,因此,如果可能的话,这一步还需要使用android NDK编译C/C++代码,当然,编译C/C++代码的步骤也可以提前到第一步或者第二步。

4.根据proguard文件,混淆.class文件

发布包需要,会把所有依赖的jar包放在一起处理,行程混淆后的单一jar包

5.转换所有的class文件,生成class.dex文件。

Android系统的Dalvik虚拟机的可执行文件为DEX格式,程序运行所需的class.dex就是在这一步生成的,使用到的工具为dx,它位于android-sdk\platform-tools目录下,dx工具主要的工作是将java字节码转换为Dalvik字节码、压缩常量池、消除冗余信息等。

6.打包生成apk文件。

打包的工具为apkbuilder,它位于android-sdk\tools目录下,apkbuilder为一个脚本文件,实际调用的是android-sdk\tools\lib\sdklib.jar文件中的com.android.sdklib.build.apkbuilderMain类。它的实现代码位于android系统源码的sdk\sdkmanager\libs\sdklib\src\com\android\sdklib\build\akpbuilderMain.java文件,代码构建了一个apkbuilder类,然后以包含resources.arec的文件为基础生成apk文件,这个文件一般为ap_结尾的文件,接着调用addSourceFolder()函数添加的资源,addSourceFolder()会调用processFileForResource()函数往apk文件中添加资源,处理的内容包括res目录与assets目录中的文件,添加完整源后调用addResourcesFromJar()函数往apk文件中写入依赖库,接着调用addNativeLibraries()函数添加工程libs目录下的Native库(通过androidDNK编译生成的so或bin文件),最后条用sealApk()关闭apk文件。

7.对apk文件进行签名。

两种签名情况:一种是在调试程序时候进行签名,使用eclipse开发编译调试程序时候就会自己使用debug.keystore进行签名。

另一种是打包发布时对程序进行签名:1,使用jdk中提供的jarsigner工具签名

2,使用android源码中提供的signapk工具,它的代码位于android系统源码的build\tools\signapk目录下。

8.对签名后的apk文件进行对对齐处理。

使用的工具为zipalign,它位于android-sdk\tools目录,源码位于android系统源码的build\tools\zipalign,它的主要工作是将apk包进行对齐处理,使apk包中的所有资源文件距离文件起始偏移为4字节整数倍,这样通过内存映射访问Apk文件时的速度会更快,验证apk文件是否对齐过的工作由ZipAlign.cpp文件的verify()函数完成,处理对齐的工作则由process()函数完成。

 

 

批量打包:

#!/bin/bash
NAME=$1
QUDAO=$2
VER=$3
IGNORE_LIST=$4
if [ $# -ne 4 ]; then
echo "usage: sh build.sh name qudao version ignore_p_list"
exit 0
fi
rm -rf apks/
mkdir apks/
tag1=s/14584/
tag2=s/****/
tag3=/g
rm -rf $NAME
apktool d $NAME.apk
cp $NAME/AndroidManifest.xml template.xml
cat $QUDAO | while read line
do
echo $line
arr=(${line//-/ })
num=${#arr[@]}
first=`echo ${arr[3]} | grep "true" | wc -l`

ignore=`echo $IGNORE_LIST | grep ${arr[1]} | wc -l`
if [ $ignore = 1 ] ; then
echo "ignore ${arr[1]} ${arr[2]}"
continue
fi

if [ $num = 4 ] && [ $first = 1 ] ; then
echo "first publish"
cp ./$NAME/res/drawable-hdpi/splash.jpg ./hdpi.jpg
cp ./$NAME/res/drawable-hdpi-854x480/splash.jpg ./h854.jpg
cp ./$NAME/res/drawable-xhdpi/splash.jpg ./xhdpi.jpg
cp ./$NAME/res/drawable-xxhdpi/splash.jpg ./xxhdpi.jpg
#需要拷贝首发渠道
rm -f ./$NAME/res/drawable-hdpi/splash.jpg
rm -f ./$NAME/res/drawable-hdpi-854x480/splash.jpg
rm -f ./$NAME/res/drawable-xhdpi/splash.jpg
rm -f ./$NAME/res/drawable-xxhdpi/splash.jpg
cp ./partners/${arr[0]}/res/drawable-hdpi/splash.jpg ./$NAME/res/drawable-hdpi/s
plash.jpg
cp ./partners/${arr[0]}/res/drawable-hdpi-854x480/splash.jpg ./$NAME/res/drawabl
e-hdpi-854x480/splash.jpg
cp ./partners/${arr[0]}/res/drawable-xhdpi/splash.jpg ./$NAME/res/drawable-xhdpi
/splash.jpg
cp ./partners/${arr[0]}/res/drawable-xxhdpi/splash.jpg ./$NAME/res/drawable-xxhd
pi/splash.jpg
fi

# 进行替换并且打包
pwd
rm ./$NAME/AndroidManifest.xml
sed -e "$tag1${arr[1]}$tag3" template.xml >> ./$NAME/AndroidManifest.xml
cp ./$NAME/AndroidManifest.xml .
sleep 1
rm ./$NAME/AndroidManifest.xml
sed -e "$tag2${arr[2]}$tag3" AndroidManifest.xml >> ./$NAME/AndroidManifest.xml

cd $NAME/
rm -rf dist/
rm -rf build/
apktool b
cd dist/

cp ../../xxxxxx.keystore .
cp ../../run.sh .
sh run.sh $NAME
# rm -rf ../../apks/p-${arr[1]}
# mkdir ../../apks/p-${arr[1]}
# mv ./tmp/$NAME-release.apk ../../apks/p-${arr[1]}/xxxxxx.apk
mv ./tmp/$NAME-release.apk ../../apks/xxxxxx-${arr[0]}-p${arr[1]}-$VER-release.ap
k

cd ../../

if [ $num = 4 ] && [ $first = 1 ] ; then
rm -f ./$NAME/res/drawable-hdpi/splash.jpg
rm -f ./$NAME/res/drawable-hdpi-854x480/splash.jpg
rm -f ./$NAME/res/drawable-xhdpi/splash.jpg
rm -f ./$NAME/res/drawable-xxhdpi/splash.jpg
cp ./hdpi.jpg ./$NAME/res/drawable-hdpi/splash.jpg
cp ./h854.jpg ./$NAME/res/drawable-hdpi-854x480/splash.jpg
cp ./xhdpi.jpg ./$NAME/res/drawable-xhdpi/splash.jpg
cp ./xxhdpi.jpg ./$NAME/res/drawable-xxhdpi/splash.jpg
#需要拷贝首发渠道
fi
done
rm -rf $NAME
rm -f *.xml
rm -f *.jpg

 

 

 

#!/bin/bash
NAME=$1

if [ $# -eq 0 ]; then
echo "usage: sh run.sh name"
exit 0
fi
rm -r tmp
mkdir tmp
cd tmp
unzip ../$NAME.apk
rm -rfv META-INF
zip -r -n .gson:.properties:.gif.txt:.wav:.WAV:.so:.ogg:.mp3:.mid $NAME.apk *
jarsigner -sigalg MD5withRSA -digestalg SHA1 -keystore ../xxxxxx.keystore -signed
jar $NAME-signed.apk $NAME.apk xxxxxx -storepass xxxxxx520
zipalign -v 4 $NAME-signed.apk $NAME-release.apk

 

posted @ 2015-01-15 19:18  saki_god  阅读(2558)  评论(0编辑  收藏  举报