当前位置: 首页 > article >正文

Qt for android : 简单实现弹窗创建文件,并使用JNI进行读写实例

简介

Qt版本 : Qt6.6.2
手机: RedMi 7A
本例使用JNI方式打开窗体创建文件, handleActivityResult中处理创建文件之后通过InputStream/OutputStream简单读写文件

代码

项目添加

QT += core-private

头文件

代码来之参考中的连接, 稍微修改
需要注意的是 QAndroidActivityResultReceiver, 继承之后可以接收startActivity执行之后的返回结果,handleActivityResult槽中处理结果

#ifndef HARDWAREUTILS_ANDROID_H
#define HARDWAREUTILS_ANDROID_H

#include "private/qandroidextras_p.h"
#include "qjniobject.h"
#include <QObject>
#include <QJniObject>
#include <QJniEnvironment>
#include <QFile>

class HardwareUtilsAndroid: public QObject, public QAndroidActivityResultReceiver
{
private:
    HardwareUtilsAndroid(QObject *parent = 0);

public:
    virtual ~HardwareUtilsAndroid();
    static HardwareUtilsAndroid* Instance(QObject *parent = 0);

    virtual void handleActivityResult(int receiverRequestCode, int resultCode, const QJniObject & data);
    virtual bool writeOnUSB(QString filename);

private:
    void writeFile(QJniObject &fileUri, const QString &text);
    void readFile(QJniObject &fileUri, QString &text);

private:
    QFile m_file;
};

#endif // HARDWAREUTILS_ANDROID_H

源文件


#include "HardwareUtils_Android.h"
#include <jni.h>

#include <QDebug>

HardwareUtilsAndroid *HardwareUtilsAndroid::Instance(QObject *parent) {
    static HardwareUtilsAndroid *instance = NULL;

    if(!instance) {
        instance = new HardwareUtilsAndroid(parent);
    }

    return instance;
}

HardwareUtilsAndroid::HardwareUtilsAndroid(QObject *parent):
    QObject(parent)
{
}

HardwareUtilsAndroid::~HardwareUtilsAndroid()
{
}

bool HardwareUtilsAndroid::writeOnUSB(QString filename) 
{
    QJniObject ACTION_CREATE_DOCUMENT = QJniObject::fromString("android.intent.action.CREATE_DOCUMENT");
    QJniObject intent("android/content/Intent");
    if (ACTION_CREATE_DOCUMENT.isValid() && intent.isValid()) 
    {
        intent.callObjectMethod("setAction", "(Ljava/lang/String;)Landroid/content/Intent;", ACTION_CREATE_DOCUMENT.object<jstring>());
        intent.callObjectMethod("setType", "(Ljava/lang/String;)Landroid/content/Intent;", QJniObject::fromString("text/plain").object<jstring>());
        intent.callObjectMethod("putExtra", "(Ljava/lang/String;Ljava/lang/String;)Landroid/content/Intent;",
                                QJniObject::fromString("android.intent.extra.TITLE").object<jstring>(),
                                QJniObject::fromString(filename).object<jstring>());

        QtAndroidPrivate::startActivity(intent.object<jobject>(), 123, this);
        return true;
    } 
    else 
    {
        return false;
    }
}

void HardwareUtilsAndroid::writeFile(QJniObject &fileUri, const QString &text)
{
    // 获取文件输出流
    QJniObject activity = QtAndroidPrivate::activity();
    QJniObject contentResolver = activity.callObjectMethod("getContentResolver", 
                                                           "()Landroid/content/ContentResolver;");
    QJniObject outputStream = contentResolver.callObjectMethod("openOutputStream", 
                                                               "(Landroid/net/Uri;)Ljava/io/OutputStream;",
                                                               fileUri.object<jobject>());

    if (outputStream.isValid())
    {
        QJniObject stringToWrite = QJniObject::fromString(text);
        QJniObject bytes = stringToWrite.callObjectMethod("getBytes", "()[B");

        QJniEnvironment env;
        jbyteArray byteArray = static_cast<jbyteArray>(bytes.object<jarray>());
        jbyte* byteData = env->GetByteArrayElements(byteArray, nullptr);
        int length = env->GetArrayLength(byteArray);

        outputStream.callMethod<void>("write", "([B)V", byteArray);
        env->ReleaseByteArrayElements(byteArray, byteData, 0);

        outputStream.callMethod<void>("close", "()V");
        qDebug() << "File written successfully";
    }
    else
    {
        qDebug() << "Failed to open output stream";
    }
}

