Android JNI Java/C++互相调用

2023-05-16

一,Java 调用 C

   1, 首先我们创建一个文件名字叫做,JNI。其实你不创建也行。看自己

public class JNI {
    //加载本地C语言文件库。库名字为你写的C语言文件名
    static {
        System.loadLibrary("Hello");
    }
    
    
    //todo: java 调用 C =======
    public native String stringFromJNI();
//相加
    public native  int numberTest(int a,int b);

//字符串拼接 java 和 C
    public native String strOrStr(String str);

 // 在C中数组中的每一个元素+10 然后返回到 java;
    public native int [] getArray(int array[]);

}

 2, 再次来到Cpp文件里

#include <jni.h>
#include <string>
#include<android/log.h>
#define  LOG_TAG    "nativeprint"
#define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOGD(...)  __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOGE(...)  __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__

// java String 转成C char
char *jstringTostring(JNIEnv *env, jstring jstr);

#pragma clang diagnostic push
#pragma ide diagnostic ignored "err_typecheck_member_reference_arrow"
extern "C" JNIEXPORT jstring JNICALL
Java_com_cwj_ndkc_JNI_stringFromJNI(JNIEnv *env, jobject) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}


extern "C"
JNIEXPORT jint JNICALL
Java_com_cwj_ndkc_JNI_numberTest(JNIEnv *env, jobject thiz, jint a, jint b) {
    // TODO: implement numberTest()
    int result = a + b;
    return result;
}


extern "C"
JNIEXPORT jstring JNICALL
Java_com_cwj_ndkc_JNI_strOrStr(JNIEnv *env, jobject thiz, jstring str) {
    // TODO: implement strOrStr()
    char *javas = jstringTostring(env, str);
    char *cc = "我是C语言中的char*";
    strcat(javas, cc);
//    return (*env)->NewStringUTF(env,javas);
    return env->NewStringUTF((char *) javas);
}

//char* 转成String
jstring stoJstring(JNIEnv *env, const char *pat) {
    jclass strClass = env->FindClass("java/lang/String");
    jmethodID ctorID = env->GetMethodID(strClass, "<init>", "([BLjava/lang/String;)V");
    jbyteArray bytes = env->NewByteArray(strlen(pat));
    env->SetByteArrayRegion(bytes, 0, strlen(pat), (jbyte *) pat);
    jstring encoding = env->NewStringUTF("utf-8");
    return (jstring) env->NewObject(strClass, ctorID, bytes, encoding);
}
// java String 转成C char
char *jstringTostring(JNIEnv *env, jstring jstr) {
    char *rtn = NULL;
    jclass clsstring = env->FindClass("java/lang/String");
    jstring strencode = env->NewStringUTF("utf-8");
    jmethodID mid = env->GetMethodID(clsstring, "getBytes", "(Ljava/lang/String;)[B");
    jbyteArray barr = (jbyteArray) env->CallObjectMethod(jstr, mid, strencode);
    jsize alen = env->GetArrayLength(barr);
    jbyte *ba = env->GetByteArrayElements(barr, JNI_FALSE);
    if (alen > 0) {
        rtn = (char *) malloc(alen + 1);
        memcpy(rtn, ba, alen);
        rtn[alen] = 0;
    }
    env->ReleaseByteArrayElements(barr, ba, 0);
    return rtn;
}

extern "C"
JNIEXPORT jintArray JNICALL
Java_com_cwj_ndkc_JNI_getArray(JNIEnv *env, jobject thiz, jintArray array) {
    // TODO: implement getArray()
    //1, 得到数组的长度
    int lenght = env->GetArrayLength(array);
    //2,得到数组的元素
    jint *intArray = env->GetIntArrayElements(array,0);
    //3,遍历数组顺便加10
    int i;
    for (i = 0; i < lenght; ++i) {
        *intArray+=10;
    }
    return array;
}

注意: 观察,Java Native方法,再看C++里面的实现。会发现,

