android使用java自带的JNI接口来调用C或者C++的代码,在之后的几篇文章中我会介绍android studio中几种常用的方法来使用JNI
1. 最简单的方法,利用android默认的c++或者c文件查找编译目录 app/src/main/jni
android工程目录如下
加入的文件主要包括myJNI的java类,用来提供java调用c++的接口以及app/src/main/jni目录下的h文件和testJNI.cpp的实现文件(可以切换至Project查看目录结构,当前处于Android状态)
myJNI文件如下:
package com.lw.myapplication;
/**
* Created by LW on 2016/9/6.
*/
public class myJNI {
static{
System.loadLibrary("testJNI");
}
public native static int add(int a,int b);
}
可见首先load了一个testJNI库,库名在之后会提到,native表示这是由c或者c++来实现的一个底层函数。
那么java是如何找到这个函数的实现的呢?
我们再看jni目录下的.h文件,这个文件可以在app/src/main目录下,于命令行终端中输入
javah -d jni -classpath ./java com.lw.myapplication.myJNI ,如图所示:
-d代表会在main目录下新建jni目录,然后根据main/java/com/lw/myapplication/myJNI.class文件中定义的native方法定义相应的.h文件,.h文件如下:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_lw_myapplication_myJNI */
#ifndef _Included_com_lw_myapplication_myJNI
#define _Included_com_lw_myapplication_myJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_lw_myapplication_myJNI
* Method: add
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_com_lw_myapplication_myJNI_add
(JNIEnv *, jclass, jint, jint);
#ifdef __cplusplus
}
#endif
#endif
课件方法名就是Java+包名+类名+方法名,前两个参数是静态方法所需要的,分别是java环境和类,很容易想到这就可以调用静态方法了,如果不是静态方法,就需要java环境和类变量,之后会说到。jint主要是为了java的平台无关性可能导致的int类型定义的字节长不同而封装的int类型,都是4个字节。
有了.h文件后,我们就可以新建一个cpp文件用来实现这个方法。testJNI.cpp定义如下:
#include "com_lw_myapplication_myJNI.h"
JNIEXPORT jint JNICALL Java_com_lw_myapplication_myJNI_add
(JNIEnv * env, jclass cls, jint a, jint b){
return a+b;
}
可见这仅仅是实现两个整数相加。
说到这,就要提到我们之前说到的库,我们再myJNI类中load了一个库,其实里面就是我们的实现,为此我们需要在build.gradle(Module:APP)中告诉android我们想要编译库的操作。
可见在其中我们告诉android我们的库名是testJNI,目标的arm架构为arm64-v8a 或者是 armeabi-v7a(这个可加可不加)。
然后在运行我们的java代码之前,就会编译好我们的libtestJNI,so这个动态库,myJNI类就可以找到这个库文件。
那么如何使用这个方法呢?很简单,通过myJNI.add(a,b)就可以运行,这和我们普通调用java类的方法并没有什么区别,只是这个方法的实现使用的是c++。
Mainactivity的代码如下:
package com.lw.myapplication;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView =(TextView)findViewById(R.id.hello);
textView.setText(String.valueOf(myJNI.add(1,2)));
}
}