Android JNI基础及其简单使用

Android JNI基础及其简单使用

前言:内容主要包括jni的概念、安卓jni开发的两种方式以及工具的简单使用,读者将了解最基础的jni开发流程。

主要参考:齐行超老师的教程


目录

Android JNI基础及其简单使用

一、JNI、NDK、Cmake、ndk-build的概述

二、Cmake工具的使用(Android默认)

三、ndk-build工具的使用

四、函数的静态注册和动态注册


 

一、JNI、NDK、Cmake、ndk-build的概述

JNI(Java Native Interface)Java本地接口,起作用是使得Java与C/C++具有交互能力,而JNI相当于作为翻译官,使两种语言能够互相理解相互调用,JNI更像是一种协议的作用。

NDK(Native Development kit)本地开发工具包,允许使用原生语言(C/C++)来实现应用程序的部分功能

库文件类型分为:静态库.a  动态库.so  动态库.dll

为什么要使用JNI技术呢?因为当我们需要进行大量数据计算时,原生代码的计算速度远远快于Java:

在安卓中主要有两种方式创建JNI工程(Cmake、ndk-build):

二、Cmake工具的使用(Android默认)

我们先概括性了解一下编译流程吧,工具使用流程如下:

1. 在工程中默认创建的cpp目录下可以看到cmake.txt文件,我们还要在该目录下编写C/C++源文件(此处就暂时不写了,后面有时间再添上)该txt文件中主要就是原生库的相关配置(模块名、源文件位置、版本等)

2. 在build.gradle中进行相关配置(c++库相关配置)

externalNativeBuild {
  cmake {
    cppFlags ”-fexceptions -std=c++14"
    arguments '-DANDROID_STL=c++_shared'
  }
}

还可以配置库的生成位置:

# 配置库生成路径
# CMAKE_CURRENT_SOURCE_DIR是指 cmake库的源路径,通常是build/.../cmake/
#
/../jniLibs/是指与CMakeList.txt所在目录的同级目录:jniLibs (如果没有会新建)
#
ANDROID_ABI 生成库文件时,采用gradle配置的ABI策略(即:生成哪些平台对应的库文件)set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../jniLibs/${ANDROID_ABI})

  1. 1、默认/app/build/intermediates/cmake/..
  2. 2安卓项目默认的JNI库目录:jinLibs
  3. 3可选配置本地jni库的目录
      sourceSets {
             main {
          jniLibs.srcDirs = ['src/main/libs']
             }
      }

还可以配置生成指定ABI库文件:

externalNativeBuild {
    cmake {
       abiFilters "arm64-v8a”
   }
}

三、ndk-build工具的使用

ndk-build工具又分为两种方式进行jni开发,其中一种类似于Cmake,要配合gradle使用,另一种直接使用命令行进行开发,完全脱离了AS

1. 首先在工程main目录下创建jni目录,用于存放配置文件(源文件、Android.mk、Application.mk)

Android.mk:

#此变量表示源文件在的位置

LOCAL_PATH := $(call my-dir)

#用于清除部分LOCAL_变量

include $(CLEAR_VARS)

#module名称,即库文件名称

LOCAL_MODULE := xxx

#源文件列表

LOCAL_SRC_FILES := xxxxxx.cpp

#收集LOCAL_XXX变量中配置的模块的相关信息

#指定了编译目标库类型(静态、动态)

include $(BUILD_SHARED_LIBRARY)

Application.mk

#c++标准库支持

APP_STL := c++_static

#abi过滤

APP_ABI :=arm64-v8a,armeabi-v7a

#指定Android平台版本

APP_PLATFORM := android-21

2-1. 利用gradle编译工程,生成库文件:

externalNativeBuild {
    ndkBuild {
        path = "Android.mk路径"
        abiFilters "arm64-v8a"
    }
}

2-2. 利用命令行生成库文件:

进入jni目录,输入ndk-build就可以进行编译

指定库文件生成目录:

# 配置库生成路径

#输出目录 ../jniLibs/

#ABI $(TARGET_ARCH_ABI)

NDK_APP_DST_DIR=../jniLibs/$(TARGET_ARCH_ABI)

 把jniLib重定向:

1安卓项目默认的JNI库目录:jinLibs

2、可选配置本地jni库的目录:

      sourceSets {

             main {

          jniLibs.srcDirs = ['src/main/libs']

             }

      }

配置生成指定ABI库文件:

ndk {
   
abiFilters "arm64-v8a"
}

四、函数的静态注册和动态注册

静态注册:按照JNI规范书写函数名:Java_包名_类名_方法名

动态注册:JNI_OnLoad中指定Java Native函数与C实现函数的对应关系

动态注册流程:

// jni头文件 
#include <jni.h>
 
#include <cassert>
#include <cstdlib>
#include <iostream>
using namespace std;
 
 
//native 方法实现
jint get_random_num(){
    return rand();
}
/*需要注册的函数列表,放在JNINativeMethod 类型的数组中,
以后如果需要增加函数,只需在这里添加就行了
参数:
1.java中用native关键字声明的函数名
2.签名(传进来参数类型和返回值类型的说明) 
3.C/C++中对应函数的函数名(地址)
*/
static JNINativeMethod getMethods[] = {
        {"getRandomNum","()I",(void*)get_random_num},
};
//此函数通过调用RegisterNatives方法来注册我们的函数
static int registerNativeMethods(JNIEnv* env, const char* className,JNINativeMethod* getMethods,int methodsNum){
    jclass clazz;
    //找到声明native方法的类
    clazz = env->FindClass(className);
    if(clazz == NULL){
        return JNI_FALSE;
    }
   //注册函数 参数:java类 所要注册的函数数组 注册函数的个数
    if(env->RegisterNatives(clazz,getMethods,methodsNum) < 0){
        return JNI_FALSE;
    }
    return JNI_TRUE;
}
 
static int registerNatives(JNIEnv* env){
    //指定类的路径,通过FindClass 方法来找到对应的类
    const char* className  = "com/example/wenzhe/myjni/JniTest";
    return registerNativeMethods(env,className,getMethods, sizeof(getMethods)/ sizeof(getMethods[0]));
}
//回调函数
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved){
    JNIEnv* env = NULL;
   //获取JNIEnv
    if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
        return -1;
    }
    assert(env != NULL);
    //注册函数 registerNatives ->registerNativeMethods ->env->RegisterNatives
    if(!registerNatives(env)){
        return -1;
    }
    //返回jni 的版本 
    return JNI_VERSION_1_6;
}

动态注册原理图:

静态注册流程图:

Java调用Native流程图:

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值