AndroidJNI(Java Native Interce)

一、JNI(Java Native Interface)

 1、什么是JNI:

              JNI(Java Native Interface):java本地开发接口

              JNI是一个协议,这个协议用来沟通java代码和外部的本地代码(c/c++)

              外部的c/c++代码也可以调用java代码

       2、为什么使用JNI

              效率上 C/C++是本地语言,比java更高效

             代码移植,如果之前用C语言开发过模块,可以复用已经存在的c代码

              java反编译比C语言容易,一般加密算法都是用C语言编写,不容易被反编译

     

       3、引用类型对应

              

       4、堆内存和栈内存的概念

              栈内存:系统自动分配和释放,

                      保存全局、静态、局部变量,

                      在站上分配内存叫静态分配,

                      大小一般是固定的

              堆内存:程序员手动分配(malloc/new)和释放(free/java不用手动释放,由GC回收),

                      在堆上分配内存叫动态分配,

                      一般硬件内存有多大堆内存就有多大

二、交叉编译

       1、交叉编译的概念

          交叉编译即在一个平台,编译出另一个平台能够执行的二进制代码

          主流平台有: Windows、 Mac os、 Linux

          主流处理器: x86、 arm、 mips

       2、交叉编译的原理

          即在一个平台上,模拟其他平台的特性

          编译的流程: 源代码-->编译-->链接-->可执行程序

       3、交叉编译的工具链

          多个工具的集合,一个工具使用完后接着调用下一个工具

       4、常见的交叉编译工具

          NDK(Native Development Kit): 开发JNI必备工具,就是模拟其他平台特性类编译代码的工具

          CDT(C/C++ Development Tools): 是Eclipse开发C语言的一个插件,高亮显示C语言的语法

          Cygwin: 一个Windows平台的Unix模拟器(可以参考之前博客Cygwin简介及使用)

       5、NDK的目录结构(可以在Google官网下载NDK开发工具,需要FQ)

          docs: 帮助文档

          build/tools:linux的批处理文件

          platforms:编译c代码需要使用的头文件和类库

          prebuilt:预编译使用的二进制可执行文件

          sample:jni的使用例子

          source:ndk的源码

          toolchains:工具链

          ndk-build.cmd:编译打包c代码的一个指令,需要配置系统环境变量

三、JNI的第一个例子

          好了,准备知识已经完毕,下面开始我们的一个JNI例子。

        1、新建一个Android项目,在根目录下创建 jni文件夹,用于存放 C源码。

        2、在java代码中,创建一个本地方法 getStringFromC 本地方法没有方法体。

           private native String getStringFromC();

      3、在jni中创建一个C文件,定义一个函数实现本地方法,函数名必须用使用 本地方法的全类名,点改为下划线。

           #include
#include
#include
//方法名必须为本地方法的全类名点改为下划线,穿入的两个参数必须这样写,
//第一个参数为Java虚拟机的内存地址的二级指针,用于本地方法与java虚拟机在内存中交互
//第二个参数为一个java对象,即是哪个对象调用了这个 c方法
jstring Java_com_mwp_jnihelloworld_MainActivity_getStringFromC(JNIEnv* env,
                                                               jobject obj){
    //定义一个C语言字符串
    char* cstr = "hello form c";
    //返回值是java字符串,所以要将C语言的字符串转换成java的字符串
    //在jni.h 中定义了字符串转换函数的函数指针
    //jstring   (*NewStringUTF)(JNIEnv*, const char*);
    //第一种方法:很少用
    jstring jstr1 = (*(*env)).NewStringUTF(env, cstr);
    //第二种方法,推荐
    jstring jstr2 = (*env) -> NewStringUTF(env, cstr);
    return jstr2;
}

 4、在jni中创建 Android.mk文件,用于配置 本地方法

LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) #编译生成的文件的类库叫什么名字 LOCAL_MODULE := hello #要编译的c文件 LOCAL_SRC_FILES := Hello.c include $(BUILD_SHARED_LIBRARY)

  5、在jni目录下执行 ndk-build.cmd指令,编译c文件

  6、在java代码中加载编译后生成的so类库,调用本地方法,将项目部署到虚拟机上之后就会发现toast弹出的C代码定义的字符串,第一个例子执行成功了。

static{ //加载打包完毕的 so类库 System.loadLibrary("hello"); } 

 7、jni打包的C语言类库默认仅支持 arm架构,需要在jni目录下创建 Android.mk 文件添加如下代码可以支持x86架构

     APP_ABI := armeabi armeabi-v7a x86

 

 

 

你可能感兴趣的:(Android)