Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Cant get the correct filepath from FileDialog in Android



  • I am using FileDialog with qt 5.13.1 to save a file in my application directory. The problem is that the path of the file does not contains the correct name of the file and I need it.

    Here is my qml code

    import QtQuick 2.12
    import QtQuick.Controls 2.12
    import QtQuick.Dialogs 1.2
    
    ApplicationWindow {
        id: mRoot
        visible: true
        width: 400
        height: 300
    
        Button{
            id: mButtonSaveFiles
    
            anchors.centerIn: parent
    
            height: 50
            width: 100
    
            text: "Save File"
    
            onClicked: mFileDialog.open()
        }
    
        FileDialog{
            id: mFileDialog
    
            nameFilters: ["Compressed files(*bz2)"]
    
            onAccepted: mFileManager.saveFile(mFileDialog.fileUrl)
        }
    }
    

    Here is my c++ function:

    
    bool FileManager::saveFile(QString fileUrl) {
      qDebug() << "File url:" << fileUrl;
    
      int start = fileUrl.indexOf(QDir::separator()) + 1;
      int length = fileUrl.length() - start;
      QString filename = fileUrl.mid(start, length);
    
      QFile file(fileUrl);
      if (!file.copy(m_dir.path() + QDir::separator() + filename))
        return false;
    
      return true;
    }
    

    It works just fine in desktop, but in android I am getting this fileUrl:
    "content://com.android.providers.downloads.documents/document/152"

    So my file is being saved as 152, but I need it to be saved with the original name.

    Does anyone know how I can get the correct name?



  • @Amanda1102 ,
    I use this config for 3 platforms:

    #ifdef ANDROID_PLATFORM
        m_currentDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
        qDebug() << "Android writable location ... " + QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
    #elif IOS_PLATFORM
        m_currentDir = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
    #else
        m_currentDir = QDir::currentPath();
    #endif
    

    It's worked well for both C++ and QML. You can try it!
    QFile file(m_currentDir + QDir::separator() + filename);



  • Thank you for your help @Quang-Phu, but that isn't my problem. The problem is that I have a file inside a android directory and I wanna save it inside my app directory, but I am not getting the correct name. For example, my filename is android-file, but I am getting 151 as the name. The thing is that it is using a uri link and I need to get the name of the file based on the uri.


  • Lifetime Qt Champion

    @Amanda1102 said in FileDialog in Android:

    and I wanna save it inside my app directory

    I don't think your app has write access in the directory where it is installed. Why do you want to write there?



  • I did solve the problem partially by creating a java class and calling it from c++. Unfortunally this doesn't work with OneDrive.

    Here is the java code I found in the internet:

    package br.com.myjavapackage;
    
    import android.content.Context;
    import android.database.Cursor;
    import android.net.Uri;
    import android.webkit.MimeTypeMap;
    import android.provider.OpenableColumns;
    
    public class PathUtil {
    
        public static String getFileName(Uri uri, Context context) {
            String fileName = getFileNameFromCursor(uri, context);
    
            if (fileName == null) {
                String fileExtension = getFileExtension(uri, context);
                fileName = "temp_file" + (fileExtension != null ? "." + 
                                                            fileExtension : "");
            } else if (!fileName.contains(".")) {
                String fileExtension = getFileExtension(uri, context);
                fileName = fileName + "." + fileExtension;
            }
    
            return fileName;
        }
    
        public static String getFileExtension(Uri uri, Context context) {
            String fileType = context.getContentResolver().getType(uri);
            return MimeTypeMap.getSingleton().getExtensionFromMimeType(fileType);
        }
    
        public static String getFileNameFromCursor(Uri uri, Context context) {
            Cursor fileCursor = context.getContentResolver().query(uri, new String[] 
                                   {OpenableColumns.DISPLAY_NAME}, null, null, null);
            String fileName = null;
            if (fileCursor != null && fileCursor.moveToFirst()) {
                int cIndex = fileCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
                if (cIndex != -1) {
                    fileName = fileCursor.getString(cIndex);
                }
            }
            return fileName;
        }
    }
    

    Here is the way I call it on my c++ function:

      QAndroidJniObject uri = QAndroidJniObject::callStaticObjectMethod(
          "android/net/Uri", "parse", "(Ljava/lang/String;)Landroid/net/Uri;",
          QAndroidJniObject::fromString(fileUrl).object<jstring>());
    
      QString filename =
          QAndroidJniObject::callStaticObjectMethod(
              "br/com/myjavapackage/PathUtil", "getFileName",
              "(Landroid/net/Uri;Landroid/content/Context;)Ljava/lang/String;",
              uri.object(), QtAndroid::androidContext().object())
              .toString();
    

    I am marking this problem as solved, but if anyone find a better solution please share it!


  • Qt Champions 2016

    @Amanda1102 perhaps you can get some ideas from my share example, where I try to get the file uri from a content uri
    https://github.com/ekke/ekkesSHAREexample/blob/master/android/src/org/ekkescorner/examples/sharex/QShareActivity.java
    https://github.com/ekke/ekkesSHAREexample/blob/master/android/src/org/ekkescorner/utils/QSharePathResolver.java
    don't know if it helps or if it works with OneDrive



  • Using java to solve this problem is very weird.

    Isn't there a true Qt/QML solution?


Log in to reply