android studio中的JNI实现

来源:互联网 发布:淘宝怎么才能延时收货 编辑:程序博客网 时间:2024/06/07 04:42

前言:

这段时间由于工作上的问题,所以一直没写博客,最近在做sdk,正好用到了JNI,所以写一篇关于如何在Android studio中使用JNI。PS:去年也写过一篇博客是关于NDK在eclipse上的实现,有兴趣可以了解下。

准备工作:

1.下载最新的android-ndk-r13b-windows-x86_64,这个根据自己系统版本来,链接我就不贴了,这个百度一下很多地方有链接的。我解压出来是放到F盘中的,目录:F/android-ndk-r13b
2.创建一个项目,然后配置NDK路径。

3.在项目中的app下的build.gradle中添加如下信息:moduleName就是我们的so文件名字。

4.接下来在gradle.properties中添加一句 android.useDeprecatedNdk=true

按照上述的4步基本上就已经配置好了开发环境了,这里我就不谈一些基础的部分了,比如JNIEnv 以及java中的数据类型在JNI中的转换例如 int->jint,这个可以自行去了解,这里仅仅谈下实现的步骤,相信对于初学者很多都困扰在这里。

项目实现:

1.先来个demo实现结果,这里由于我的录屏工具出现问题了,所以这里没弄成gif格式的,整个demo的操作流程是,分别点击两个textview 调用两个不同的native方法。







2.创建一个加载so文件以及调用native方法的类
先给张整体项目的目录结构:



JNIUtils就是我们的加载so文件的工具类:
package com.example.ljx.jniproject03;/** * Created by ljx on 2017/9/17. */public class JNIUtils {    static {        System.loadLibrary("JniTest");    }    public static native String getStringFromNative();    public static native int sum(int x, int y);}

3.生成JNIUtils的.h文件,主要的作用还是为了给我们生成native方法的代码,我们的实现还是在.c/.cpp文件中实现。
生成的步骤我直接截图出来了

通过上图的方式生成.h文件,简单方便,这样不需要去找我们的class文件,再通过.h来生成了。并且android studio会直接在main目录下创建一个jni的文件夹,用来放我们的.h还有.c/.cpp文件。

com.example.ljx.jniproject03_JNIUtils.h代码:
/* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>/* Header for class com_example_ljx_jniproject03_JNIUtils */#ifndef _Included_com_example_ljx_jniproject03_JNIUtils#define _Included_com_example_ljx_jniproject03_JNIUtils#ifdef __cplusplusextern "C" {#endif/* * Class:     com_example_ljx_jniproject03_JNIUtils * Method:    getStringFromNative * Signature: ()Ljava/lang/String; */JNIEXPORT jstring JNICALL Java_com_example_ljx_jniproject03_JNIUtils_getStringFromNative  (JNIEnv *, jclass);JNIEXPORT jint JNICALL Java_com_example_ljx_jniproject03_JNIUtils_sum        (JNIEnv *, jclass, jint, jint);#ifdef __cplusplus}#endif#endif

4.创建一个.c或者.cpp文件,是具体实现.h文件中声明的native方法的,也就是我们的getStringFromNative还有sum方法。C文件的名字随意取,只是要把.h中的代码全部复制过去,并且实现其中的native方法。
我这里创建的是test.c 

test.c代码:
/* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>#include<util.h>/* Header for class com_example_ljx_jniproject03_JNIUtils */#ifndef _Included_com_example_ljx_jniproject03_JNIUtils#define _Included_com_example_ljx_jniproject03_JNIUtils#ifdef __cplusplusextern "C" {#endif/* * Class:     com_example_ljx_jniproject03_JNIUtils * Method:    getStringFromNative * Signature: ()Ljava/lang/String; */JNIEXPORT jstring JNICALL Java_com_example_ljx_jniproject03_JNIUtils_getStringFromNative  (JNIEnv * env, jobject jObj){        //LOGE("log string from ndk.");        return (*env)->NewStringUTF(env,"Hello From JNI!");  }JNIEXPORT jint JNICALL Java_com_example_ljx_jniproject03_JNIUtils_sum        (JNIEnv *env, jclass jObj, jint x, jint y){    return sum(x, y);}#ifdef __cplusplus}#endif#endif

可以看到,我这还创建了一个util.c/h两个文件,是用来实现sum方法的,这个就和C语言一样了,个人建议,做android最好还是学习下C/C++,并不要求一定要有很深的造诣,毕竟很多底层功能还是需要专业的C/C++程序员来完成的,但是学好C/C++对于理解源码,以及JNI有很大帮助。

5.到这基本就完工了,通过Build->make project 编译一下,就会在app/intermediates/ndk中生成我们的so文件


6.然后在工程的main目录下创建jinLIB文件夹(正规做法是jniLibs文件夹,不过这里并没有什么影响,因为在项目运行的时候,android studio会自动加载jniLibs中的so文件),把armeabi的这个文件夹复制进去,当然也可以把armeabi-v7a..全部复制进去,适配不同CPU类型的手机。一般项目都会生成全部的,并且全部都给复制进去,防止错误。我这仅仅是个demo,所以就图方便了。在项目中千万别这么干。




从上面的流程可以看到,在android studio中实现JNI比在eclipse上方便了很多,Google为我们集成了很好的NDK开发环境,连android.mk都不需要我们自己去写了,可以说,我们仅仅只需要实现我们的C代码,然后通过以上步骤就刽生成我们的so库了,简单方便。
android studio中JNI使用的基本操作就介绍到这里了,如果有问题的话,可以留言,最好是学习下C/C++,当项目中遇到条件变更,需要更改C代码的流程的时候,简单点的东西我们自己也可以改了,并不需要麻烦C/C++工程师了。


DEMO链接地址