JNI入门-第一个实例

NDK简介

官方文档介绍如下:

The Android NDK is a toolset that lets you implement parts of your app in native code, using languages such as C and C++. For certain types of apps, this can help you reuse code libraries written in those languages.

大概意思就是NDK它是一个工具集, 它可以让你使用C/C++语言来实现APP的某些部分。对于某些类型的应用,NDK可以帮助你使用C/C++重写代码库。

与NDK密切相关的另一个词汇则是JNI,它是NDK开发中的枢纽,Java与C/C++层交互基本上就是是通过它来完成的,那么什么是JNI?

JNI:Java Native Interface 也就是java本地接口,它是一个协议,这个协议用来沟通java代码和本地代码(c/c++)。通过这个协议,Java类的某些方法可以使用原生实现,同时让它们可以像普通的Java方法一样被调用和使用,而原生方法也可以使用Java对象,调用和使用Java方法。也就是说,使用JNI这种协议可以实现:java代码调用c/c++代码,而c/c++代码也可以调用java代码。

环境准备

1、Android Studio

2、Android SDK

3、Android NDK

使用AS创建好一个Project后,需要注意几个地方的配置:

1)local.propertites 添加ndk目录


2) gradle.propertites  添加ndk的支持

扫描二维码关注公众号,回复: 2746493 查看本文章


代码编写步骤

第一步 (创建一个Java类)

public class MyFirstJniTest {
    // native关键字 即表示该方法为本地方法  是C/C++实现的
    public static native String getString();
    public static native int add(int a, int b);

}

第二步 (命令行进入到该类的目录下,输入  javac MyFirstJniTest.java) 

例如下:


此时,我们可以看到在你的MyFirstJniTest包下 多了个.class文件,如下


第三步(回到代码的Java文件加下,输入命令 javah -jni com.example.androidqunyinhui.jni.MyFirstJniTest)


输入完命令,则会生成com_example_androidqunyinhui_jni_MyFirstJniTest.h文件;

在main文件夹下创建一个jni文件夹,然后将该.h文件剪贴到jni文件夹下,具体如下:



此处的MyFirstJniTest.c文件是接下来的步骤中会创建的文件。

我们大致看下com_example_androidqunyinhui_jni_MyFirstJniTest.h文件

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

#ifndef _Included_com_example_androidqunyinhui_jni_MyFirstJniTest
#define _Included_com_example_androidqunyinhui_jni_MyFirstJniTest
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_example_androidqunyinhui_jni_MyFirstJniTest
 * Method:    getString
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_example_androidqunyinhui_jni_MyFirstJniTest_getString
  (JNIEnv *, jclass);

/*
 * Class:     com_example_androidqunyinhui_jni_MyFirstJniTest
 * Method:    add
 * Signature: (II)I
 */
JNIEXPORT jint JNICALL Java_com_example_androidqunyinhui_jni_MyFirstJniTest_add
  (JNIEnv *, jclass, jint, jint);

#ifdef __cplusplus
}
#endif
#endif

可以发现声明得有两个函数,XXX_getString  和  XXX_add, 这两个函数的具体实现,我们将在.c文件中完成。

第四步 (编写实现代码 MyFirstJniTest)

// 包含头文件
#include <com_example_androidqunyinhui_jni_MyFirstJniTest.h>

//返回一个字符串
JNIEXPORT jstring JNICALL Java_com_example_androidqunyinhui_jni_MyFirstJniTest_getString
  (JNIEnv *env, jclass jobj){
    return (*env)->NewStringUTF(env,"MyFirstJniTest 我是用jni调用出来的字符串");
}
//返回 a+b的结果
JNIEXPORT jint JNICALL Java_com_example_androidqunyinhui_jni_MyFirstJniTest_add
  (JNIEnv *env, jclass jobj, jint a, jint b){
  return a+b;
}

第五步 (修改app 下的  build.gradle 中的配置)

defaultConfig {
        applicationId "com.example.androidqunyinhui"
        minSdkVersion 16
        targetSdkVersion 24
        versionCode 1
        versionName "1.0"

        multiDexEnabled true
        // 此处为ndk添加的配置
        ndk {
            moduleName "MyFirstJinTest"//指定生成的so文件名
            abiFilters "armeabi-v7a", "x86"//cpu的类型
        }
    }

第六步 (rebuild project 工程文件)

rebuild 整个工程文件,我们可以在build文件夹下看到对应的so包,具体如下:


第七步(Java层的使用)

public class JniTestActivity extends AppCompatActivity {

    public static void startActivity(Context context){
        Intent intent = new Intent(context, JniTestActivity.class);
        context.startActivity(intent);
    }

    static {
        //名字必须和build.gradle中的moduleName一致
        System.loadLibrary("MyFirstJinTest");
    }

    private TextView tvShowInfo;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_jni_test);

        initView();
    }

    private void initView(){

        tvShowInfo = (TextView) findViewById(R.id.tv_show_info);

        findViewById(R.id.btn_show_info).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String text = MyFirstJniTest.getString();
                int sum = MyFirstJniTest.add(1, 2);
                tvShowInfo.setText(text+"   "+sum);
            }
        });
    }
}

具体显示如下:



通过以上七个步骤, 基本上完成了  Java层native方法-->jni层-->native层代码编写及调用关系,基本上展现了NDK开发的所有步骤流程。

参考文献

https://www.cnblogs.com/guanmanman/p/6769240.html

https://blog.csdn.net/u011652925/article/details/78272406

猜你喜欢

转载自blog.csdn.net/u010349644/article/details/80816701
今日推荐