用cmake构建JNI
step1、用Android Studio创建一个Android工程

最终的工程结构如下:

这个工程结构与使用ndk-build构建的工程结构不一样。 用ndk-build构建的工程结构中的文件夹叫做jni,而这里叫做cpp, 并且还有一个CMake的配置文件CMakeLists.txt, 而ndk-build构建实际上使用的是gmake, 配置文件是Android.mkApplication.mk

注意:CMake是比gmake更高级的构建系统。CMake的作用是智能的生成各种构建系统的配置文件,当然包括gmake的配置文件Makefile。 也就是说,从分层结构上来说,CMake更靠近开发者。 我们可以类比网络的分层模型,假如CMake等于HTTP协议;那么gmake就是IP协议。

step2、创建一个Java类,包含JNI信息
package com.fpliu.jnitest;

public class XX {

    static {
        System.loadLibrary("xx");
    }

    public native String getText();
}

这里面特别注意:加载动态库的方式,通常是在Java类的静态代码块中,因为类加载器在加载一个类的时候, 类的静态成员和静态代码块最先执行,然后才会调用构造方法进行构造实例,之后,那些native方法才能正确执行。 当然,你也可以在其他地方加载,只是需要进行判断操作。

native修饰的方法就是要使用C/C++实现的方法,所以,它只是声明,没有方法体。

native修饰的方法也可以被其他修饰符所修饰,比如static

step3、通过javah命令生成头文件

1、切换到app/src/main/java目录:

cd ~/JNITest/app/src/main/java

2、使用javah命令生成头文件

javah -jni com.fpliu.jnitest.XX

这样就在app/src/main/java目录中生成了头文件com.fpliu.jnitest.XX.h,文件内容如下:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include 
/* Header for class com_fpliu_jnitest_XX */

#ifndef _Included_com_fpliu_jnitest_XX
#define _Included_com_fpliu_jnitest_XX
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_fpliu_jnitest_XX
 * Method:    getText
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_fpliu_jnitest_XX_getText
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif
step4、在app/src/main/cpp目录中实现

1、把com.fpliu.jnitest.XX.h剪切到app/src/main/cpp目录中:

mv java/com.fpliu.jnitest.XX.h cpp/

2、编写实现文件native-lib.cpp,内容如下:

#include "com_fpliu_jnitest_XX.h"

JNIEXPORT jstring JNICALL Java_com_fpliu_jnitest_XX_getText (JNIEnv *env, jobject obj) {
    return env->NewStringUTF("Hello NDK !");
}

这里使用C++了, 因为AndroidStudio已经自动帮助你选择了,我们就不自己折腾了,毕竟,C++语言比C更安全,而且开发效率更高! 但是,如果你追求极致体验,并且算法的功力足够好的话,C还是首选, 毕竟,它的执行效率是最好的。

step5、构建

使用CMake构建的工程,在build.gradle中的配置也不一样。

android {
    ...
    defaultConfig {
        ...
        externalNativeBuild {
            cmake {
                cppFlags ""
            }
        }
    }

    externalNativeBuild {
        cmake {
            path "CMakeLists.txt"
        }
    }
}

直接运行工程,看效果吧!

AndroidStudio创建的工程,自动支持了JNI开发, 它默认使用C++语言实现, 使用CMake构建,让gradle支持了基本的一些配置, 使得我们用AndroidStudio开发JNI也是比较省事的, 这是主流方向。当然,你喜欢用命令行的方式,不用AndroidStudio帮你做这些事情也是可以的。