Solved Failed to create QFile when deploying to Android device
-
@J.Hilk I added the file.open() command in ReadOnly mode. But this does not help as
if(!file.exists())
request tells me there is no file under directory
/data/user/0/org.qtproject.example.sozius_client/files.Is there a way that my App could access my SD card and manipulate or just read a file from it?
-
Do you mean you want to comparing the content of the certificate itself ?
-
@a_so "request tells me there is no file under directory" - I thought you want to create a file?
"Is there a way that my App could access my SD card and manipulate or just read a file from it?" - yes, using QFile, but you need to do it properly. You need to make sure your app has the rights to write there. -
@jsulm Yes I want to create a file but as this did not work for me I tried to copy a file in the directory and just open and read it .
How do I give my app read/write permissions? I have in my AndroidManifest.xml permissions for "READ_EXTERNAL_STORAGE" and "WRITE_EXTERNAL_STORAGE". I have a 8 GB SanDisk ultra SdCard in my Slot. Does the sdcard need to be formatted in a special way?
-
@a_so You wrote: "if(!file.exists())
request tells me there is no file under directory
/data/user/0/org.qtproject.example.sozius_client/files."
Which file do you expect to be where and who is writing this file to this directory? -
@a_so What API are you using?
23+ Was kinda broken and you had to grand your app the requested permissions manually in the settings of your HardwaredeviceChances are that this is adressed in Qt5.9. But I haven't tested that yet.
-
@jsulm hi, I tried to write a file to /data/user/0/org.qtproject.example.sozius_client/files as @J-Hilk said that by using QStandardPaths class should enable me to read/write to such a location even without permission from the manifest. Here is the relevant code part
QString certNameOnDisk = _hostName + "pem"; //Open the File QString writeableLocation; writeableLocation = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); QFile certFile(writeableLocation + QDir::separator() + certNameOnDisk, this); if(certFile.exists()) { qWarning() << "cert file exists"; } else { qWarning() << "cert file does not exist"; } certFile.open(QIODevice::ReadOnly); if(certFile.open(QIODevice::ReadOnly)) { qWarning() << "certFile is open"; certFile.close(); } if (!certFile.open(mode)) { qCritical() << "so_SslClient: Error reading or writing cert-File"; return QSslCertificate(); } //Write the file to disk if (mode == QIODevice::WriteOnly) { if (certFile.write(cert.toPem()) == cert.toPem().length()) { qDebug() << "so_SslClient: New trusted certificate written with success"; } return QSslCertificate(); } //Read the file from disk QSslCertificate localCert = QSslCertificate(&certFile, QSsl::Pem); if (localCert.isNull()) { qWarning() << "so_SslClient: Certificate file empty"; } return localCert; }
The file should then be called e.g. 192.168.0.7pem and be located in /data/user/0/org.qtproject.example.sozius_client/files. My app, which is basically a client, should create this file.
-
@a_so said in Failed to create QFile when deploying to Android device:
QStandardPaths class should enable me to read/write to such a location even without permission from the manifest
No, it should not - it does not give you any permissions to anything. It can tell you in which directories you have write access.
Why do you open the file first in read only mode and then in "mode" mode (what ever mode is set to)?
Did you verify that you can open the file in write mode? -
@J.Hilk I use API level 23 and Qt 5.8. I also tried level 21 and 22
-
@a_so said in Failed to create QFile when deploying to Android device:
certFile.open(QIODevice::ReadOnly);
if(certFile.open(QIODevice::ReadOnly)) {
qWarning() << "certFile is open";
certFile.close();
}Why do you open the file twice in read only mode?!
-
@a_so api 23 is Android 6.0 Marshmallow, comes with the problems, you could try a lower one.
Adjustment of your code sample, to what @jsulm said:
if(certFile.exists()) { qWarning() << "cert file exists"; } else { qWarning() << "cert file does not exist"; if(certFile.open(QIODevice::ReadOnly)) { qWarning() << "certFile created"; certFile.close(); }else qWarning() << "certFIle could not be created"; } if (!certFile.open(mode)) { qCritical() << "so_SslClient: Error reading or writing cert-File"; return QSslCertificate(); }
edit:
Also youreturn
, without closing the file! You shouldn't do that... -
@jsulm this is the very original code. My client runs also on Linux and Windows. There the folder for certificates is created in the current directory of my project, where .pro and all header and source files are located.
QSslCertificate so_SslClient::certFileOnDisk(const OpenMode mode, const QSslCertificate &cert) { //Get the current directory QString currentDir = QCoreApplication::applicationDirPath(); QString certDir = currentDir + QDir::separator() + "certs"; if (!QDir(certDir).exists()) { QDir(currentDir).mkdir("certs"); qDebug() << "so_SslClient: No 'certs' folder in app-dir, created one"; } //Save the file under the hostname + 'pem' file ending QString certNameOnDisk = _hostName + "pem"; //Open the File QFile certFile(certDir + QDir::separator() + certNameOnDisk, this); if (!certFile.open(mode)) { qCritical() << "so_SslClient: Error reading or writing cert-File"; return QSslCertificate(); } //Write the file to disk if (mode == QIODevice::WriteOnly) { if (certFile.write(cert.toPem()) == cert.toPem().length()) { qDebug() << "so_SslClient: New trusted certificate written with success"; } return QSslCertificate(); } //Read the file from disk QSslCertificate localCert = QSslCertificate(&certFile, QSsl::Pem); if (localCert.isNull()) { qWarning() << "so_SslClient: Certificate file empty"; } return localCert; }
-
@jsulm I am sorry. My mistake, not intentionally.
-
Guys thank you so much! The adjusted code from @J-Hilk did it for me + I used target SDK 21. Thank you for your help!