C++的方法名字:是Java+JavaNative接口包名+接口名的方式生成的,对,这个不用自己写。直接根据AS提示,自动创建。

3,在Activity中调用。先看看目录

     case R.id.btn_java:
                //java调用C
                jni.strOrStr("参数");
                

二,C++调用Java

1,首先要有一个java 方法吧,然后C调用java了 ,最后,还是要回到Activity中去调用。 这里只是把java方法和native接口写在了一个类中。


    //todo: C 调用java=======================================================
    public int  addJava(int x,int y){
        Log.e(TAG, "addJava() x=" + x + " y=" + y);
        return x+y;
    }
    public native void callAdd();

    
    //todo:C  c调用静态java方法
     public static void javaString(String jstr){
         Log.e(TAG, "javaString()  "  +jstr);

     }
     public native void javaStringCall();

2,Cpp代码

//=============================================todo:===================== C调用java
extern "C"
JNIEXPORT void JNICALL
Java_com_cwj_ndkc_JNI_callAdd(JNIEnv *env, jobject thiz) {
    // TODO: implement callAdd()
    //要用到反射
    //1,得到字节码
    jclass  jclass1=env->FindClass("com/cwj/ndkc/JNI");
    //2,得到方法
    jmethodID jmethodId=env->GetMethodID(jclass1,"addJava","(II)I");
    //3,实例化该类
    jobject  jobject=env->AllocObject(jclass1);
    //4,调用方法,得到结果
   jint jint1= env->CallIntMethod(jobject,jmethodId,99,1);
}
//调用静态java方法
extern "C"
JNIEXPORT void JNICALL
Java_com_cwj_ndkc_JNI_javaStringCall(JNIEnv *env, jobject thiz) {
    // TODO: implement javaStringCall()
        //1,得到字节码
            jclass jclass1=env->FindClass("com/cwj/ndkc/JNI");
        //2.得到方法 字节码,方法名,方法签名
            jmethodID jmethodId=env->GetStaticMethodID(jclass1,"javaString","(Ljava/lang/String;)V");
        //3,调用方法
            jstring jst=env->NewStringUTF("这个是java静态方法参数");
            env -> CallStaticVoidMethod(jclass1,jmethodId,jst);
            printf("日志:=======");
            __android_log_print(ANDROID_LOG_INFO,"日志",  "aa");
}

3,最后调用方式是一样的。

 case R.id.btn_c:
                //C调用java
                jni.callAdd();//C
                jni.javaStringCall();//C

注意:学这个之前先把C++ 看一遍。其实语法差不多,最大的区别是,C++的指针,和结构体,这俩要多看几遍

三,C调用Activity中的方法,更新UI

    Activity ==================

    public  native void showToastCall();

    public void  showToast(){
        Toast.makeText(this, "C++调用我了", Toast.LENGTH_SHORT).show();
    }

    Cpp==================

    extern "C"
JNIEXPORT void JNICALL
/**
 * 
 * @param env  
 * @param thiz 这个代表的Activity  ,不需要实例化
 */
Java_com_cwj_ndkc_MainActivity_showToastCall(JNIEnv *env, jobject thiz) {
    // TODO: implement showToastCall()
    //要用到反射
    //1,得到字节码
    jclass  jclass1=env->FindClass("com/cwj/ndkc/MainActivity");
    //2,得到方法
    jmethodID jmethodId=env->GetMethodID(jclass1,"showToast","()V");
    //3,实例化该类
//    jobject  jobject=env->AllocObject(jclass1);
    //4,调用方法,得到结果
    env->CallVoidMethod(thiz,jmethodId);
}


Activity调用=================================
                 MainActivity.this.showToastCall();

    

 

 

 

四,日志的配置

