一、前言
为什么要使用jni、ndk?
效率上 C/C++是本地语言,比java更高效
代码移植,如果之前用C语言开发过模块,可以复用已经存在的c代码
java反编译比C语言容易,一般加密算法都是用C语言编写,不容易被反编译
二、环境配置
1.安装JDK,配置环境变量:
JAVA_HOME:D:\installSoftCache\jdk1.8.0_31(jdk安装目录)
CLASSPATH: .;%JAVA_HOME%\lib(引用jdk目录,注意前面有.)
Path增加:D:\installSoftCache\jre1.8.0_31\bin
如果出现问题:"android 中javah不是内部命令",是因为环境变量没有配置或者android studio没有引用jdk目录,需要在Terminal窗口中输入命令:
setx PATH "%PATH%;D:\installSoftCache\jre1.8.0_31\bin"
三、项目实现native方法
1.新建Android项目,包名为com.whh.jni4ndk
2.新建包ndk,在其中新建NDKTools.class文件
文件内容
public class NDKTools {
static {
System.loadLibrary("jni4ndk-jni");
}
public static native String getStringFromNDK();
}
3.在UI中显示native方法内容
String text = NDKTools.getStringFromNDK();
((TextView)findViewById(R.id.tv)).setText(text);
4.编译项目,生成classes文件
5.在Terminal窗口中,进入app\src\mian目录,输入命令:
E:\Android_workspace\JNI4NDK\app\src\main>javah -d jni -jni -classpath ....\build\intermediates\classes\debug com.whh.jni4ndk.ndk.NDKTools
几秒后在JNI4NDK\app\src\main\jni下面生成com_whh_jni4ndk_ndk_NDKTools.h文件,内容如下
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_whh_jni4ndk_ndk_NDKTools */
#ifndef _Included_com_whh_jni4ndk_ndk_NDKTools
#define _Included_com_whh_jni4ndk_ndk_NDKTools
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_whh_jni4ndk_ndk_NDKTools
* Method: getStringFromNDK
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_whh_jni4ndk_ndk_NDKTools_getStringFromNDK
(JNIEnv *, jclass);
#ifdef __cplusplus
}
#endif
#endif
6.在jni目录下增加相应的.c文件
#include "com_whh_jni4ndk_ndk_NDKTools.h"
JNIEXPORT jstring JNICALL Java_com_whh_jni4ndk_ndk_NDKTools_getStringFromNDK
(JNIEnv *env, jobject obj){
return (*env)->NewStringUTF(env,"Hellow World,这是慧慧同学的NDK的第一行代码");
}
7.在jni目录下增加Android.mk文件,其内容如下:
include $(CLEAR_VARS)
LOCAL_MODULE := jni4ndk-jni
LOCAL_SRC_FILES := jni4ndktest.c
include $(BUILD_SHARED_LIBRARY)
8.检查local.properties文件中是否包含ndk目录配置,没有则配置上
打开AS-Settings-搜索sdk-选择SDK Toos,在列表中选择ndk安装
ndk下载
在local.properties文件最后加上:
ndk.dir=D\:\\installSoftCache\\Android\\sdk\\ndk-bundle
sdk.dir=D\:\\installSoftCache\\Android\\sdk
ndk配置完成,使得项目支持NDK,需要在项目中gradle.properties文件后面加上一句:
Android.useDeprecatedNdk=true
9.为了生成so文件,在app module目录下的build.gradle中的增加内容
app gradle配置
ndk{
moduleName "jni4ndk-jni"
abiFilters "armeabi", "armeabi-v7a", "x86"
}
externalNativeBuild {
ndkBuild {
path 'src/main/jni/Android.mk'
}
}
sourceSets.main {
jni.srcDirs = []
jniLibs.srcDirs = ['src/main/jniLibs']
}
四、总结
JNI和NDK
JNI是Java调用Native 语言的一种特性,属于Java,Java本地接口,使Java与本地其他类型语言交互(C++)
实现步骤:在Java中声明Native方法,编译该文件得到.class文件,通过javah命令导出JNI头文件(.h文件),使用Java需要交互的本地代码实现子啊Java中声明的Native方法,编译so文件,通过Java执行Java程序,最终实现Java调用本地代码
NDK(Native Develop Kit):Android开发工具包,属于Android。
作用:快速开发C、C++动态库,并自动将so文件和应用打包成APK,即可通过NDK在Android中使用JNI与本地代码(C、C++)交互(Android开发需要本地代码C、C++实现)
特点:运行效率高,代码安全性高,功能拓展性好,易于代码复用和移植。
使用步骤:①配置NDK环境;②创建Android项目,并于NDK进行关联;③在Android项目中声明所需调用的Native方法;④使用该Native方法;⑤通过NDK build命令编译产生so文件;⑥编译AS工程,实现调用本地代码。
JNI和NDK的关系:JNI实现目的,NDK是Android实现JNI的手段,即在AS开发环境中通过NDK从而实现JNI功能。
参考文章:
一天掌握Android JNI本地编程 快速入门 - rocomp - 博客园
https://www.cnblogs.com/rocomp/p/4892866.html
Android JNI学习(二)——实战JNI之“hello world” - 简书
https://www.jianshu.com/p/b4431ac22ec2
每天进步一点点(2019-06-02):
我的技术分享文集目录 https://www.jianshu.com/p/23485c157d76
网友评论