现在已经有更好的方式去写NDK项目,请移步:
http://blog.csdn.net/b2259909/article/details/58591898
Android studio越来越成熟,所以需要将之前的 eslipce 项目变成 gradle 构建的项目。
这里说一下我的过程:我目前用的版本已经是Android studio 2.0,当导入没有带有 JNI 的普通项目时,As 运行得很好,直接智能帮你把一些文件放置好了。不管是不是有第三方的so 和 jar 都已经帮你放好了。直接编译就可以了。
如果是 之前的工程有 jni代码的,导入后会出现以下错误。下面说说我是怎么做的。
分两组情况:
1. 如果整个工程最后只是编译成了一个so文件。
1.1在project的gradle.properties(没有这个文件就自己建一个)里添加:
android.useDeprecatedNdk=true
1.2在project的gradle.properties里添加:(指定NDK目录)
ndk.dir=/Users/zhangbh/Library/Android/android-ndk-r10e
1.3在app中的build.gradle 的android 节点下指定编译后的so库名 ndk {moduleName "hello-jni" }
注意,这里还可以添加其他编译的项目,主要这里会影响 gradle 自动生成的Android.mk 文件,这个文件可以在 app/build/intermediates/ndk/ 下看到,这个mk文件不要去改它,改了也没用,会被gradle新生成的覆盖掉
1.4 按 【command + ;】打开Project Structure,检查Android NDK location是否正确
然后就可以直接编译了,编译生成的so库放置在 src/main/jniLibs下
2. 如果不想用gradle生成的Android.mk来编译你的工程,比如你的工程有多个mk文件,生成多个so库。这时上面的就适应了。最终我在网上找到了一种方法,那就是不让gradle去编译NDK,而是用gradle创建一个task,执行shell下的ndk-build,这种方法实质跟eslipce的工程一样的。怎么做呢?
2.1 上面1.1,1.2,1.4的动作照做
2.2 在app下的 build.gradle 中增加以下代码:
在android 节点下:
sourceSets.main.jni.srcDirs = []//指定需要编译成so的c源文件路径,这里屏蔽掉,也就是不让gradle自动生成mk文件去编译sourceSets.main.jniLibs.srcDirs = ['build/libs']//指定链接的so路径(可以不指定,默认是src/jniLibs),那么要想app成功运行,需要手动将编译成功的so库从 app/build/libs下拷贝到默认的目录2.3 在android 节点外添加task。
tasks.withType(JavaCompile) { compileTask -> compileTask.dependsOn ndkBuild } task ndkBuild(type: Exec, description: 'Compile JNI source via NDK') { println('executing ndkBuild') Properties properties = new Properties() properties.load(project.rootProject.file('local.properties').newDataInputStream()) def ndkDir = properties.getProperty('ndk.dir') println(ndkDir) commandLine "$ndkDir/ndk-build", 'NDK_PROJECT_PATH=build',//指定生成的obj和libs放置的目录 'APP_BUILD_SCRIPT=src/main/jni/Android.mk',//对应你自己的mk文件,下同 'NDK_APPLICATION_MK=src/main/jni/Application.mk' }
完工!
如果上面没有设置这句sourceSets.main.jniLibs.srcDirs = ['build/libs']
这里提供一个拷贝 build/libs下so 到 默认的so路径的task
task CopyToJniLibs(type: Copy, dependsOn: 'ndkBuild', description: 'copy the native libs to jniLibs') { from('build/libs') into 'src/main/jniLibs/' include '**/*.so' }
然后每次编译就会自动拷贝过去了,记得把前面的:
tasks.withType(JavaCompile) { compileTask -> compileTask.dependsOn ndkBuild }
改为tasks.withType(JavaCompile) { compileTask -> compileTask.dependsOn CopyToJniLibs }
另外就是如果要把一个模块的代码打成jar包:
只打包class的jar包,涉及UI的部分,导不出jar包,可能需要特殊方法。
可以参考这个链接:
http://www.open-open.com/lib/view/open1451444360917.html
http://www.cnblogs.com/wuya/p/android-studio-gradle-export-jar-assets.html