Android studio 下的JNI开发

前几天去喜马拉雅面试,笔试中问到了这个问题。自己有印象,但好多细节没记住,悔的我哟!!!多年磨一剑,今天好好总结一下,也和大家分享一下自己的练习经验。毕竟自己脑子还是有点死,有时候只知其一,不知其二。希望大家批评指出,我们一起进步!


JNI的概念

JNI是Java Native Interface的缩写,它提供了若干的API实现了Java和其他语言的通信(主要是C&C++)。它是Java语言提供的Java和C/C++相互沟通的机制,Java可以通过JNI调用本地的C/C++代码,本地的C/C++的代码也可以调用java代码。JNI 是本地编程接口,Java和C/C++互相通过的接口。Java通过C/C++使用本地的代码的一个关键性原因在于C/C++代码的高效性。另一方面,(个人认为)调用动态链接库的so文件来实现某些加密算法后能使得程序系统更加安全,不易破解。


JNI的实现步骤

1.配置NDK环境



2.新建JNI调用文件,并声明本地的JNI接口

打开Android Studio新建好一个Android项目后,我们新建一个JNI文件,在这里来声明和调用我们的JNI方法。我曾尝试将调用写在一个activity中,但是后来在编译,class文件的时候总是报错,说什么找不到activity吧。后来查阅网上也有解决办法,但是出于减少麻烦以及良好的习惯。我们自己建一个JNI的调用文件。然后在里面声明需要实现的方法例如:



public class JNI {
    public native int add(int a,int b);
}
这个方法主要用于求两个数的和。

3.编译生成.class文件
点击菜单栏中的build-->rebuild后进行java文件的编辑可以生成相应的.class文件,生成的文件储存在\build\intermediates\classes\debug中。

4.编译.class生成.h文件
打开Android Studio自带的Terminal工具,进入build\intermediates\classes\debug>文件夹下,方便的办法是在project目录树中找到这个目录,然后将这个文件夹拖进Terminal编辑器。好了,接下来我们输入:
javah -jni [JNI.class文件的路径],我的是com.jerry.hometest.JNI。这里不用加文件的后缀名,路径分隔符是“.”而不是“/”。
紧接着在debug文件夹下会生成一个后缀名为.h的文件

 
5.新建JNIFolder
在项目中新建-->Folder-->JNIFolder,然后finish。会在/src/main/文件夹下生成一个jni文件夹。然后我们把刚刚生成的.h文件copy到这个文件夹下


6.  你的,h文件是这样的(红色字是参数,这是需要我们补上的。我们可以看见这里有四个参数:JNIEnv和JObject分别是JNI指针参数和JObject参数,这两个参数不是我们需要关心的,每个生成的.h文件应该都有这两个参数的。后面的两个参数类型正好就是我们在.class文件中传递进来的两个参数类型,但是具体的实现还不是在这里!

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

#ifndef _Included_com_jerry_hometest_JNI
#define _Included_com_jerry_hometest_JNI
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_jerry_hometest_JNI
 * Method:    add
 * Signature: (II)I
 */
JNIEXPORT jint JNICALL Java_com_jerry_hometest_JNI_add
  (JNIEnv *env, jobject obj, jint a, jint b);

#ifdef __cplusplus
}
#endif
#endif

7.新建.c文件并实现JNI方法

在jni文件夹下新建一个.c文件,在这里实现我们定义的java方法,方法名直接从.h文件中copy,别忘了把“;”换成“{}”



#include "com_jerry_hometest_JNI.h"
JNIEXPORT jint JNICALL Java_com_jerry_hometest_JNI_add
  (JNIEnv *env, jobject obj, jint a, jint b){
return a+b;}

8.实现了Java的方法后,我们还需要配置NDK环境,在jni文件夹中新建Android.mk文件,写入内容:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE:= hello
LOCAL_SRC_FILES := hello.c
include $(BUILD_SHARED_LIBRARY)
 
其中第三和第四个参数分别是定义的模块名称和运用到的.c文件,第四的参数必然是我们刚刚的.c文件。
 
9.再次打开Terminal编辑器,cd到jni文件夹下,输入ndk-build命令,生成.so文件


10.最后在JNI类中的static代码块中引入.so文件。

public class JNI {
    static {
        System.loadLibrary("hello");
    }
    public native int add(int a,int b);
}
 
引号里的应该就是.mk中的第三个参数吧,也可以根据智能提示把该文件加载进来。这样我们就可以在本地的Java文件中调用.c中的方法啦!有时候部分手机不能调到这个.so文件,也就是说在
System.loadLibrary("hello");中报错。这是因为不同手机由于cpu的不同,使用不同的驱动。ABI:指应用基于哪种指令集来进行编译,ABI总共有四种,分别是armeabi、armeabi-v7a、mips、x86,它们都是表示cpu的类型。
 

 
我们在导入其它.so文件也是这么做的!
 
谢谢大家,希望对您有帮助!
 



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值