Android Studio NDK JNI 实践

环境要求

1 . Android Studio2.2 以上

2.2 以上版本的Android Studio会自动下载ndk-bundle 并配置好ndk路径

具体步骤

1 . 新建一个项目名字随意取名,我这边叫做NDKTest 一路next 直到finish 创建完成。
image
2 . 在项目工程目录的src/main建立jni目录,如果有就不要在新建了。
3 . 新建Android.mk文件 内容如下

LOCAL_PATH       :=  $(call my-dir)
# 设置工作目录,而my-dir则会返回Android.mk文件所在的目录

include              $(CLEAR_VARS)
# 清除几乎所有以LOCAL——PATH开头的变量(不包括LOCAL_PATH)

LOCAL_MODULE     :=  hello_jni
# 设置模块的名称,即编译出来.so文件名
# 注,要和上述步骤中build.gradle中NDK节点设置的名字相同

LOCAL_SRC_FILES  :=  test.cpp
# 指定参与模块编译的C/C++源文件名

include              $(BUILD_SHARED_LIBRARY)
# 指定生成的静态库或者共享库在运行时依赖的共享库模块列表。

4 . 新建Application.mk文件,内容如下:

APP_ABI := rmeabi x86 mips
# 最常用的APP_ABI字段:指定需要基于哪些CPU平台的.so文件
# 常见的平台有armeabi x86 mips,其中移动设备主要是armeabi平台
# 默认情况下,Android平台会生成所有平台的.so文件,即同APP_ABI := armeabi x86 mips
# 指定CPU平台类型后,就只会生成该平台的.so文件,即上述语句只会生成armeabi平台的.so文件

5 . 新建test.cpp文件 内容如下

# include <jni.h>
# include <stdio.h>

extern "C"
{

    JNIEXPORT jstring JNICALL Java_com_lzc_ndktest_MainActivity_getFromJNI(JNIEnv *env, jobject obj ){
       // 参数说明
       // 1. JNIEnv:代表了VM里面的环境,本地的代码可以通过该参数与Java代码进行操作
       // 2. obj:定义JNI方法的类的一个本地引用(this)
    return env -> NewStringUTF("Hello i am from JNI!");
    // 上述代码是返回一个String类型的"Hello i am from JNI!"字符串
    }
}

Java_com_lzc_ndktest_MainActivity_getFromJNI 命名规则

  • Java是必写后接_
  • 中间的com_lzc_ndktest是将应用包名com.lzc.ndktest的.替换成即可后接
  • MainActivity是加载动态库使用的类文件
  • getFromJNI 是jni方法的名称
  • 如果包名中存在_ 则对应的替换成_1

最后三个文件位置如下图所示:

image

6 . 定位到jni目录下 执行ndk-build,完成后在工程目录的main文件夹下生成libs和obj文件夹,如下图:
image
将main目录下的libs文件夹里面的文件复制到工程目录下的libs中。
image
7. 在app的build.gradle文件中添加如下代码:

android{
    ....
 sourceSets {
        main {
            jniLibs.srcDirs = ['libs']
//            jniLibs.srcDir 'src/main/libs'
//            java.srcDirs += 'src/main/jni/src'
//            assets.srcDirs += 'src/main/jni/assets'
        }
    }
....
}

8 . 在MainActivity中添加如下代码:

//加载动态库 不用写前面的lib 
static {
        System.loadLibrary("hello_jni");
    }
    // 步骤2:定义在JNI中实现的方法
    public native String getFromJNI();

9 . 调用事例,如下所示:

  @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        TextView textView= (TextView) findViewById(R.id.text_hello_jni);
        textView.setText(getFromJNI());

    }

10 . 运行结果图

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章