Cant get the correct filepath from FileDialog in Android
-
wrote on 19 Jun 2020, 13:25 last edited by Amanda1102
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?
-
wrote on 20 Jun 2020, 07:40 last edited by Quang Phu
@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);
-
wrote on 22 Jun 2020, 12:38 last edited by
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.
-
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.
@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?
-
wrote on 25 Jun 2020, 14:37 last edited by
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!
-
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!
@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 -
wrote on 3 Sept 2021, 16:27 last edited by
Using java to solve this problem is very weird.
Isn't there a true Qt/QML solution?