Qt Creator: include additional files inside Android apk

Developing an app for Android frequently require to include some additional files containing custom data used by the app itself (in majority of cases sqlite database files). Android provide a standard way by using a special folder called assets where these kind of files need to be stored. Qt Creator provide a instructions to use for copy these files during apk creation.



Full project example here

Basically you have to instruct qmake tool used by Qt Creator to copy specific files inside assets folder during compilation phase. What you have to do is to add the following instruction inside the Qt Creator project file .pro:

android
{
my_files.path = /assets
my_files.files = $$PWD/myfolder/*
INSTALLS += my_files
}

path is the path where the files will be copied. In case of Android this have to be assets folder but you can add subfolders if you need it. files is the list of files to copy. In the example $$PWD is the root where .pro file is located and using asterisk at the end mean copy entire subfolder structure (files and subfolders). In case you need to specify a list of files located in different paths you can add manually as follow:

my_files.files += $$PWD/path_to_file1/file1
my_files.files += $$PWD/path_to_file2/file2
my_files.files += $$PWD/path_to_file3/file3
...
...

Once finished compilation you can verify if your files has been added correctly by open the apk file using some archive tool like the free 7-zip software (apk is basically a compressed file containing all required data used by Android). Now you need a way to access these files by code. Qt have a special way to access assets folder as explained in official documentation below:

Qt for Android provides a special, virtual file system which is based on the assets mechanism in Android. Files that are put under assets in the android folder created by Qt Creator, will be packaged as part of your application package. These can be accessed in Qt by prefixing the paths with assets:/. For instance, to access the image logo.png in the folder assets/images, you can use QPixmap("assets:/images/logo.png").

Please note, in case you plan to use assets folder for store sqlite database files you have to know that, unfortunately, you can not use these database directly from assets folder itself. The reason is assets folder is read only but sqlite engine require read/write access also if you plan to use your database file only for read data without any write. In this case you have to copy these files in the app data writable folder as showed in the example below:

QFile DbFile;
QString DatabaseDataStoragePath = QStandardPaths::writableLocation(QStandardPaths::StandardLocation::AppDataLocation);
DbFile.setFileName("assets:/MyDatabase.sqlite");
DbFile.copy(DatabaseDataStoragePath + "/MyDatabase.sqlite")
QFile::setPermissions(DatabaseDataStoragePath + "/MyDatabase.sqlite", QFile::WriteOwner | QFile::ReadOwner);

Once done you can use the database from data folder you just copied to. Be carefully since this "problem" of assets folder have significant consequence to the space occupied by your app cause the space of database files is duplicated as consequence of copy operation (Android calculate app space by sum apk content size of app data folder size).

Comments

  1. nice article ... with an obvious question ... where is defined the name "my_files" in pro ?
    the compiler is giving me this error: -1: error: [install_my_files] Error 3 (ignored)

    ReplyDelete
    Replies
    1. my_files is defined in the same time you declared my_files.path and my_files.files as in the first snippet. Are you sure you used the correct syntax inisde the pro file?

      Delete
    2. thank you ... seems the error insist ... i have not any clue ... without the assets file the project is working right ... i could send you the pro file in case you want in your email

      Delete
    3. Create a project example on the fly. I added the link to the project at the begining of the post. Please try to test this working example for check if work on your environment.

      Delete
    4. configuration Qt5.10.1 on tablet Android API25 V7.1

      Yes the test project is working as expected ... thank you
      digging deeper i came to the following conclusion:

      The assets file system is not compatible (as expected) to the rest android file system.

      The result of my tests: (maybe there are even more issues)
      ----------------------------------------------------
      "assets:/logo.png" ok
      "assets:/logo.PNG" error (case sensitive)

      "assets:/set_tings.ini" error (not acceptable underscore char)
      "assets:/settings.ini" ok

      FILE *file; error (C object opens nothing)
      QFile file("assets:/settings.ini"); ok

      ifnt = QFontDatabase::addApplicationFont("assets:/main.ttf"); error (returns -1)

      db = QSqlDatabase::addDatabase("QSQLITE", "db");
      db.setDatabaseName("assets:/airnavigation.db"); error (doesn't open the database)
      ----------------------------------------------------

      1) The above 'errors' are not compile errors, means doesn't work with the "assets:/" path file.
      2) Under the "/sdcard/" path, all are working as expected .
      3) Reading the relative documentations in Internet there are no such references, notices etc, i think would be good this information and results to be included here in this article.

      Unfortunately for my own project the mission seems to be impossible,
      speaking for an "air navigation system" with a hundred of external files wanting to include all of them in one apk file, will be a painful story,
      not mentioning the 50 MB limit of "Google Play Store", so i have not idea how to publish easily for customers this free appl. If you have a good idea how to handle the 1GB needed external files, am here to listen.

      again many thanks
      Artemis

      Delete
    5. From what I remeber Google increase the apk file size limit but surely not to 1GB. The reasons qslite database file doesn't work by opening directly from assets virtual file system is explained in the post (basically because assets is a read only file system). The only solution you have is to use some online storage service from where download all required files at first initialization. This is the way followed by all major navigator app for download maps as you surely know. However, cause the large amount of byte do download, I don't think it will be possible to find some free service. I guess you'll have to pay for it...

      Delete
    6. I recommend the next article to be Qt for Android and "Google Play Store APK Expansion Files 2GB" :) ... if you search this topic there is almost nothing, just scattered information, no clear guides, and would be really helpful.
      https://developer.android.com/google/play/expansion-files.html

      Delete
    7. You right! In the same time you posted the link I remembered to have read about this solution introduced by Google. However in the time I got the news the limit was not so high, this mean Google increased the limit in the time. Anyway good for you, very sorry I didn't remeber this solution before. ^_^

      Delete

Post a Comment

Popular posts from this blog

Access GPIO from Linux user space

Launch an app from Android shell terminal

Android: adb push and read-only file system error