Android JNI、NDK实现

一、前言
为什么要使用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安装


3013099-5c5aae33c6b8f091.png
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中的增加内容


3013099-f4d04dfb70d73b44.png
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

猜你喜欢

转载自blog.csdn.net/weixin_34415923/article/details/90967384