Android Stuido Ndk-Jni 开发(一):创建简单的JniDemo

Java Native Interface(JNI)即java本地接口,它允许Java代码和其他编程语言(主要是C/C++)的代码进行交互。native实现的代码的效率可以比java高,有一些对运行效率要求比较高的场合需要用到Jni。有时候需要调用C/C++编写的代码,也需要用到Jni。所以Jni开发在android开发里面有特殊的作用。本文就从创建一个简单的JniDemo讲起。

本文的源码请前往Github https://github.com/dragonjiang/HelloJni.git

环境配置

  • 下载ndk,墙内官网访问不了,可以度娘,现在最新的是
    android-ndk-r10e-windows-x86_64.exe

  • 解压,一般是解压到与SDK同级的目录下:

  • 设置Windows环境变量

然后在Path里面添加%Android_NDK_HOME%

新建工程

1. 打开android studio,新建工程

选择新建一个Empty Actity

2. 新建NativeHelper类,声明一个native方法:

声明代码如下:

 public class NativeHelper {
     public native String getStringFromJni();
 }

3. 执行Build->Make Project,目的是生成class文件###

打开工程目录HelloJni\app\build\intermediates\classes\debug\com\dj\jni\hellojni\NativeHelper.class 可以看到生成了NativeHelper.class文件:

4. 根据class文件生成对应的c语言头文件

打开android stuido 的 terminal,执行命令cd app/src/main进入mian目录,目的是在mian目录下生成jni文件夹。

然后用javah生成c头文件:

javah -d jni -classpath D:\ANDROID_DEVELOP_ENVIRNMONT\SDK\platforms\android-21\android.jar;..\..\build\intermediates\classes\debug com.dj.jni.hellojn
i.NativeHelper

命令格式是:

javah -d (jni文件夹名) -classpath (sdk路径);(class路径) (class完整的文件名,包括包名)

然后再看main目录下会多出jni文件夹,里面已经自动生成了一个头文件com_dj_jni_hellojni_NativeHelper.h
文件内容如下:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_dj_jni_hellojni_NativeHelper */

#ifndef _Included_com_dj_jni_hellojni_NativeHelper
#define _Included_com_dj_jni_hellojni_NativeHelper
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_dj_jni_hellojni_NativeHelper
 * Method:    getStringFromJni
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_dj_jni_hellojni_NativeHelper_getStringFromJni
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

5. 新建.c文件

在jni文件下新建.c文件,当然新建.cpp文件也是可以的啦,就看大家习惯使用c还是c++

添加内容如下:

#include <jni.h>

/*
 * Class:     com_dj_jni_hellojni_NativeHelper
 * Method:    getStringFromJni
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_dj_jni_hellojni_NativeHelper_getStringFromJni
        (JNIEnv *env, jobject obj){

    return (*env)->NewStringUTF(env,"Hello from JNI !");
}

6. 配置ndk

执行Build->Clean Project, 再执行Build->Make Project,期间可能会提示错误:

我们根据提示在gradle.properties文件中添加以下内容:

android.useDeprecatedNdk=true

打开File->Project Structure,选择ndk的路径

在app目录下的build.gradle中设置要生成的so库文件名,在defaultConfig这项里面添加:

        ndk {
            moduleName "HelloJni" //编译后会生成HelloJni.so
        }

在NativeHelper类中添加对so库的加载:

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

android动态加载库文件有两个方法,System.load 和 System.loadLibrary
System.load 参数必须为库文件的绝对路径
System.loadLibrary 参数为库文件名,不包含库文件的扩展名。
注意加载的库名字要与build.gradle中配置的库名字一致。

NativeHelper类的完整代码如下:

7. 编译jni, 调用native方法

再执行Build->Clean Project,
执行Build->Make Project。

打开工程目录HelloJni\app\build\intermediates\ndk\debug\lib 可以看到生成了各个平台的so文件:

注意: 每次修改jni文件夹下的.c文件或者.h文件都要重新执行Build->Make Project,重新生成so文件。

打开MainActivity,调用native方法:

运行结果:

推薦閱讀更多精彩內容