Build universal apk for project with dynamic feature modules

For the latest version of org.totschnig.myexpenses, I have decided to make use of Play Store’s dynamic feature delivery. F-Droid would need to build a universal APK, which can be done in one step via gradle, as explained here In my case, the command would be “./gradlew :myExpenses:packageConscriptExternReleaseUniversalApk”.
I cannot find in the documentation for Fdroid’s metadata how to specifiy the exact gradle command. Is this currently supported?

The current code can be tested?

In theory:

  - conscrypt
  - extern

But where exactly do you specify the universal apk thing? Can you link me to the gradle lines?

Yes. The HEAD of master branch is supposed to be tagged as version 3.1.4 and should work. If I only specify the flavors as you suggest, wouldn’t F-Droid simply execute the task assembleConscriptExternRelease ? This would result in an APK without the dynamic feature module (ocr).
The universalApk ist not specified in build.gradle, but it is a feature of the Android Gradle Plugin. Apparently it uses bundletool ( under the hood to build the univeral apk from an Android App Bundle.

How does it use that? You could specify it in build: then pick up the resulting apk in output:, right?

“bundletool” comes with buildtools or sdk or?

That should work I think. So the recipe would be something like?

  - ./gradlew :myExpenses:packageConscriptExternReleaseUniversalApk
 - myExpenses/build/outputs/universal_apk/conscriptExternRelease/myExpenses-conscript-extern-release-universal-unsigned.apk

Bundletool is not part of the command line tools included in the SDK, but is made available as a separate download. I unfortunately do not know how the Android Gradle Plugin uses it. The task for packaging the universal APK is not documented.

Maybe we can build it from

Yes, this is the tool that allows to manipulate AAB files, and it has an option to extract the universal APK from it. But since the same can be achieved directly from Gradle, it does not seem necessary.

Can you put an APK on Github/somewhere so I can compare its contents?

Built from tag r428 with “./gradlew clean :myExpenses:packageConscriptExternReleaseUniversalApk”:

Build fine, but what is ? Why do we download (random) APKs with your app? (I know it’s not random but you get my point)

The app also links to the FAQ, where I explain the rationale behind: . So for the moment, the Scan receipt feature would require F-Droid users to download this helper app that uses Google’s proprietary Mlkit library. As soon as I have got to implement OCR based on Tesseract, my idea is to submit an equivalent app to F-Droid, and users would then be linked to the download from F-Droid.

Just to clarify. The idea of outsourcing the OCR capability to another app, is not primarily motivated by this app not being free, but by keeping the size of MyExpenses apk smaller.

Right so we need a “NonFreeDep” antifeature too? Because the current workflow just downloads an APK without explanation of where and what license. Can you add an explanation in the UI?

Sure. Do you mean that with the explanation, the antifeature would not be necessary?

I have added Apache 2.0 licence to org.totschnig.ocr and augmented the information user sees when download is suggested:

I’d say if it does not “depend” on it it’s not warranted. The UI text helps the user to “opt-in” if they want. :wink: @Izzy right?

Well yes and no, you can license it as you will, if it depends on a closed source lib…the resulting APK will not open source.

Merge my typo fix and I’ll pickup that commit


I am aware that publishing it under Apache 2.0 does not qualify it for being included into F-Droid, but think it is relevant for users. It still is Open Source in the sense of Apache 2.0, although it is not free in the sense of the FSF.

Thank you for fixing the typo!

If you refer to that, wouldn’t that rather be NonFreeAdd (promotes non-free addons)? I might have missed something here, but from what I’ve read I agree that for NonFreeDep

It’s not a dependency, but a suggestion (“promotes”) – but NonFree nonetheless.