Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: ensure all devices get 32-bit and 64-bit ABIs from the Play Store #951

Merged
merged 6 commits into from
Apr 21, 2022

Conversation

gmaclennan
Copy link
Member

Currently, for the Play Store release, our Bitrise deployment script uploads an Android App Bundle (.aab) to the Play Store. When a device installs Mapeo from the Play Store, the store uses this AAB to generate an APK that contains only the architecture (ABI) used by the phone. In most cases this will either be armeabi-v7a (32-bit Arm) or arm64-v8a (64-bit Arm). The current AAB also includes builds for 64-bit and 32-bit Intel (x86) devices. There are virtually no x86 phones, but Chromebooks now run Android apps and many of those have a x86 processor.

The problem with this current setup is that a 64-bit Arm phone would install an APK that only has the architecture for 64-bit phones. This is good in that the Play Store download is smaller, but it means that the 64-bit phone that installed from the Play Store can only update other 64-bit phones, but it cannot update 32-bit phones. Vice-versa is ok (a 64-bit phone can run a 32-bit APK). This is all quite confusing for users trying to understand why a given phone may or may not update another.

The proposed solution here is to upload an APK to the Play Store (instead of the AAB) that contains Arm 32-bit and Arm 64-bit binaries. The Play Store will not re-package an APK (it will only do that if you upload an AAB). This means that devices that install from the Play Store will now get an APK that contains binaries for both 32-bit and 64-bit architectures, so they can share p2p updates with either 32-bit or 64-bit phones.

I have not included Intel (x86) binaries in this APK, because that would double the size of the APK, increasing download time. Instead I am uploading to the Play Store a separate APK for Intel (x86) which includes both 32-bit and 64-bit binaries for Intel. This means that an Intel device will not be able to p2p update an Arm device. I think this is a reasonable compromise (reducing download size vs. universality of p2p update working).

Play Store should accept both APKs, and send the correct one to the corresponding device (e.g. x86 devices will get the APK with the x86 binaries, and Arm devices will get the APK with arm binaries), but we will not be able to test this until we try to deploy a release.

Previously we were uploading the `.aab` with all ABIs to Google Play.
The Play Store generates a custom apk from this `.aab` with only the
ABI that the device supports. This causes p2p update to fail when
updating between devices with different ABIs. By uploading a `.apk`
instead of a `.aab`, Play Store will not generate custom apks. The
downside of this is a larger install from Google Play (the apk
containing both the armeabi-v7a and arm64-v8a ABIs), but it avoids
issues with p2p updates. Note: This means that Intel devices cannot
install from the Google Play Store (since we are no longer shipping x86
and x86_64 ABIs). This will be resolved in a future commit, and only
affects a very small number of phones (it also affects Chromebooks that
support Android apps and run on x86).
@gmaclennan
Copy link
Member Author

FYI the Intel APK has a higher version code assigned - this is necessary if we are pushing each to the Play Store, see https://developer.android.com/google/play/publishing/multiple-apks#Rules

Copy link
Member

@achou11 achou11 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm! out of curiosity, what's the size difference now that we have both binaries + the fact that it's no longer an aab?

@@ -81,7 +81,7 @@ workflows:
before_run:
- primary
envs:
- GRADLE_TASKS: assembleApp assembleIccaRelease bundleAppUniversal -x assembleAppDebug
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so just to clarify, this is replacing the command that builds the aab with the commands to build the apks instead?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I define the tasks in the environment variable so that I can share the same build code for the different builds (internal, release candidate, and release). The naming of these is ${task}${flavor}${builtType}. I removed the bundleAppUniversal task which would create a .aab of the "app" flavor and "universal" build type (the universal build type includes both arm and x86, 32- and 64-bit). I replaced it with the assembleAppUniversal task which builds the same but as a .apk. I also added a new built type intel which only includes the x86 binaries. When publishing multiple APKs to the Play Store they must not overlap (e.g. we could not publish the release build (which is only Arm) and the universal build, because the universal build includes Arm as well as x86.

@gmaclennan
Copy link
Member Author

lgtm! out of curiosity, what's the size difference now that we have both binaries + the fact that it's no longer an aab?

A single-architecture APK is about 35-38Mb, so that is what a user installing from the Play Store would previously need to download. The dual-architecture Arm binary is about 62Mb.

@gmaclennan gmaclennan merged commit fd7af49 into develop Apr 21, 2022
@gmaclennan gmaclennan deleted the fix/play-store-abis branch April 21, 2022 10:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants