Hi Spike,
Good question! Thanks to the Qt resource system there is a pretty neat solution for this: Google recommends to split up APKs into a main apk with 100MB maximum and an expansion file (obb file) that you can upload parallel to the main apk in Google Play Store. To split up your binary of your Felgo app or game you just have to split up your resources:
- Use your default “resources.qrc” file and add all your QML, JavaScript and other logic files
- Add a second “resources_expansion.qrc” file where you add all our audio, video and image files. Do not add this resource file to your main project file (i.e. do not add it to RESOURCES +=), we only use it for generating the expansion file.
It’s totally up to you how you split up those two files and where you add your resources, just make sure that the main APK does not exceed the 100MB limit.
Next, we create the expansion file from the second resource file. That’s actually the cool thing about Qt resources, it’s possible to create a binary form of your resource file and use that as the expansion file directly. This step is quite easy: Open a terminal and enter the following command (adapt the path to rcc if it’s not on your path and the app’s version code and bundle id).
rcc -binary resources_expansion.qrc -o main.<version-code>.<bundle-id>.obb
You can later on rename the file for every new version you release, just keep in mind that the name must match the released bundle id and version code.
Next, you need some additional code in your main.cpp file to load the second resource bundle, as it is not included in the main app. You can use the following code snippet, just make sure to adapt the version code for every released update again (improvement would be to set the app’s version code dynamically):
#if defined(Q_OS_ANDROID)
// The Android binary uses an obb file that loads additional resources, therefore we need to register it in the qresource system
QAndroidJniObject mediaDir = QAndroidJniObject::callStaticObjectMethod("android/os/Environment", "getExternalStorageDirectory", "()Ljava/io/File;");
QAndroidJniObject mediaPath = mediaDir.callObjectMethod( "getAbsolutePath", "()Ljava/lang/String;" );
QAndroidJniObject activity = QAndroidJniObject::callStaticObjectMethod("org/qtproject/qt5/android/QtNative", "activity", "()Landroid/app/Activity;");
QAndroidJniObject package = activity.callObjectMethod("getPackageName", "()Ljava/lang/String;");
QString dataAbsPath = mediaPath.toString()+"/Android/obb/"+package.toString()+"/main.<version-code>."+package.toString()+".obb";
bool loadResource = QResource::registerResource(dataAbsPath);
qDebug() << "Loading resource file from" << dataAbsPath << "succeeded:" << loadResource;
#endif
The code snippet looks a little bit complicated, it just resolves the path to the resource file dynamically. The most important line is QResource::registerResource which loads the expansion resource file into Qt’s resource system.
That’s all, you can then test your expansion file as described on several threads on StackOverflow before releasing your update.
A nice addition is to add a DEFINE statement in your project file where you can set if you want to use the expansion file or create a single APK file, which makes testing and development easier.
If there are any issues, just let us know!
Best,
Alex