1.先给Android Studio配置NDK,可以直接在Tools---SDK Manager中,
然后可以在File---Project Structure中配置好ndk的路径
2.再针对这个ndk路径配置好环境变量,在系统变量下面添加一个变量名“NDK_ROOT”,值为NDK的路径。
最后在path中新建%NDK_ROOT%
配置好了以后在cmd窗口输入ndk-build.cmd以后有下面的打印
3.环境配置好了以后就可以写程序了
先创建一个JniDataUtil.java类,这个类是填充java需要调用c语言的方法的类
package com.ldw.jnitest;
/**
* author: ldw
* created on: 2019/10/13 2:13
* description:
*/
public class JniDataUtil {
//创建一个 native 方法
public native static String get();
}
4.然后创建c语言,创建so
打开 Android Studio 的 Terminal 到 移动到 app/src/main/java 目录下执行命令:javah -jni com.ldw.jnitest.JniDataUtil,
执行以后在java路径下生成com_ldw_jnitest_JniDataUtil.h
在app/src/main目录下创建一个jni的目录,然后将com_ldw_jnitest_JniDataUtil.h移动到jni的目录下,同时在 jni 目录下创建一个 c/c++ resource 文件 test.cpp,
#include
//导入我们创建的头文件
#include "com_ldw_jnitest_JniDataUtil.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_ldw_jnitest_JniDataUtil
* Method: get
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_ldw_jnitest_JniDataUtil_get
(JNIEnv * env, jclass obj)
{
return env->NewStringUTF("This is my NDK Application");
}
#ifdef __cplusplus
}
#endif
下面的这个方法使我们从头文件中复制过来的,头文件是自动生成的com_ldw_jnitest_JniDataUtil.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include
/* Header for class com_ldw_jnitest_JniDataUtil */
#ifndef _Included_com_ldw_jnitest_JniDataUtil
#define _Included_com_ldw_jnitest_JniDataUtil
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_ldw_jnitest_JniDataUtil
* Method: get
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_ldw_jnitest_JniDataUtil_get
(JNIEnv *, jclass);
#ifdef __cplusplus
}
#endif
#endif
然后我们在 jni 目录下创建两个 .mk 文件:
一个 Android.mk:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := JNITest
LOCAL_SRC_FILES := test.cpp
include $(BUILD_SHARED_LIBRARY)
一个是 Application.mk:
APP_ABI := all
Android.mk参考
LOCAL_PATH:=$(call my-dir)
include $(CLEAR_VARS)
#libtestjni.so //生成so的名字
LOCAL_MODULE := testjni //生成模块的规则,生成的so的名字testjni
LOCAL_SRC_FILES := test.cpp //生成模块的规则,so依赖的cpp文件可以有多个
LOCAL_LDLIBS := -llog //生成模块的规则,当前so依赖的so
include $(BUILD_SHARED_LIBRARY) //生成尾缀是so的文件
然后我们需要生成 so 库:
打开 Terminal,到 app/src/main/jni 目录下,使用 ndk-build 命令生成 so 库:
接着打开 app/src/main/libs 就可以看见我们生成的 so 库了。
5.为了防止 so 库兼容错误,在 gradle.properties 最后一行添加:
android.useDeprecatedNdk=true
为了让项目能够找到我们的 so 库,在app下面的 build.gradle 文件夹的 android 下添加:
sourceSets {
main() {
jniLibs.srcDirs = ['src/main/libs']
jni.srcDirs = [] //屏蔽掉默认的jni编译生成过程
}
}
6.然后我们在 JniDataUtil.java 中动态导入 so 库,不需要写 libJNITest,只用写 JNITest:
package com.ldw.jnitest;
/**
* author: ldw
* created on: 2019/10/13 2:13
* description:
*/
public class JniDataUtil {
// 动态导入 so 库
static {
System.loadLibrary("JNITest");
}
//创建一个 native 方法
public native static String get();
}
然后我们在 MainActivity 中打印 JNITest 的 get() 方法获取到的 String 值,Toast中会弹出:This is my NDK Application
package com.ldw.jnitest;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private Button btn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initUi();
}
public void initUi(){
btn = (Button) findViewById(R.id.button);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, JniDataUtil.get(), Toast.LENGTH_SHORT).show();
}
});
}
}
可以参考文档:https://blog.csdn.net/young_time/article/details/80346631