I try to embed the sqlite file generated by QML's Local Storage for Android. The code below works for desktop. Although There are sqlite and ini files in Android's assets folder, the app doesn't see the database file as default. How can I get it work?
The code in main.cpp:
QString customPath = "assets:/OfflineStorage";
QDir dir;
if(dir.mkpath(QString(customPath))){
qDebug() << "Default path >> "+engine.offlineStoragePath();
engine.setOfflineStoragePath(QString(customPath));
qDebug() << "New path >> "+engine.offlineStoragePath();
}
engine.clearComponentCache();
It has been solved here. The problem was copying sqlite and ini file to the right location.
Related
I'm developing an app on android using Qt 5.15.0. My app creates a database and some other files using QStandardPaths::AppDataLocation. everything works fine from the code side: debug output makes me think the files are there and that the app is using them. The problem is that when I search from the PC inside the smartphone folders I cannot find the files created. So this makes me think I am not writing to the folder I'm expecting to.
This is my code:
appDataPath = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
QDir directory;
if (!directory.exists(appDataPath + QStringLiteral("/DATABASE")))
directory.mkpath(appDataPath + QStringLiteral("/DATABASE"));
if (!directory.exists(appDataPath + QStringLiteral("/DATA")))
directory.mkpath(appDataPath + QStringLiteral("/DATA"));
qDebug() << "Percorso: " << appDataPath << " dir exists:" << directory.exists(appDataPath + QStringLiteral("/DATABASE"));
QFile f( appDataPath + "/DATABASE/Prova.txt" );
if( f.open( QIODevice::WriteOnly ) )
{
f.write( "Ciao" );
f.close();
}
if( f.error() != QFileDevice::NoError )
qDebug() << QString("Error writing file '%1':").arg(appDataPath + "/DATABASE/Prova.txt") << f.errorString();
I also write a file that I read at startup and I can read from it so I assume the file is present and is not saved as temporary.
The output is:
D/MyApp(17849): Percorso: "/data/data/org.qtproject.example/files" dir exists: true
Now I suppose I can find my files in this directory inside the phone in this folder:
Questo PC\Samsung Galaxy J3 (2016)\Phone\Android\data\org.qtproject.example\files
But there are no directories or files inside. I bet I am missing some trivial things.
I am giving the app these permission:
android.permission.WRITE_EXTERNAL_STORAGE
android.permission.READ_EXTERNAL_STORAGE
Can someone help me?
Thanks in advance!
It seems that
QStandardPaths::AppLocalDataLocation, QStandardPaths::AppDataLocation
don't give the correct path to the app's file folder. I encountered the same issue with Qt 5.14.1. While QStandardPaths gave me
/data/user/0/com.mycompany.myapp/files
a call via a QAndroidJniObject to the java side gave me
/storage/emulated/0/Android/data/com.mycompany.myapp/files
Using the latter all directories and files were created correctly. I suggest to either try my work-around with
QtNative.activity().getExternalFilesDir(null).getAbsolutePath();
in an added java class and call it through a QAndroidJniObject or report this as a bug to Qt.
Nevertheless, there might be another solution to the problem I'm not aware of.
I got a couple of questions :
Where can I locate installed android apk on my mobile
I can not open the database
Where should i copy Database file on my hard
here is pro file :
ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android
deployment.files += Poem.db
deployment.path = /android/assets
INSTALLS += deployment
connection file:
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("Poem.db");
QFile dfile("assets:/Poem.db");
if (dfile.exists())
{
dfile.copy("./Poem.db");
QFile::setPermissions("./Poem.db",QFile::WriteOwner | QFile::ReadOwner);
}
If the installation is successful app logo will appear along with other apps.
You can copy by code to application folder or other folder you want .
QString path1 = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation);
QString path = path1 +"/Appfolder/sample.db";
if(QFile::copy("assets:/sample.db", path))
{
qDebug() <<"db copied" << endl;
}
I'm trying to copy a default initialized database packaged in the assets folder to an permanent location in an android device. For this I hav the following code:
QString db_file = "/my_db";
QString path = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
QFile assets_path("assets:" + db_file);
assets_path.copy(path + db_file);
QFile::setPermissions(path + db_file, QFileDevice::ReadUser |
QFileDevice::WriteUser);
And then I would go on to open the database in this new path, the thing is I'm getting the following error after the copy.
Copy error "Cannot create /data/user/0/org.qtproject.Demo/files/my_db for output"
What am I doing wrong?. Is also this the correct/proper way to do this?
Thanks.
Well aparently is a bug in Qt 5.10 prebuilt version, rolled back to Qt 5.9 and it works. Its a shame since I needed the QML translation functions.
https://bugreports.qt.io/browse/QTBUG-64103
I am trying to make an android application using qml and C++ on QtCreator and I am not able to deploy sqlite database to android :
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
QFile file(":/patients.db") ;
if (file.exists()) {
file.copy("./patients.db") ;
QFile::setPermissions("./patients.db",QFile::WriteOwner | QFile::ReadOwner) ;
} else qDebug() << "the file does not exist" ;
db.setDatabaseName("./patients.db");
patinets.db exist under the qrc tree in QtCreator and the code work on my development host (Linux ubunntu)
But on android, the debug message "the file does not exist" gets printed out.
Am I missing something here?! What is the correct way to do this?
Thank you.
It is helpfull if you check status return codes in each step of your 'deploying'. Both, file.copy() and QFile::setPermissions() have success indicating return values.
It is highly possibile, that alreadyfile.copy("./patients.db") failes, because on android you are not allowed to create any files in same directory where your binary/apk is contained.
You need to obtain the path to internal storage allocated for your app at runtime. Link to 'Saving Files' of Android docs.
You should obtain the correct path by means of QStandartPath (e.g. AppLocalDataLocation).
You could obtain a possible target directory and place your sqlite file there like this:
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
QFile file(":/patients.db") ;
QString patientDbPath;
if (file.exists()) {
patientDbPath = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation);
if (patientDbPath.isEmpty())
{
qDebug() << "Could not obtain writable location.";
return;
}
patientDbPath.append("/patients.db");
file.copy(patientDbPath) ;
QFile::setPermissions(patientDbPath ,QFile::WriteOwner | QFile::ReadOwner) ;
} else qDebug() << "the file does not exist" ;
db.setDatabaseName(patientDbPath);
The application that I work on has a external SQLite database (sitting in the assets folder). My friend is using the same DB file in the iPhone version of the app. Content of the DB file is updated continuously. As both projects are in the same repository we created a Shared folder where we keep the DB file so both of use can link to that shared resource. It works in the iPhone project but fails in Android.
When in Eclipse, I click on the assets/new/file and click on Advanced and then Link to file in the file system. The file appears in the assets folder (in Eclipse) but I cannot access it from JAVA code.
Why that doesn't work? Is there any other was of linking external files to the project in Eclipse?
Thanks
EDITED:
I use this code for opening the assets file:
OutputStream os = new FileOutputStream(db_path + DB_NAME);
byte []b = new byte[1024];
int i, r;
//load list of files from 'data' folder
String[] fileCollection = am.list("data");
Arrays.sort(fileCollection);
for(i=0;i<fileCollection.length;i++)
{
//String fn = String.format(DB_NAME"%dd.db", (i + 1));
String fn = DB_NAME + "." + (i + 1);
if(fileCollection[i].equals(fn) == false){
break;
}
InputStream is = am.open("data/"+fn);
while((r = is.read(b)) != -1) {
os.write(b, 0, r);
}
is.close();
}
os.close();
From, the detail you given in question, I conclude that you can not use database file directly from the asset directory, you have to copy that database file into application's internal storage data/data/database/ and then use it.
EDIT:
I think Android environment can't recognize the physical path of you system files, so when we try to link any file for asset or any folder which are in android project hierarchy then it can not find the file which one linked from a system path.
So to make it working in android you have to put that file in your asset directory physically, not virtually (by putting file link in asset).
Hope I am not wrong in this. If yes then let me know on this topic.
Thanks.