JNI和Ndk开发

news2024/11/19 4:47:07

按照一下配置,基本能保证demo跑通

1、下载NDK,下载需要的版本

      

 2、下载Cmake版本

     

3、项目结构:含C++源码

     

4、编写JNI的加载类


public class YjkModel {
    static {
        System.loadLibrary("nativ"); //跟CMakeLists.txt 库名一致
    }

    public native  String getJsonData(String path);//通过C++读写数据库,并返回数据,path为数据库的地址,存在assests目录下
    public native  int writeJsonData(String path,String modifyJson); //path数据库地址
}

5、Java调用方(完整代码已贴出)

       String newFilePath = getApplicationContext().getDatabasePath("ctest.ydb").getPath(); // data/data目录
                File file = new File(newFilePath);
                if (!file.exists()) {
                    copyFile(SecondActivity.this, "ctest.ydb", newFilePath);
                }

                YjkModel model = new YjkModel();
                String json = model.getJsonData(newFilePath);



   public static void copyFile(Context context,String filename, String newFilePath) {
        InputStream in = null;
        FileOutputStream out = null;
        // path为指定目录
        File file = new File(newFilePath);
        if (!file.exists()) {
            try {
                in = context.getAssets().open(filename); // 从assets目录下复制
                out = new FileOutputStream(file);
                int length = -1;
                byte[] buf = new byte[1024];
                while ((length = in.read(buf)) != -1) {
                    out.write(buf, 0, length);
                }
                out.flush();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (in != null) {
                    try {
                        in.close();
                    } catch (IOException e1) {
                        e1.printStackTrace();
                    }
                }
                if (out != null) {
                    try {
                        out.close();
                    } catch (IOException e1) {
                        e1.printStackTrace();
                    }
                }
            }
        }
    }

6、配置CMakeLists.txt

cmake_minimum_required(VERSION 3.22.1)


project("nativ")

set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR})
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR})

add_library( 

        # 库名,跟Jni加载类中System.loadLibrary("nativ")一致;跟上面的project("nativ")一致
        nativ

        SHARED

        # 项目中用到的C++文件在这里引入
        native-lib.cpp
        DBoperate.cpp
        DBoperate.hpp
        cJSoperate.cpp
        sqlite3.c
        sqlite3.h
        cJSON.c
        cJSON.h)


find_library( 
        log-lib

        log)


target_link_libraries( 
        nativ

        ${log-lib})

  CMake版本需要在progect的gradle文件中配置,当前的版本是3.22.1

  同样,C++版本配置,也需要在progect的gradle文件中配置,版本是C++11

plugins {
    id 'com.android.application'
}