这个放到你的Cpp文件中顶部。
#include<android/log.h>
#define  LOG_TAG    "nativeprint"
#define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOGD(...)  __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOGE(...)  __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__


      build.gradle

  defaultConfig {
        applicationId "com.cwj.ndkc"
        minSdkVersion 24
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        externalNativeBuild {
            cmake {
                cppFlags " "
            }
            ndk {
                // Specifies the ABI configurations of your native
                // libraries Gradle should build and package with your APK.
//                abiFilters 'x86', 'x86_64', 'armeabi', 'armeabi-v7a',
//                               'arm64-v8a'

                ldLibs "log"
            }

        }

使用:      __android_log_print(ANDROID_LOG_INFO,"日志",  "aa");

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android JNI Java/C++互相调用 的相关文章

  • Java 的 QP 求解器 [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 如何查看Android Asset资源?

    我想检查 assets 文件夹中是否存在文件 我怎样才能做到呢 请帮忙 我向我的应用程序类之一添加了一个辅助方法 我假设 应用程序运行时 资产列表不会更改 the List
  • 如何自定义JProgressBar?

    我正在制作一个启动器 我想要一个自定义的进度栏 我已经做了一些研究 并且可以使用 JavaFX 从未用它做过任何事情 并且可以通过替换 UI 来实现 我正在寻找一个具有圆形边缘和圆形填充的酒吧 像这样的事情 package gui impo
  • 使用 Asp.Net 的 GCM 推送通知

    正如您可能已经看到的 Google 正在迁移其推送通知系统 http developer android com guide google gcm c2dm html http developer android com guide goo
  • 将样式应用于警报对话框

    我决定尝试材质警报dialogs https material io develop android components dialog 在安卓上 我遇到的问题是当我尝试应用某些样式时 检查文档 我发现了这个
  • Android 设备 ID(不是 IMEI)

    我使用命令 adb devices 列出连接的设备 在我的电脑上我得到 附加设备列表 HT9CTP820988 器件 我的问题是 如何以编程方式获取此 id HT9CTP820988 你所看到的adb devices命令是序列号 序列号 创
  • 如何使用 Java 原生接口从 Java 调用 Go 函数?

    可以通过以下方式调用 C 方法JNA https en wikipedia org wiki Java Native AccessJava 中的接口 如何使用 Go 实现相同的功能 package main import fmt impor
  • Java String.format 向整数添加空格

    我有一小段代码 我不明白输出 此输出向我的字符串格式文本添加空格 我做错了什么吗 public class HelloWorld public static void main String args int a1 540 int a2 4
  • .class 与 .java

    class 文件和 java 文件有什么区别 我正在尝试让我的小程序工作 但目前我只能在 Eclipse 中运行它 还不能嵌入 HTML 谢谢 编辑 那么如何使用 JVM 进行编译呢 class 文件是编译后的 java 文件 java 都
  • 使用 IntelliJ / Android Studio 调试基于 gradle 的单元测试

    我正在使用robolectric gradle 插件 https github com robolectric robolectric gradle plugin为 Android 编写单元测试 到目前为止 除了能够使用 Android S
  • 如何在高速缓存中存储图像

    我对此完全空白 我想从 URL 下载图像 并且必须将其存储在内部 以便下次我不需要连接到网络 而是从缓存中检索它 但我不知道该怎么做 谁能帮我提供一个代码片段 import java io BufferedInputStream impor
  • @TestPropertySource 不适用于 Spring 1.2.6 中使用 AnnotationConfigContextLoader 的 JUnit 测试

    似乎我在 Spring 4 1 17 中使用 Spring Boot 1 2 6 RELEASE 所做的任何事情都不起作用 我只想访问应用程序属性并在必要时通过测试覆盖它们 无需使用 hack 手动注入 PropertySource 这不行
  • 有没有办法模拟小部件或屏幕特定位置的触摸?

    我想触摸或点击小部件上的某处 而不让用户在此时明确触摸屏幕 有什么办法可以做到吗 我已经检查了SO答案 有些人建议使用 集成测试 但在未物理或以某种方式连接到笔记本电脑的设备上无法执行 集成测试 无法找到更好的措辞 我还尝试进行 hitTe
  • 为什么在尝试使用 Java 连接到 RDS PostgreSQL 数据库时会收到 SocketTimeoutException?

    我有一个 Spring 应用程序 我试图在 AWS 上托管 几天来我一直在努力配置 我有一个 EC2 实例 并且能够通过 SSH 连接到它 我还在 AWS 中设置了 Postgres RDS 数据库 但我无法使用 IDE 中的代码连接到它
  • Mule/码头设置

    我有一个正在运行的 Mule 应用程序 我想在其上设置 Jetty 来响应 http 请求 以下配置
  • 使用 Maven 3 时 Cobertura 代码覆盖率为 0%

    读完这篇文章后 将 Cobertura 与 Maven 3 0 2 一起使用的正确方法是什么 https stackoverflow com questions 6931360 what is the proper way to use c
  • 无法读取解析推送通知包数据

    我尝试使用 Parse 推送通知服务发送自定义数据 但从 Bundle 中提取时总是返回 null 值 自定义广播接收器 Override public void onReceive Context context Intent inten
  • ActionBar 中的进度条

    我正在使用一个应用程序 它将在应用程序内部加载一个网站 现在我想在操作栏中添加一个进度栏 而无需向上滑动来抑制功能 像那样 我在用Fragment在我的应用程序中 WebviewFragment public class WebviewFr
  • 如何更改焦点/按下时图像按钮的色调

    我有一个ImageButton在我的应用程序中 当按钮打开时我需要更改图像的色调pressed focused 我有ImageButton设置为获取其src来自 XML 文件 如下所示
  • 监控 Java 应用程序上的锁争用

    我正在尝试创建一个小基准 在 Groovy 中 以显示几个同步方法上的高线程争用 当监控自愿上下文切换时 应该会出现高争用 在 Linux 中 这可以通过 pidstat 来实现 程序如下 class Res private int n s

随机推荐

  • HAL_UART_IRQHandler(UART_HandleTypeDef *huart)里面的中断接收函数(作者自己生成的函数代码,中间有关闭接收中断,但是原子教程中没有关闭中断的语句注意区别)

    前言 1 UART Receive IT 2 HAL UART Receive 3 HAL UART Receive IT 前言 看了很长时间串口中断的HAL库 xff0c 最容易混淆的就是函数的名称 xff0c 主要集中在UART Rec
  • STM32 HAL库串口发送函数HAL_UART_Transmit()分析

    STM32 HAL库串口发送函数HAL UART Transmit 分析 硬件平台 xff1a STM32F103VET6 软件平台 xff1a STM32CubeMX 4 22 MDK 5 23 HAL库版本 xff1a FW F1 V1
  • 我在STM32单片机上跑神经网络算法

    01 前言 为什么可以在STM32上面跑神经网络 xff1f 简而言之就是使用STM32CubeMX中的X Cube AI扩展包将当前比较热门的AI框架进行C代码的转化 xff0c 以支持在嵌入式设备上使用 目前使用X Cube AI需要在
  • slambook2+ch7+orb_self 源码的一点小问题

    slambook2 43 ch7 43 orb self 源码的一点小问题 43 解读 源码详细解读小错误调试 xff0c 有的真的属实自己菜运行结果 源码详细解读 下面是一些个人的见解内联代码片 span class token comm
  • 运行相机与vins_Fusion

    安装相机的SDK git clone https github com slightech MYNT EYE D SDK git cd MYNT EYE D SDK make init make all 这里由于没有添加依赖 xff0c O
  • 无刷无霍尔BLCD电机控制

    声明 xff1a 本文出自百度文库无刷无霍尔电机控制 xff0c 因为该文为繁体 xff0c 看起来特别别扭 xff0c 特此翻译 文库网址 xff1a https wenku baidu com view b99217dca0116c17
  • stl的中常用几个容器的介绍与特点。

    lt 1 gt vector容器 vector容器是一个动态数组的结构 xff0c 在内存中有一个指针指向一块连续的内存 类似数组结构一样 它的特点支持随机访问数据 xff0c 因为其在内存中的单元是连续 如此之外 xff0c 还可以vec
  • 关闭优化选项

    这里没有调用拷贝构造函数 xff0c 按照C 43 43 机制 xff0c 应该是会调用的 想起来 xff0c 以前最初写拷贝构造函数的时候也是跟预想的调用不一致 记得编译器会自动优化掉临时对象的 比如 在一个函数中 return list
  • WIFI学习一(socket介绍)

    一 什么是socket socket译为 插座 xff0c 在计算机通信领域 xff0c socket被翻译为 套接字 xff0c 它是计算机之间进行通信的一种约定或一种方式 通过这种方式 xff0c 一台计算机可以接受其他计算机的数据 x
  • 两台电脑实现串口通信

    本文主要介绍串口传输文件的练习 将两台笔记本电脑 xff0c 借助 usb转rs232 模块和杜邦线 xff0c 建立起串口连接 然后用串口助手等工具软件 xff08 带文件传输功能 xff09 将一台笔记本上的一个大文件 xff08 图片
  • VScode前进和后退按钮,非快捷键

    在网上找了半天 xff0c 不喜欢用快捷键 xff0c 喜欢鼠标点击 xff0c 费了好长时间发现这个插件 Back amp Forth xff0c 安装后可以在右上角出现前进和后退按钮 xff0c 如下图
  • Nonce验证

    验证可能会涉及 span class token keyword def span span class token function getNonce span span class token punctuation span span
  • DJI飞行器 精准降落功能测试

    概述 xff1a 该功能仅在自动返航至起飞点 Auto RTL 时生效 xff0c 飞行器降落环境需要足够的照明和没有障碍物的区域 使用该功能后 xff0c 飞行器将使用底部的两个视觉传感器记录起飞时的地形纹理信息 xff0c 并根据记录的
  • 带学生参加电赛,5个国一,2个国二!15个省奖!

    大家好 xff0c 我是张巧龙 xff0c 转眼21年的各省电赛就结束了 xff0c 今年的电赛确实让人难忘 xff0c 不管是题目还是比赛形式 xff0c 亦或是比赛时间一拖再拖 国赛结果也在前段时间公示了 xff0c 参与人数再次增长
  • 【JAVA基础篇】内部类

    定义在一个类内部的类称为内部类 内部类访问权限可以是public protected default或private xff0c 可以声明为abstract供其他内部类或外部类继承 xff0c 可以声明为static final xff0c
  • CURL 是什么

    cURL是一个利用URL语法在命令行下工作的文件传输工具 xff0c 1997年首次发行 它支持文件上传和下载 xff0c 所以是综合传输工具 xff0c 但按传统 xff0c 习惯称cURL为下载工具 cURL还包含了用于程序开发的lib
  • STM32F103C8T6 gps串口数据处理

    基于stm32f10x系列单片机demo程序修改 配置串口 void USART1 Config void GPIO InitTypeDef GPIO InitStructure USART InitTypeDef USART InitSt
  • RS-485总线布线规则及方法

    摘要 xff1a 本文阐述了RS 485双向串行总线的特点 RS 485总线在实际应用中的布线规则 拓扑结构和匹配电阻的连接方法 可供有关技术人员在RS 485总线设计和施工时做参考 关键词 xff1a RS 485 总线 规则 方法 前言
  • jetson nano 基础设置

    关闭图像界面 span class token function sudo span systemctl set default multi user target 开启图像界面 span class token function sudo
  • Android JNI Java/C++互相调用

    一 xff0c Java 调用 C 1 xff0c 首先我们创建一个文件名字叫做 xff0c JNI 其实你不创建也行 看自己 public class JNI 加载本地C语言文件库 库名字为你写的C语言文件名 static System