Android开发——JNI

Android开发——JNI

一、什么是JNI

JNI全称为java native interface(java本地开发接口)

作用:相当于桥梁的作用,是一种协议

通过JNI就可以让java调用C语言

在这里插入图片描述

Android系统架构:

在这里插入图片描述

二、JNI基础应用

2.1JNI数据类型对照表

Java类型JNI别名本地类型
booleanjbooleanunsigned char
bytejbytesigned char
charjcharunsigned short
shortjshortshort
intjintint
longjlonglong long
floatjfloatfloat
doublejdoubledouble

2.2C++调用Java方法

2.2.1Java中调用

语法:

权限修饰符 native 返回值类型 方法名();

示例:

public native String stringFromJNI();
2.2.2C++中实现

语法:

  • JNIEnvJNI工具类
  • jobject:调用此方法的Java类实例
extern "c" JNIEXPORT 返回类型(使用JNI类型) JNICALL Java_全类名_方法名(类名方法名之间使用下划线分隔)(JNIEnv *env, jobject thiz){}

示例:

extern "C" JNIEXPORT jstring JNICALL
Java_com_lxc_jnitest1_MainActivity_helloC(JNIEnv *env, jobject thiz) {
    return env->NewStringUTF("hello word");
}
2.2.3运行结果

在这里插入图片描述

2.3C++调用Java方法

  • 使用Java方法调用C++函数,在C++函数中调用Java方法
2.3.1创建Java方法
    /**
     * 运行Test1Method();
     */
    public native void runTest1();

    /**
     * 运行Test2Method();
     */
    public native void runTest2();

    public void Test1Method(){
        Log.d(TAG, "test1 is runing");
    }

    public int Test2Method(int a, int b){
        return a+b;
    }
2.3.2生成头文件
  • jdk10之后javah命令已经被删除
  • 进入所在类目录中使用命令:javac -h c 类名.java

在这里插入图片描述

此错误是因为javac在编译时找不到android.util.Log包导致的

解决:将代码中的相关代码注释掉,重新编译成功后再打开注释

  • 注释代码,再次编译
  • 此时,会生成对应java文件的class字节码文件和c目录下的头文件

在这里插入图片描述

  • 将头文件移到cpp文件夹中,并删除编译的class文件

在这里插入图片描述

2.3.3编写C++代码
  • 在cpp文件中引入生成的头文件
  • 实现runTest1runTest2的方法
  • 调用Java方法具体步骤
    • 获取Java字节码
      • 使用env->FindClass();方法
      • 参数:需要调用的方法所在类的全限定类名,其中./代替
    • 获取要执行的方法
      • 使用env->GetMethodID();
      • 参数一:第一步获取的Java类字节码
      • 参数二:方法名
      • 参数三:签名——详情
    • 实例化对象
      • 使用env->AllocObject():
      • 参数:第一步获取的Java类字节码
    • 执行方法
      • 使用env->CallxxxxMethod();方法,根据要调用的方法的返回值所定
      • 参数一:实例化对象
      • 参数二:获取到的方法jmethodID

完整C++源码:

#include <jni.h>
#include "com_lxc_jnitest1_JNITest.h"
#include <string>
#include <android/log.h>

using namespace std;

const string TAG = "hello.cpp";

extern "C" JNIEXPORT void JNICALL
Java_com_lxc_jnitest1_JNITest_runTest1(JNIEnv *env, jobject) {
    //获取字节码
    jclass jclazz = env->FindClass("com/lxc/jnitest1/JNITest");
    //获取方法
    jmethodID  jmethodId = env->GetMethodID(jclazz, "Test1Method", "()V");
    //实例化对象
    jobject  jobj = env->AllocObject(jclazz);
    //执行方法
    env->CallVoidMethod(jobj, jmethodId);
};

extern "C" JNIEXPORT void JNICALL
Java_com_lxc_jnitest1_JNITest_runTest2 (JNIEnv* env, jobject){
    //获取字节码
    jclass jclazz = env->FindClass("com/lxc/jnitest1/JNITest");
    //获取方法
    jmethodID  jmethodId = env->GetMethodID(jclazz, "Test2Method", "(II)I");
    //实例化对象
    jobject  jobj = env->AllocObject(jclazz);
    //执行方法
    jint value = env->CallIntMethod(jobj, jmethodId, 18, 20);
    //打印
    __android_log_write(ANDROID_LOG_DEBUG, TAG.c_str(), ("value is "+to_string(value)).c_str());
};
2.3.4调用静态方法
extern "C" JNIEXPORT void JNICALL
Java_com_lxc_jnitest1_JNITest_runTest3(JNIEnv * env, jobject){
    //获取字节码
    jclass jclazz = env->FindClass("com/lxc/jnitest1/JNITest");
    //获取静态方法
    jmethodID jmethodId = env->GetStaticMethodID(jclazz, "Test3Method", "(Ljava/lang/String;)V");
    //执行静态方法
    env->CallStaticVoidMethod(jclazz, jmethodId, env->NewStringUTF("hello world"));
};
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陌尘吖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值