用Qt开发安卓免不了需要调用底层的代码,也就是调用java功能函数,这就用到了JNI了。
native关键字说明其修饰的方法是一个原生态方法,方法对应的实现不是在当前文件(即只在此处声明),而是在用其他语言(如C和C++)实现的文件中。Java语言本身不能对操作系统底层进行访问和操作,但是可以通过JNI接口调用其他语言来实现对底层的访问。
通过看名字就可猜想到:jclass 为类本身,jobject为类实例,
总的来说:
具体可看下面文章了解:
JNI/NDK入门指南之jobject和jclass_jni jobject_IT先森的博客-CSDN博客
JNIEnv是提供JNI Native函数的基础环境,线程相关,不同线程的JNIEnv相互独立,并且JNIEnv是一个JNI接口指针,指向了本地方法的一个函数表,该函数表中的每一个成员指向了一个JNI函数,本地方法通过JNI函数来访问JVM中的数据结构。
具体可看下面文章了解:
JNI/NDK入门指南之JavaVM和JNIEnv_javavm jni_IT先森的博客-CSDN博客
JNINativeMethod 该结构体用于描述需要注册的JNI native方法信息。 在注册函数表JNIEnv::RegisterNatives里传入。
jint RegisterNatives(jclass clazz, const JNINativeMethod* methods,
jint nMethods)
具体看下面文章,学习使用:
JNI 之 JNINativeMethod——安卓_十年之少的博客-CSDN博客
pro文件
QT += androidextras
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*
const char* GetStringUTFChars(jstring string, jboolean* isCopy)
上面是用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(callFromJava)}};
QAndroidJniObject javaClass("org/qtproject/example/jnimessenger/JniMessenger");
//注册
QAndroidJniEnvironment env;
jclass objectClass = env->GetObjectClass(javaClass.object());
env->RegisterNatives(objectClass,
methods,
sizeof(methods) / sizeof(methods[0]));
//释放内存
env->DeleteLocalRef(objectClass);
}
c++ 调用java函数比较简单,如下
静态函数示例:
void JniMessenger::printFromJava(const QString &message)
{
QAndroidJniObject javaMessage = QAndroidJniObject::fromString(message);
QAndroidJniObject::callStaticMethod("org/qtproject/example/jnimessenger/JniMessenger", //类名
"printFromJava",//函数名
"(Ljava/lang/String;)V",//(参数类型)返回类型
javaMessage.object());//传入参数
}
普通函数示例(假如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());
}
这只是个开始,若是想玩转安卓,还是得学习或了解整套框架。