由于项目需要,需要脱离IDE来生成APK包,一开始我太天真,用纯bat去实现了一版,参见:http://www.oschina.net/code/snippet_170948_37095 ,但是bat的语法实在可怕,为了扩展的需要我又用Lua实现了一版,请戳:http://www.oschina.net/code/snippet_170948_38321 。
下面就说下基本步骤和一些值得注意的小坑:
一般来说,Android APK包的生成,利用IDE(Eclipse 或者 Android Studio)会比较方便,例如在Eclipse中可以将项目导出成签名或者非签名的APK包。想要实现自动化打包,就必须脱离IDE,自己去实现相关的步骤,不过幸好有一些自动化构建工具可以减轻我们的工作。
通常来说java的一些项目构建工具,都可以用来构建APK包,例如ANT,MAVEN。ANT相对来说简单一些,我们选择的就是它。如下图,一个典型的APK包,包括assets,lib,META-INF,res,AndroidManifest.xml,class.dex等文件,其中assets是资源文件夹和res的区别是,res是无层次概念的,res中一般保存的是多媒体资源,assets一般保存lua,ccbi等文件。lib是编译后的jni库,就是.so文件。META是和签名相关的文件夹,用来MD5校验等。class.dex是经过编译后的java字节码文件,所有的java文件都将编译成一个字节码文件。
APK自动化打包脚本就是分别生成以上文件夹,并生成zip包的过程。
有一处需要说明的是,构建so文件,可以用cygwin,也可以使用NDK,NDK版本8以上是可以独立编译出so文件的。cygwin环境配置太复杂,所以直接选用NDK即可,NDK是区分32位和64位,需要注意NDK不同位宽并不兼容。
使用Eclipse构建APK包的时候,需要将cocos2dx引擎下cocos2dx\platform\android\java\src目录中的org的源文件,拷贝到proj.android下的src文件中,使用脚本构建APK包的时候是通过mk文件指定库目录的,所以无需拷贝,否则会报重复定义的错。
首先,在proj.android文件夹下的Android.mk文件,先指定编译NDK所需的目录,在文件中添加如下两行:
$(call import-add-path, $(LOCAL_PATH)/../../../..)
$(call import-add-path, $(LOCAL_PATH)/../../../../cocos2dx/platform/third_party/android/prebuilt)
其次,是生成assets文件夹,每一次重新构建APK时,先删除旧的assets文件夹,之后再用luajit对lua文件生成相应字节码文件,最后将lua字节码文件加密,不需要加密的文件,只需要做拷贝即可,需要注意的是我在lua中编写测试文件夹是否存在函数的时候,发现win7和xp略有不同,代码如下:
os.execute(string.format('pushd "%s">nul 2>nul && popd', dir))
在win7 下上面的函数式返回true(文件夹存在),nil(文件夹不存在),而在xp下,是返回1,0。
同时,最好删除旧有的APK包,在bin目录下,名为xxxx-release.apk,理论上APK生成方式是覆盖的,新的覆盖旧的,不过有时候会有bug,新的包覆盖不了,所以最好删除旧的APK包。
使用luajit的时候也需要注意,必须要在同目录下加上luajit所依赖的lua51.dll和jit文件夹,编写luajit函数的时候有两点需要注意:
1,我是通过os.excute来执行luajit的,所以必须要指定luajit运行的环境目录,单纯的执行luajit.exe会报jit文件夹不存在,所以应该通过pushd popd来指定环境文件夹,代码如下:
function jit_file(toolpath, from , to)
check_mk_filepath(to)
local cmd1 = "pushd "..toolpath
local cmd2 = toolpath.."\\luajit.exe -bg " .. from .. " " .. to
local cmd3 = "popd"
local cmd = cmd1.." & "..cmd2.." & "..cmd3
local res = run_one_cmd(cmd)
end
必须要用“&”符号来将3条指令,连接成一条指令去运行,否则还是不行,因为lua中使用os.excute执行一条指令时,是相当于一个trunk来执行,每个trunk是独立的,拥有自己的函数环境。
2。luajit 使用-bg指令编译lua文件,出错时可以定位具体行号。
然后,是使用NDK编译so库的过程,需要在NDK编译的参数中使用module-path来指定NDK的路径,通过如下指令即可完成:
ndk-build -C "D:\engine\projects\XXXX\proj.android" "NDK_MODULE_PATH=D:\engine;D:\engine\cocos2dx\platform\third_party\android\prebuilt"
之后,使用android sdk的tools下的android update去更新工程目录和引擎目录,命令:
android update project -p "D:\engine\projects\XXXX\proj.android
会生成proguard-project.txt和build.xml文件,这两个文件无需任何改动,并修改project.properties 中的参数,需要注意的是,你的sdk的版本是多少,在project.properties中的#project target参数就需要设置成多少,否则会报 missing target的错。
update指令会更新该文件中的库目录路径,如下:
android.library.reference.1=../../../cocos2dx/platform/android/java
同时需要,需要使用Android update去更新库目录中的project.properties文件,命令如下:
android update lib-project -p cocos2dx/platform/android/java
最后,是使用ANT去生成APK包,这一步其实是ANT调用Android sdk的工具AAPT去完成的,命令很简单如下:
ant release 或者 ant debug,release是生成APK包,debug是生成不签名的APK包(去掉一些优化),
在ant.properties指定签名所需的密钥文件,格式如下:
key.store=”密钥文件名“(最好同目录下)
key.alias=”签名作者“
key.store.password=”发布密钥“
key.alias.password=”签名密钥“
AAPT的作用如下图所示:
在新的SDK中传统的APKbuilder也已经被AAPT取代了。
打包成功后,可以在bin目录下找到生成的APK包。
常见错误:
1.如果运行ANT 出现如下错误:
BUILD FAILED
D:\android-sdk-windows\tools\ant\build.xml:653:The following error occurred while executing this line:
D:\android-sdk-windows\tools\ant\build.xml:698:null returned: 1
解决方法是清楚bin目录下的所有文件,如果是在eclipse里面clean一下当前项目即可
2.假设你将环境拷贝到别的机器上,使用别的机器进行NDK编译时,务必先删除obj目录,其中有大量缓冲文件,会导致路径未定义的错误。
3.如果ANT出现如下错误
D:\android-sdk-windows\tools\ant\build.xml: 950
D:\android-sdk-windows\tools\ant\build.xml: 932
这是由于你的资源文件中出现了中文命名的文件,AAPT是没有办法识别的, IOS是可以识别的,但是AAPT不行,所以最好不要使用中文命名任何文件或者文件夹。