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包,可能需要特殊方法。