简介
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;");// 创建InputStreamQJniObject 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