QStandardPaths & Android
-
Hell everyone,
I have some trouble with crossplatform file management.
In my app, I create a temporary pdf and I want to attach it to the native E-Mail programm.
I'm using this code for the file location:
QString filePath = QStandardPaths::writableLocation(QStandardPaths::TempLocation) + "/" + name + "."+ extension;
It works fine in Ios, but in Android this results in
/data/user/0/myApp/cache/name.pdf
, and I'm unable to attach the file to the E-Mail programm.
If I use a fixed hardcoded path, lets say/sdcard/Download/name.pdf
the file is attached properly.My guess is, that
QStandardPaths::writableLocation(QStandardPaths::TempLocation)
is not a readable location for external programms, under Android?Is there a StandardPath that would allow this ?
-
So I ended up with the following solution, because @VRonin link/example is really extensive and, so do I feel at least, overkill.
void EmailPopup::showEmailPopup(QString receiver, QString extension) { #if defined(Q_OS_IOS) QString filePath = QStandardPaths::writableLocation(QStandardPaths::TempLocation) + "/" + extension + "."+ extension; _impl->showEmail(receiver.toLatin1().data(), filePath.toLatin1().data()); #elif defined(Q_OS_ANDROID) QtAndroid::requestPermissions(QStringList("android.permission.WRITE_EXTERNAL_STORAGE"), [this, receiver, extension](QtAndroid::PermissionResultMap resultHash){ if(resultHash["android.permission.WRITE_EXTERNAL_STORAGE"] == QtAndroid::PermissionResult::Granted){ QString filePath = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation) + "/" + extension + "."+ extension; QAndroidJniObject javaFilenameStr = QAndroidJniObject::fromString(filePath); QAndroidJniObject javaSendToStr = QAndroidJniObject::fromString(receiver); QAndroidJniObject::callStaticMethod<void>("app/email/Mailer","sendMail","(Ljava/lang/String;Ljava/lang/String;)V", javaFilenameStr.object<jstring>(), javaSendToStr.object<jstring>()); }else{ emit errorMessage(tr("Sending E-Mails with attachment requires permission to write")); } }); #else Q_UNUSED(receiver) Q_UNUSED(extension) #endif }
I decided to use
QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation)
when on Android, thats a path, that allows all apps to access, but requires extra permission.If the user does not grand the permission he/she can not send the pdf file. But it's checked and requested each time he/she tries to send one. In case once mind changes.
Works fine.
-
This is actually explained in a blog post by @ekkescorner : http://blog.qt.io/blog/2017/12/01/sharing-files-android-ios-qt-app/
-
@VRonin thanks, I was not aware of that. Its a rather lengthly post, but I'll read through it.
In the end, I could potentially simply create a folder at /sdcard/MyCompany/MyApp and call it a day. But that doesn't seem very future proof and it would at the very least require external read and write permission.
And I'm hesitant to go that route.
-
So I ended up with the following solution, because @VRonin link/example is really extensive and, so do I feel at least, overkill.
void EmailPopup::showEmailPopup(QString receiver, QString extension) { #if defined(Q_OS_IOS) QString filePath = QStandardPaths::writableLocation(QStandardPaths::TempLocation) + "/" + extension + "."+ extension; _impl->showEmail(receiver.toLatin1().data(), filePath.toLatin1().data()); #elif defined(Q_OS_ANDROID) QtAndroid::requestPermissions(QStringList("android.permission.WRITE_EXTERNAL_STORAGE"), [this, receiver, extension](QtAndroid::PermissionResultMap resultHash){ if(resultHash["android.permission.WRITE_EXTERNAL_STORAGE"] == QtAndroid::PermissionResult::Granted){ QString filePath = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation) + "/" + extension + "."+ extension; QAndroidJniObject javaFilenameStr = QAndroidJniObject::fromString(filePath); QAndroidJniObject javaSendToStr = QAndroidJniObject::fromString(receiver); QAndroidJniObject::callStaticMethod<void>("app/email/Mailer","sendMail","(Ljava/lang/String;Ljava/lang/String;)V", javaFilenameStr.object<jstring>(), javaSendToStr.object<jstring>()); }else{ emit errorMessage(tr("Sending E-Mails with attachment requires permission to write")); } }); #else Q_UNUSED(receiver) Q_UNUSED(extension) #endif }
I decided to use
QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation)
when on Android, thats a path, that allows all apps to access, but requires extra permission.If the user does not grand the permission he/she can not send the pdf file. But it's checked and requested each time he/she tries to send one. In case once mind changes.
Works fine.