android {
    namespace 'com.test.nativ'
    compileSdk 32

    defaultConfig {
        applicationId "com.test.nativ"
        minSdk 21
        targetSdk 32
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

        externalNativeBuild {
            cmake {
                cppFlags '-std=c++11'
            }
        }
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    externalNativeBuild {
        cmake {
            path file('src/main/cpp/CMakeLists.txt')
            version '3.22.1'
        }
    }
    buildFeatures {
        viewBinding true
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar'])

    implementation 'androidx.appcompat:appcompat:1.4.1'
    implementation 'com.google.android.material:material:1.5.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}

7、native-lib.cpp(动态注册JNI方法,以及如何调用C++函数)

       注:静态注册JNI方法也可行,但是后期维护麻烦,这里推荐动态注册JNI的方法

#include <jni.h>
#include <string>
#include "DBoperate.hpp"
#include "cJSON.h"


static jstring getJsonData(JNIEnv *env, jobject thisObj, jstring path) {
    const char *dbPath = env->GetStringUTFChars(path, JNI_FALSE);

    DBoperate db;
    bool ret = db.openDB(dbPath);
    cJSON *global = db.jsonGenerate();
    char *json_data = cJSON_Print(global);    //JSON数据结构转换为JSON字符串
    printf("%s\n", json_data);//输出字符串
    db.closeDB();

    return env->NewStringUTF(json_data);
}

static jint writeJsonData(JNIEnv *env, jobject thisObj, jstring path,jstring modifyJson) {
    const char *dbPath = env->GetStringUTFChars(path, JNI_FALSE);

    DBoperate db;
    bool ret = db.openDB(dbPath);
    const char *modifyPath = env->GetStringUTFChars(modifyJson, JNI_FALSE);
    int result= db.ModifyYdb(modifyPath);
    db.closeDB();

    return result;
}


/**
 * 动态注册方案
 * 绑定对应的方法映射表
 */
static const JNINativeMethod methods[] = {
        {"getJsonData",   "(Ljava/lang/String;)Ljava/lang/String;", (jstring *) getJsonData},
        {"writeJsonData",   "(Ljava/lang/String;Ljava/lang/String;)I", (jstring *) writeJsonData},
};

int jniRegisterNativeMethods(JNIEnv *env,
                             const char *className,
                             const JNINativeMethod *gMethods,
                             int numMethods) {
    jclass clazz;
    int tmp;
    printf("Registering %s natives\n", className);
    clazz = env->FindClass(className);
    if (clazz == NULL) {
        printf("Registering registration "
               "unable to find class '%s'\n", className);
        return -1;
    }
    if ((tmp = env->RegisterNatives(clazz, gMethods, numMethods)) < 0) {
        printf("Registering failed for '%s', %d\n", className, tmp);
        return -1;
    }
    return 0;
}

int registerNativeMethods(JNIEnv *env) { //com/test/nativ/YjkModel 为JNI类的全路径
    return jniRegisterNativeMethods(env, "com/test/nativ/YjkModel", methods,
                                    sizeof(methods) / sizeof(methods[0]));
}

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
    JNIEnv *env = NULL;
    jint result = JNI_ERR;
    if (vm->GetEnv((void **) &env, JNI_VERSION_1_4) != JNI_OK) {
        return result;
    }
    if (registerNativeMethods(env) != JNI_OK) {
        return -1;
    }
    result = JNI_VERSION_1_4;
    printf("Registering jni load start: %d", result);
    return result;
}

关于对native-lib.cpp中重要内容介绍:   

     1. java层在调用System.loadLibrary()加载动态库后,java虚拟机就会去该库中寻找JNI_OnLoad这个函数,如果有则会调用它,我们的动态注册也就是在这里完成的,所以如果想实现动态注册,就必须实现JNI_OnLoad这个函数;

    2.动态注册方案 绑定对应的方法映射表,需要先获取函数的签名,看第三步

   static const JNINativeMethod methods[] = {
        {"getJsonData",   "(Ljava/lang/String;)Ljava/lang/String;", (jstring *) getJsonData},
        {"writeJsonData",   "(Ljava/lang/String;Ljava/lang/String;)I", (jstring *) writeJsonData},
};

   3.如何获取函数签名,使用命令

        javac  YjkModel.java   (生成.class文件)

        javap -s -p YjkModel.class   (生成函数签名)

         

    4、JNI签名信息介绍:
        格式:(参数1类型标识 参数2类型标识 …参数n类型标识)返回值类型标识

        例如:JAVA层的native函数   

               public native String getJsonData(String path);

        它对应的JNI层签名信息如下:
              (Ljava/lang/String;)Ljava/lang/String;

 

     其中括号内部是参数类型的标识,最右边是返回值类型标识的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/157261.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于 APISIX 的服务网格方案 Amesh 积极开发中!

作者lingsamuel&#xff0c;API7.ai 云原生技术专家&#xff0c;Apache APISIX Committer。 在云原生快速发展的前提下&#xff0c;服务网格领域也开始逐渐火热。目前阶段&#xff0c;大家所熟知的服务网格解决方案很多&#xff0c;每种产品又各有其优势。因此在面对不同的行业…

python直接赋值、浅拷贝与深拷贝

本文主要参考这篇博文python浅拷贝与深拷贝 基本概念 首先了解python中的一些基本概念 变量&#xff1a;是一个系统表的元素&#xff0c;拥有指向对象的连接空间对象&#xff1a;被分配的一块内存&#xff0c;存储其所代表的值引用&#xff1a;是自动形成的从变量到对象的指…

ECU Extract + OS Task Mapping 步骤

纲要&#xff1a; 通过 Composition里面的Assembly Connection (Intra-ECU Communication)System Extract 里面的SystemDataMapping (Inter-ECU Communication) 已经把SWC的所有Data Element都连接上了&#xff0c;接下来就是把SWC的Runnable给Mapping到对应的OS Task上&…

(三)redis五大数据类型和key

目录 一、redis键&#xff08;key&#xff09;的常用操作 二、redis字符串&#xff08;String&#xff09; 1、简介 2、常用命令 3、数据结构 三、redis列表&#xff08;List&#xff09; 1、简介 2、常用命令 3、数据结构 四、redis集合&#xff08;Set&#xff09;…

Django(16):rest_framework框架使用指南

目录1.安装配置2.数据序列化2.1 Serializer2.2 ModelSerializer2.3 序列化对象的属性和方法3.请求和响应3.1 Request3.2 Response3.3 状态码3.4 as_view3.5 format_suffix_patterns3.6 示例4.CBV构建&#xff08;基于类的视图&#xff09;4.1 如何构建4.2 类型视图的扩展功能4.…

DMIPS, FLOPS, OPS概念

DMIPS DMIPS(Dhrystone Million Instructions executed Per Second)&#xff1a;Dhrystone是测量处理器运算能力的最常见基准程序之一&#xff0c;常用于处理器的整型运算性能的测量。Dhrystone是一种整数运算测试程序。换句话说&#xff0c;就是使用Dhrystone这种程序在不同的…

【云原生 | 52】Docker三剑客之Docker Compose第三节

&#x1f341;博主简介&#xff1a; &#x1f3c5;云计算领域优质创作者 &#x1f3c5;2022年CSDN新星计划python赛道第一名 &#x1f3c5;2022年CSDN原力计划优质作者 &#x1f3c5;阿里云ACE认证高级工程师 &#x1f3c5;阿里云开发者社区专…

FineReport填报报表

二次确认&#xff0c;删除行&#xff1a;参考&#xff1a; JS实现删除时二次确认- FineReport帮助文档 - 全面的报表使用教程和学习资料JS实现记录填报操作- FineReport帮助文档 - 全面的报表使用教程和学习资料确认后直接校验提交// 二次确认 var cell this.options.location…

开始安装Domino 12.0.2

大家好&#xff0c;才是真的好。 上周我们话题是NotesDomino12.0.2产品发布&#xff0c;主要说到了Domino12.0.2的新特性&#xff0c;新特性很多&#xff0c;要用很多篇来进行测试和说明。 今天我们主要谈谈Domino 12.0.2的系统要求和安装等。 首先&#xff0c;Domino12.0.2…

一、初识FreeRTOS之FreeRTOS简介

目录 一、什么是FreeRTOS&#xff1f; 二、为什么选择FreeRTOS&#xff1f; 三、FreeRTOS的特点 四、FreeRTOS资料与源码下载 五、FreeRTOS源码文件介绍 一、什么是FreeRTOS&#xff1f; Free即免费的&#xff0c;RTOS的全称是Real time operating system,中文就是实时操作…

python数据结构(一):字符串

一、字符串的格式化输出 1.1、格式化运算符 print("我跑完了第" str(lap 1) "圈")上面这段输出的代码使用了两个加号做了字符串拼接&#xff0c;并且将整形转换成了字符串。也可以使用一种更好的办法&#xff0c;格式化输出来打印这句话。 print(&quo…

xilinx srio ip学习笔记之再识srio

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 xilinx srio ip学习笔记之再识srio前言SRIO的理解IP核的理解前言 这段时间&#xff0c;随着对SRIO的学习&#xff0c;又有了更深的一点认识&#xff0c;不像一开始这么慌张了…

年终汇报工作,如何用项目管理工具展现成果

据报道&#xff0c;2022年11月20日的一次京东内部会议上&#xff0c;刘强东痛批京东中高层管理人员&#xff0c;表示部分高管醉心于 PPT 和奇妙词汇&#xff0c;或吹得天花乱坠但是执行一塌糊涂。 不可否认&#xff0c;刘强东提到的现象&#xff0c;的确是当今众多互联网大厂和…

基于frp实现外网访问个人本地服务器

适用对象想要通过frp实现内网服务被外网访问的人。关键词描述内网&#xff1a;内网指的是局域网&#xff0c;几台或者几十台电脑之间互访&#xff0c;也叫私网。外网&#xff1a;指的是我们上的Internet网络&#xff0c;也叫公网。需要具备的知识基础和条件1&#xff1a;外网服…

Java异常分类常见使用场景

今天在自己实现RxJava框架时&#xff0c;发现一些参数异常、流关闭异常等&#xff0c;Rxjava框架是会抛出相应的异常的&#xff0c;所以自己编写实现这块源码的时候&#xff0c;渐渐的也需要使用到这些知识&#xff0c;这里对这块做一下回顾总结。 使用 我们代码编写实现中&am…

开年喜讯!知道创宇一连斩获2022年度“IT168技术卓越奖”三项大奖

近日&#xff0c;业界知名IT垂直门户媒体IT168发布“2022年度IT168技术卓越奖”获奖名单&#xff0c;知道创宇凭借强大的技术优势与出色的产品能力脱颖而出&#xff0c;一举斩获网络安全领域三项大奖&#xff1a; 知道创宇创始人、CEO赵伟获评“数字化转型领军人物” ScanV-互…

【C++】优先级队列priority_queue/仿函数(函数对象)

这里写目录标题一.优先级队列1.优先级队列的介绍2.priority_queue的定义与使用二.仿函数/函数对象三.优先级队列的模拟实现一.优先级队列 1.优先级队列的介绍 1&#xff09;注意优先级队列和队列不是一个东西&#xff0c;队列是容器&#xff0c;优先级队列是一种容器适配器&am…

服务监控之promethues+grafana,直接送你上大师,这还不上热门吗

最近的项目需要上监控&#xff0c;虽然之前也是使用这个方案&#xff0c;但是作为使用者一直没有太关注细节&#xff0c;也没有真正的去部署过&#xff0c;刚好凑着这次机会&#xff0c;彻底掌握下这套监控系统 1、监控系统架构 监控的架构这个图几乎每个文章都有&#xff0c…

学习JS,实现自动打字机动效

前几天遇到一个需求&#xff0c;产品告诉我说&#xff0c;希望这些字可以像自动打字那样&#xff0c;一个一个的出来&#xff0c;于是在完成需求的同时&#xff0c;顺便把这个方法记录出来&#xff0c;看大家是否也需要。 目录 1、实现思路 2、html布局和css样式 3、预定义…

【数据库】什么是关系型数据库和非关系型数据库

数据库分类关系型数据库非关系型数据库键值对存储数据库列存储数据库搜索引擎数据库面向文档数据库图形数据库数据库优缺点应用程序都离不开数据库&#xff0c;那不同的数据结构&#xff0c;就会存放在不同的数据数据库中&#xff0c;所以数据库按数据结构分为关系型数据库和非…