从eclipse下NDK的Library项目,最近想要迁移到Android studio中来,却怎么也编译不出so文件,折腾好久,才发现,Android studio并不是按照jni文件夹下的mk文件来编译ndk项目,而是由gradle脚本生成一个临时的Android.mk文件,路径是
/build/intermediates/ndk/release/Android.mk
网上的教程大多数是在将如何从头建立一个ndk工程,基本不适合我这样的情况:依赖其他目录下大量的静态文件来编译的lib工程项目。
最终搜索一下,“Android studio 使用mk”,从一篇外文找到答案:
Using custom Android.mk with Gradle/Android Studio
将主要步骤翻译一下:
首先要禁止gradle默认的ndk编译过程,在build.gradle文件中,添加如下代码:
android { sourceSets.main.jni.srcDirs = [] }//告知gradle,没有jni代码
2.定义编译过程:
tasks.withType(Compile) {
compileTask -> compileTask.dependsOn ndkLibsToJar
}
这里定义编译过程依赖于 ndkLibsToJar;下面是实现ndkLibsToJar编译任务:
task ndkLibsToJar(type: Zip, dependsOn: 'ndkBuild', description: 'Create a JAR of the native libs') {
destinationDir new File(buildDir, 'libs')
baseName 'ndk-libs'
extension 'jar'
from(new File(buildDir, 'libs')) { include '**/*.so' }
into 'lib/'}
这个任务,是将java代码编译成jar包,放到src/main/lib下
3.定义任务ndkBuild,来编译ndk生成so文件:
task ndkBuild(type:Exec,description:'生成so文件'){
commandLine "$ndkDir/ndk-build",
'NDK_PROJECT_PATH=build',
'APP_BUILD_SCRIPT=src/main/jni/Android.mk'
}
到这里 就基本完成了。剩下的是需要调整一下生成文件的路径
但是目前这个还是有点问题,没有编译出jar包来,只有so文件了,根源还是在于我不会gradle的脚本,以后再试。
2015-12-24更新:
之所以没有打出jar包来,果真是我理解不到位。在更正之前,先声明一个重要的点:groovy是兼容java语法的。所以我可以用大java来写这个脚本——因为我不知道groovy怎么写啊。。
打包成jar的操作代码没有成功主要是因为我的build路径下没有libs文件夹,现在更新如下:
task ndkLibsToJar(type:Zip,dependsOn:'ndkBuild',description:'创建jar包'){
File dest=new File(buildDir,'libs')
if(!dest.exists()){ dest.mkdirs();}//如果libs文件夹不存在,则创建,和java一样对不对
destinationDir dest
// println("编译jar包"+buildDir)
baseName 'NAndroidSDK'
extension 'jar'
from(new File(buildDir,'intermediates/classes/release/'))
into 'com/' //into这个的意思不是打包到某个文件,而是被压缩的jar文件里的顶级目录
}
这样就可以在build/libs下找到jar包了。
后续问题是jar包里有buildConfig.class 这个和我们平时的jar是不一样的,还得再找找。
2015-12-24再次更新:
上次更新说到打出来的jar包里有BuildConfig.class文件,那么现在直接在打包的时候,将其删除就行:
task ndkLibsToJar(type: Zip, dependsOn: 'ndkBuild', description: '创建jar包') {
File classFolder=new File(buildDir, 'intermediates/classes/release/aa/bb/sdk/')//这个路径上加包名
File[] fs= classFolder.listFiles(new FileFilter() {
@Override
boolean accept(File pathname) {
return pathname.isFile();
}
})
delete(fs)
File dest = new File(buildDir, 'libs')
if (!dest.exists()) {
dest.mkdirs();
}//如果libs文件夹不存在,则创建,和java一样对不对
destinationDir dest
// println("编译jar包"+buildDir)
baseName 'NewMapAndroidSDK'
extension 'jar'
from(new File(buildDir, 'intermediates/classes/release/'))
into '/' //into这个的意思不是打包到某个文件,而是被压缩的jar文件里的顶级目录
}
tasks.withType(JavaCompile) {
compileTask -> compileTask.dependsOn ndkLibsToJar
}
}