void HardwareUtilsAndroid::readFile(QJniObject &fileUri, QString &text)
{
    QJniEnvironment env;
    QJniObject activity = QtAndroidPrivate::activity();
    QJniObject contentResolver = activity.callObjectMethod("getContentResolver", 
                                                           "()Landroid/content/ContentResolver;");

    // 创建InputStream
    QJniObject inputStream = contentResolver.callObjectMethod("openInputStream", 
                                                              "(Landroid/net/Uri;)Ljava/io/InputStream;", fileUri.object<jobject>());

    // 创建缓冲区
    jbyteArray bufferArray = env->NewByteArray(1024);

    // 读取数据
    QByteArray fileData;
    jint bytesRead;
    while ((bytesRead = inputStream.callMethod<jint>("read", "([B)I", bufferArray)) != -1) 
    {
        jbyte* buffer = env->GetByteArrayElements(bufferArray, nullptr);
        fileData.append(reinterpret_cast<const char*>(buffer), bytesRead);
        env->ReleaseByteArrayElements(bufferArray, buffer, JNI_ABORT);
    }

    // 关闭流
    if (inputStream.isValid()) 
    {
        inputStream.callMethod<void>("close", "()V");
        if (env->ExceptionCheck()) 
        {
            env->ExceptionClear();
        }
    }

    text = QString::fromUtf8(fileData);
    // 删除局部引用
    env->DeleteLocalRef(bufferArray);
}

void HardwareUtilsAndroid::handleActivityResult(int receiverRequestCode, int resultCode, const QJniObject & data) 
{
    qDebug() << "Receive activity result";

    jint RESULT_OK = QJniObject::getStaticField<jint>("android/app/Activity", "RESULT_OK");
    if (receiverRequestCode == 123 && resultCode == RESULT_OK)
    {
        QJniObject uri = data.callObjectMethod("getData", "()Landroid/net/Uri;");
        if (!uri.isValid())
        {
            qDebug() << "Invalid URI";
            return;
        }

        QString text;
        writeFile(uri, QString("hello world!!!!"));
        readFile(uri, text);
        qDebug() << "read: " << text;
    }
    else
    {
        qDebug() << "Failed to create file";
    }
}

调用

可以搭配QFileDialog进行使用,打开U盘的路径创建文件

HardwareUtilsAndroid::Instance()->writeOnUSB(dlg.selectedFiles().value(0));

参考:
https://github.com/jbflamant/android-usb-access


http://www.kler.cn/a/501265.html

相关文章:

  • 典型的 package.json 文件中的
  • 解读若依微服务架构图:架构总览、核心模块解析、消息与任务处理、数据存储与缓存、监控与日志
  • Wireshark使用
  • OpenCV基础:视频的采集、读取与录制
  • 【Python进阶——分布式计算框架pyspark】
  • 【C++】字符串中的 insert 方法深层分析
  • LeetCode 225: 用队列实现栈
  • 每日学习30分轻松掌握CursorAI:多文件编辑与Composer功能
  • OpenGL利用DDA算法绘制图形,并增加鼠标键盘交互
  • VUE3 监听器(watch)
  • 卷积神经网络:过滤器为啥被叫作“核”
  • 内网服务器添加共享文件夹功能并设置端口映射
  • 【YOLOv5】源码(train.py)
  • 红队攻防 | 凭证获取的10个方法
  • 云计算-操作系统介绍
  • 我这不需要保留本地修改, 只需要拉取远程更改
  • Vue2: el-table为每一行添加超链接,并实现光标移至文字上时改变形状
  • 如何快速准备数学建模?
  • 代码随想录day13| 二叉树理论基础| 递归遍历|迭代遍历| 统一迭代 |层序遍历
  • 第25章 汇编语言--- 信号量与互斥锁
  • 什么是数据分析?
  • asp.net core webapi 并发请求时 怎么保证实时获取的用户信息是此次请求的?
  • 【网络安全 | 漏洞挖掘】通过监控调试模式实现价值$15k的RCE
  • 基于单片机的粮仓环境监测系统设计
  • 第32天:Web开发-PHP应用文件操作安全上传下载任意读取删除目录遍历文件包含
  • SpringCloud:gateway分发服务报302,Network Error