本地接口JNI的使用总结
1、简介
JNI是Java Native Interface的简写,即为Java语言的本地接口,它允许我们在Java代码中去使用其他语言的功能,比如:C、C++及汇编语言等。
一般,在Android当中,我们会把某些敏感或是核心的功能放在C/C++中实现,因为Java或Android的安全性不是很好,容易被反编译或是破解,而用C/C++实现的话,安全性好,并且C/C++是运行在底层的,好处可想而知。
2、使用
对于JNI的使用比较简单,分为以下几步:
A、新建一个Android项目
B、创建本地接口
C、创建对应本地接口的头文件和源文件
D、使用工具ndk-build编译生成.so库文件
E、将生成的.so文件放入到项目的libs/armeabi使用
下面就按照上面的步骤一步步进行,以在屏幕上显示HelloJni来演示JNI的使用流程:
A、新建项目
我的项目目录如下:
B、新建本地的接口文件(JNIService)
内容如下:
/*
* JNI的本地方法
*/
public class JNIService {
static {
System.loadLibrary("hello_jni");
}
public static native String getString();// 获取字符串
}
C、创建本地接口对应的C/C++文件
头文件:
我们可以使用jdk的命令工具javah来生成需要的头文件,当然,也可以自行编写头文件(这需要你对C比较熟悉)。
具体如下:
首先,运行新建接口的项目,此时会在项目的bin目录下生成对应的.class文件,我们只需要对定义了本地接口的类进行编译生成头文件即可,具体如下:
切换到项目的目录下,执行命令:javah -classpath bin/classes -d jni com.demo.hellojni.JNIService,这里我们新建了一个目录jni来存放生成的头文件,我的目录如下所示:
接下来,就是编写源文件了,这里我们使用Visual studio 来编写C文件,上面的头文件内容如下:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_demo_hellojni_JNIService */
#ifndef _Included_com_demo_hellojni_JNIService
#define _Included_com_demo_hellojni_JNIService
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_demo_hellojni_JNIService
* Method: getString
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_demo_hellojni_JNIService_getString
(JNIEnv *, jclass);
#ifdef __cplusplus
}
#endif
#endif
下面我们编写对应的源文件JNIService.c,这个文件的编写需要参照头文件的规范,具体如下:
#include <jni.h>
JNIEXPORT jstring JNICALL Java_com_demo_hellojni_JNIService_getString(JNIEnv * env, jobject obj)
{
return (*env)->NewStringUTF(env,"HELLO NDK!");
}
好了,头文件和源文件都编写完成,接下来我们需要再编写一个Android.mk文件来,内容如下:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := hello_jni
LOCAL_SRC_FILES := JNIService.c
include $(BUILD_SHARED_LIBRARY)
接下来,我们将上面的头文件、源文件及Android.mk文件放到JNI。
D、编译生成的文件
这里使用了ndk来编译资源文件,所以需要先安装和配置NDK,另外我们需要第三方软件(这里我使用Cygwin协助编译),具体可参考博客:
http://blog.csdn.net/jiangwei0910410003/article/details/17710243
打开Cygin软件,定位到上面的jni目录,我的目录:
执行命令:$NDK/ndk_build进行编译,执行结果如下:
编译成功后,会生成两个文件目录,分别为libs和obj,这里我们只需要关注libs即可。具体如下:
到这里,我们需要已久的.so文件就可以使用了,将这个.so文件放到项目目录的libs/armeabi(如果没有 则新建这个目录,只有在这个目录下的so文件才会被加载)。
最后,就是怎样调用这个JNI了,具体如下:
public class HelloJNIActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_hello_jni);
}
public void helloJNIShow(View v) {
String helloJNI = JNIService.getString();
Toast.makeText(this, helloJNI, Toast.LENGTH_SHORT).show();
}
}
这样就可以运行我们的项目,当我们点击欢迎语的时候,就是显示C/C++返回的信息提示了,效果图如下:
在后面的文章中,我会继续列举一个有实际意义的例子,比如:Android当中的加密和解密实现
/*
* Android技术交流群号:179914858
* 欢迎加入
*/