# APK Size Optimization for F-Droid / IzzyOnDroid ## Current state | Artifact | Size | |----------|------| | Universal AAB (`app-release.aab`) | 58.5 MB | | Per-ABI APK (estimated) | ~20–25 MB | | IzzyOnDroid per-APK limit | 30 MB | `bundletool` is not installed in this environment, so per-ABI APK sizes were not measured directly. The estimate above is based on typical Expo/Hermes React Native apps: - Hermes JS engine binary: ~8–10 MB per ABI - React Native native libraries: ~5–8 MB per ABI - JavaScript bundle (ABI-independent): ~6–8 MB - Assets (icons, splash, etc.): ~2–3 MB **Conclusion:** arm64-v8a APK is likely ~20–25 MB — within IzzyOnDroid's 30 MB limit. No ABI splits required for the initial submission. To verify when bundletool is available: ```bash bundletool build-apks \ --bundle=android/app/build/outputs/bundle/release/app-release.aab \ --output=apks.apks \ --mode=universal # For per-ABI sizes: bundletool build-apks \ --bundle=android/app/build/outputs/bundle/release/app-release.aab \ --output=apks-splits.apks \ --mode=default unzip apks-splits.apks -d apk-splits/ ls -lh apk-splits/splits/ ``` --- ## If arm64-v8a APK exceeds 30 MB — fix approach ### Option A: ABI splits in Expo config plugin (recommended) `android/app/build.gradle` is regenerated by `npx expo prebuild` on every CI run, so direct edits are overwritten. The correct approach is an Expo config plugin. Create `plugins/withAbiSplits.js`: ```js const { withAppBuildGradle } = require('@expo/config-plugins'); module.exports = function withAbiSplits(config) { return withAppBuildGradle(config, (config) => { const contents = config.modResults.contents; // Insert splits block inside android { ... } after defaultConfig if (!contents.includes('splits {')) { config.modResults.contents = contents.replace( /defaultConfig \{/, `splits { abi { reset() enable true universalApk true include "armeabi-v7a", "arm64-v8a", "x86", "x86_64" } } defaultConfig {` ); } return config; }); }; ``` Register in `app.json`: ```json { "expo": { "plugins": [ "./plugins/withAbiSplits.js" ] } } ``` After `npx expo prebuild`, `android/app/build.gradle` will contain the splits block. Run `./gradlew assembleRelease` — produces separate APKs per ABI. For IzzyOnDroid / F-Droid: attach `app-arm64-v8a-release.apk` to the GitHub release. ### Option B: fdroid Gradle product flavor Add a `fdroid` flavor that includes only arm64-v8a: ```groovy // In the config plugin or directly in build.gradle (pre-prebuild override) android { flavorDimensions "distribution" productFlavors { fdroid { dimension "distribution" ndk { abiFilters "arm64-v8a" } } play { dimension "distribution" } } } ``` Build with: `./gradlew assembleFdroidRelease` This also provides a clean hook for excluding FCM artifacts (see below). --- ## FCM / expo-notifications `expo-notifications` compiles FCM receiver classes even when only local notifications are used (the app only calls `scheduleNotificationAsync` — no push token retrieval). F-Droid scanner may flag `com.google.firebase:firebase-messaging` as `NonFreeNet` or `NonFreeDep`. **Mitigation for F-Droid mainline:** add a `fdroid` product flavor that excludes the FCM artifact: ```groovy // In config plugin android { flavorDimensions "distribution" productFlavors { fdroid { dimension "distribution" } } } configurations.fdroidImplementation { exclude group: 'com.google.firebase', module: 'firebase-messaging' } ``` Or patch `expo-notifications` `build.gradle` via a Gradle init script to replace the FCM dependency with a no-op stub in the `fdroid` flavor. **This is not required for IzzyOnDroid** (more tolerant of GMS dependencies if they are not actively invoked). Track the F-Droid reviewer's feedback before investing in this fix — they may accept without it given the local-only usage. --- ## Action items (when ready to optimize) 1. Install bundletool: `sudo apt-get install bundletool` or download JAR from https://github.com/google/bundletool/releases 2. Run `build-apks --mode=default` to measure per-ABI sizes 3. If arm64-v8a > 30 MB: implement config plugin (Option A above) 4. For F-Droid mainline FCM concern: implement `fdroid` product flavor (Option B) 5. Document measured sizes in this file once known