QStandardPaths & Android

  • Moderators

    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 ?

  • Qt Champions 2018

  • Moderators

    @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.

  • Qt Champions 2018

    @J.Hilk Not all smartphones have a SDCard.

  • Moderators

    @jsulm sofar all Android devices refer to the internal solid state memory as "sdcard", confused the hell out of me before too. => /sdcard/ has existed an all the devices I had since 2012

  • Qt Champions 2018

    @J.Hilk OK, good to know

  • Moderators

    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>());
                emit errorMessage(tr("Sending E-Mails with attachment requires permission to write"));

    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.

Log in to reply

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.