前言
用Qt开发安卓免不了需要调用底层的代码,也就是调用java功能函数,这就用到了JNI了。
JNI基础知识点
关键词native
native关键字说明其修饰的方法是一个原生态方法,方法对应的实现不是在当前文件(即只在此处声明),而是在用其他语言(如C和C++)实现的文件中。Java语言本身不能对操作系统底层进行访问和操作,但是可以通过JNI接口调用其他语言来实现对底层的访问。
jobject、 jclass
通过看名字就可猜想到:jclass 为类本身,jobject为类实例,
总的来说:
- 当Java中定义的native方法为静态方法时,则第二个参数为jclass,jclass代表native方法所属类的class本身
- 当Java中定义的native方法为非静态方法时,则第二个参数为jobject,jobject代表native方法所属类的实例对象
具体可看下面文章了解:
JNI/NDK入门指南之jobject和jclass_jni jobject_IT先森的博客-CSDN博客
JNIEnv
JNIEnv是提供JNI Native函数的基础环境,线程相关,不同线程的JNIEnv相互独立,并且JNIEnv是一个JNI接口指针,指向了本地方法的一个函数表,该函数表中的每一个成员指向了一个JNI函数,本地方法通过JNI函数来访问JVM中的数据结构。
具体可看下面文章了解:
JNI/NDK入门指南之JavaVM和JNIEnv_javavm jni_IT先森的博客-CSDN博客
JNINativeMethod
JNINativeMethod 该结构体用于描述需要注册的JNI native方法信息。 在注册函数表JNIEnv::RegisterNatives里传入。
jint RegisterNatives(jclass clazz, const JNINativeMethod* methods,jint nMethods)
具体看下面文章,学习使用:
JNI 之 JNINativeMethod——安卓_十年之少的博客-CSDN博客
使用
pro文件
QT += androidextras
java调用C++
java代码中定义native方法
package org.qtproject.example.jnimessenger;public class JniMessenger
{//用 native 声明的方法表示告知 JVM 调用,该方法在外部定义,一个native Method就是一个 Java 调用非 Java 代码的接口。private static native void callFromJava(String message);public JniMessenger() {}public static void printFromJava(String message){System.out.println("This is printed from JAVA, message is: " + message);//这里调用了native方法(外部实现的)callFromJava("Hello from JAVA!");}
}
在c++中实现:这里是 调用了c++ JniMessenger 实例发射信号messageFromJava,入参value传入了信号。C++中定义的实现都是这种格式
static 【return】 funcName (JNIEnv *env, jclass ,【arg1,arg2 ...】) 或者
【return】 funcName (JNIEnv *env, jobject,【arg1,arg2 ...】)
JniMessenger *JniMessenger::m_instance = nullptr;static void callFromJava(JNIEnv *env, jclass /*thiz*/, jstring value){emit JniMessenger::instance()->messageFromJava(env->GetStringUTFChars(value, nullptr));
}
jstring 转为 char*
上面是用C++实现了callFromJava,但是要想与java中的关联起来,还需要将此函数指针在JNIEnv中注册,上面基础知识中说过“JNIEnv是一个JNI接口指针,指向了本地方法的一个函数表,”,我们需要做的将此函数,注册到此函数表中
JniMessenger::JniMessenger(QObject *parent) : QObject(parent)
{m_instance = this;//c++ 本地定义的 jni native方法JNINativeMethod methods[] {{"callFromJava", "(Ljava/lang/String;)V", reinterpret_cast<void *>(callFromJava)}};QAndroidJniObject javaClass("org/qtproject/example/jnimessenger/JniMessenger");//注册QAndroidJniEnvironment env;jclass objectClass = env->GetObjectClass(javaClass.object<jobject>());env->RegisterNatives(objectClass,methods,sizeof(methods) / sizeof(methods[0]));//释放内存env->DeleteLocalRef(objectClass);
}
C++调用java
c++ 调用java函数比较简单,如下
静态函数示例:
void JniMessenger::printFromJava(const QString &message)
{QAndroidJniObject javaMessage = QAndroidJniObject::fromString(message);QAndroidJniObject::callStaticMethod<void>("org/qtproject/example/jnimessenger/JniMessenger", //类名"printFromJava",//函数名"(Ljava/lang/String;)V",//(参数类型)返回类型javaMessage.object<jstring>());//传入参数
}
普通函数示例(假如java中定义的printFromJava是普通函数):
void JniMessenger::printFromJava(const QString &message)
{QAndroidJniObject javaMessage = QAndroidJniObject::fromString(message);QAndroidJniObject javaClass("org/qtproject/example/jnimessenger/JniMessenger");javaClass.callObjectMethod("printFromJava","(Ljava/lang/String;)V",javaMessage.object<jstring>());
}
结束语
这只是个开始,若是想玩转安卓,还是得学习或了解整套框架。
本文链接:https://my.lmcjl.com/post/1588.html
4 评论