Qt for Android之QJniObject

Qt for Android之QJniObject

  • 项目构成
  • C++传值给Java
  • C++获取JAVA中的值
  • 实例:获取手机型号
  • 源码及参考

Qt6中,取消了androidextras模块,所以在.pro文件中无需添加QT += androidextras。同时,QAndroidJniObject和QAndroidJniEnvironment被QJniObject和QJniEnvironment取代。但是用法是相似的。此文的例子,是使用QJniObject,把C++的值传送给JAVA,C++主动获取JAVA的值。关于JAVA如何主动推送信息给C++,参考QT for android 获取PDA扫码的广播数据。

项目构成

Qt for Android之QJniObject_第1张图片
笔者没有使用QML,所以例子中也没有C++和QML通信的部分。新建Qt Widgets Application,Kit选Android Qt 6.2.4 Clang armeabi-v7a。新建之后,添加AndroidManifest.xml文件,包名是默认的ort.qtproject.example,这个文件无需更改。然后在android文件夹下面依次新建src->org->qtproject->example文件夹,添加JTest.java文件到example文件夹下。

C++传值给Java

这个过程相对简单,JTest.java文件如下:

package org.qtproject.example;
public class JTest {
    public JTest() {}
    public static void printFromJava(String x){
        System.out.println(x);
        }
}

第一行引入包名,就是在AndroidManifest.xml文件中的包名,要对应。
笔者在MainWindow.ui中拖入一个QPushButton,在这个按钮的槽下面添加:

QString message = "this is from c++";
QJniObject javaMessage = QJniObject::fromString(message);
QJniObject::callStaticMethod<void>("org/qtproject/example/JTest",//注1
                                   "printFromJava",//注2
                                   "(Ljava/lang/String;)V",//注3
                                   javaMessage.object<jstring>());

注1:包名和JAVA文件名,要替换成自己的;
注2:调用的JAVA中的方法名;
注3:签名,为什么长这个样子,参考其他文章吧。

运行之后点击按钮就能看到输出了:
在这里插入图片描述

C++获取JAVA中的值

还是刚才的例子,这里用到了QJniEnvironment,先看JAVA文件:

package org.qtproject.example;
import java.lang.reflect.Method;

public class JTest {
    private static native void callFromJava(String message);//注1
    public JTest() {}
    public static void printFromJava(String x){
        System.out.println(x);
        callFromJava("Hello from Java!");//注2
        }
}

JAVA文件中就添加了两行,一行声明,一行写传送的值。

mainwindow.h文件

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include 

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    static MainWindow *instance() {return m_instance;}//注1
private slots:
    void printMesFromJava(QString);//注2
    void on_pushButton_clicked();//注3
signals:
    void signalMesFromJava(const QString &message);//注4
private:
    Ui::MainWindow *ui;
    static MainWindow *m_instance;//注5
};
#endif // MAINWINDOW_H

注1和注5,两个配合使用,用于接收从JAVA获取的值;
注2和注4:信号和槽,用于把JAVA获取到的值输出。

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include 

MainWindow *MainWindow::m_instance = nullptr;//注1
static void callFromJava(JNIEnv *env, jobject /*thiz*/, jstring value)//注2
{
    emit MainWindow::instance()->signalMesFromJava(env->GetStringUTFChars(value, nullptr));
}

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    connect(this, &MainWindow::signalMesFromJava, this, &MainWindow::printMesFromJava);//注3
    m_instance = this;
    JNINativeMethod methods[] {{"callFromJava", "(Ljava/lang/String;)V", reinterpret_cast<void *>(callFromJava)}};//注4
    QJniObject javaClass("org/qtproject/example/JTest");
    QJniEnvironment env;
    jclass objectClass = env->GetObjectClass(javaClass.object<jobject>());
    env->RegisterNatives(objectClass,//注5
                         methods,
                         sizeof(methods) / sizeof(methods[0]));
    env->DeleteLocalRef(objectClass);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_pushButton_clicked()
{
    QString message = "this is from c++";
    QJniObject javaMessage = QJniObject::fromString(message);
    QJniObject::callStaticMethod<void>("org/qtproject/example/JTest",
                                       "printFromJava",
                                       "(Ljava/lang/String;)V",
                                       javaMessage.object<jstring>());
}

void MainWindow::printMesFromJava(QString mes)//注6
{
    qDebug()<<"C++:MES FROM JAVA: "<<mes;
}

开头要引入:#include < QJniObject >
注1和注2:这两行要写在构造函数的前面,注3是连接信号槽。
注4:引用JAVA文件中的方法,注5:进行注册。
运行之后点击按钮就能看到输出了:
Qt for Android之QJniObject_第2张图片

实例:获取手机型号

还可以获取手机序列号、制造商等,参考Qt for Android获取手机序列号/手机型号/手机制造商。
JTest.java

package org.qtproject.example;
import java.lang.reflect.Method;

public class JTest {
    private static native void callFromJava(String message);
    public JTest() {}
    public static void printFromJava(String x){
        System.out.println(x);
        callFromJava("Hello from Java!");
        }
    public static String getDeviceModel(){
        String mtype = "";
        try {
            mtype = android.os.Build.MODEL;
            }catch (Exception e){
            e.printStackTrace();
            }
        System.out.println("java: " + mtype);
        return mtype;
        }
}

mainwindow.cpp

QJniObject str = QJniObject::callStaticObjectMethod("org/qtproject/example/JTest",
                                                    "getDeviceModel",
                                                    "()Ljava/lang/String;");
qDebug()<<"C++: DeviceModel: "<<str.toString();

注:把这两行添加到按钮的槽下面,运行之后点击按钮输出:
Qt for Android之QJniObject_第3张图片

源码及参考

源码:https://download.csdn.net/download/weixin_43193739/85051756
参考:
Qt for Android获取手机序列号/手机型号/手机制造商

你可能感兴趣的:(Qt,for,Android,QT,android,qml)