Deploy Sqlite database to apk - android

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;
}

Related

Qt Android Directories

I am concerned about two questions regarding how Qt works with Android directories.
For example, I want to download an archive via a library (QuaZip), but I need it to be downloaded along the path "/ storage / emulated / 0 / Android / data /", and then unzipped right there. But the problem is that the file is saved in the patch "/data/user/0/org.qtproject.example.NameApp". How can this be fixed? My code (it is unlikely that it works at all, but on Windows it would work for sure):
m_file.rename ("/storage/emulated/0/Android/data/cache.zip");
Can I open a file in Android via QProccess?
On your first question about Android/data r/w
On Android 11 Android/data is forbidden for app access without root, see docs1 and docs2.
For read/write to other locations:
The directory must exis or must be created (with QDir::mkpath() at once, or with QDir::mkdir() by subdirectories sequentally, because it can't create trees of directories).
QFile must be closed before rename.
App must have android.permission.READ_EXTERNAL_STORAGE and android.permission.WRITE_EXTERNAL_STORAGE permissions.
At last, approve file access permissions manually in Android apps settings after app is deployed from Qt Creator. And you also may have to launch app manually, because there were reports about different app behavior when launched from IDE and and when launched manually from device.
This code worked for me (Android 11, Qt 5.15.2):
bool result;
QDir dir("/storage/emulated/0");
qDebug() << dir;
result = dir.mkdir("cache");
qDebug() << "mkdir(\"cache\") success: " << result;
QFile m_file(dir.path() + "/cache/cache.txt");
result = m_file.open(QFile::WriteOnly);
qDebug() << "open() success: " << result;
m_file.close();
result = m_file.rename(dir.path() + "/cache/cache.zip");
qDebug() << "rename() success: " << result;
On your second question about QProcess
This code worked for me:
QProcess process;
process.start("touch", QStringList() << "/storage/emulated/0/new_text_file.txt");
result = process.waitForFinished(1000);
qDebug() << "waitForFinished() success: " << result;
qDebug() << "errorString(): " << process.errorString();
The file new_text_file.txt appeared on my device storage. If you specify the type of file you want to launch, I can answer more precise.

How to set Local Storage path for Android

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.

How to write files to an Android device using Qt?

I have problems creating and writing files to an Android device in Qt. I have unsuccessfully tried a few different examples.
This example should write to the internal storage's Download folder:
QString path = QStandardPaths::writableLocation(QStandardPaths::DownloadLocation);
qDebug() << path; // '/storage/emulated/0/Download'
qDebug() << "Exists? " << QFile::exists(path + "/401891.png"); // This is an existing image in the folder, returns true
QFile testFile(path.append("/Testing.txt"));
testFile.open(QFile::WriteOnly);
QTextStream out(&testFile);
out << "Hello";
testFile.close();
qDebug() << "Exists? " << QFile::exists(path + "/Testing.txt"); // Returns false
I get this warning:
Warning: QIODevice::write (QFile, "/storage/emulated/0/Download/Testing.txt"): device not open
What I am missing and how to fix it?
Seems like the permissions were not being applied although they were stated in Manifest.
Go to Settings -> Applications -> Application Manager
Find your application and ensure the 'Storage' permission toggle is 'On'.
You are wrong in a last line, it gives:
.../Download/Testing.txt/Testing.txt/
use
qDebug() << "Exists? " << QFile::exists(testFile.fileName()); // Returns true

qt qml : deploying sqlite database to android using .qrc file not working

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);

Android: Linking external file to Eclipse project

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.

Categories

Resources