-
-
Notifications
You must be signed in to change notification settings - Fork 663
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
Switch to Android App Bundle format for Play Store uploads #3547
Comments
This fixes #3323, meeting the Google Play 64-bit requirement that comes into effect next week, 2019-08-01 -- in other words, it makes it possible for us to continue uploading new releases after that date. Aside from ticking a box, it's expected to improve performance on devices with 64-bit CPUs -- which is most new devices of the last few years, and 85% of all our installs on active devices as reported by the Play Console. (In "Release management > Device catalog", filtering "ABI" to `arm64-v8a` or `x86_64`.) The main work to make this possible happened in RN upstream; we pulled it in with our upgrade to RN v0.59, #3399. This is one last fragment of the diff in upstream's template app between those versions, enabling 64-bit versions in our build config. One unfortunate regression this causes: we're still distributing a single APK for all architectures, and so adding 64-bit architectures makes it a lot bigger. At a quick estimate from comparing `yarn build:android-nokeys` before and after, we go from 13MB to 22MB. The Play Store has had a solution to that for a while now, called "Android App Bundle". We should switch to that. We're already tracking that task as #3547, and this change increases its priority.
Bumping up to P1, because adding 64-bit libraries (#3323) just now increased our APK size by quite a lot, and this will reverse that increase. A release build from In fact, it should more than reverse it -- from inspecting the APK while working on #3323 , I just noticed that we're shipping not two, but four versions of all the native code. Here's a list of the biggest files within the APK, one that compresses to 21.8MB:
The quoted sizes are uncompressed. Note the four different versions of At a rough estimate, if the app is still about 22MB before we take care of this, this means it should get reduced to 9-10MB -- well under half the size. |
This should be relatively easy to accomplish: we simply need to run I'm not sure about Sentry yet; they do appear to have some support for AABs, although we may need to upgrade. (But then, I half expect that'll be needed for #3585 as well.) |
I've made some changes in our release scripts to support AABs, and in our release-process documentation to make them the primary form for the release. I've run through that process for the upcoming v27.156, up to alpha stage, and everything seems to work. (Chat thread starts here.) So, closing this issue as done. The resulting download-size savings seem to be in line with what we hoped. Our APKs have grown since the above comments (at least partly from RN upgrades; some investigation in chat), to 30.0 MB for v27.156. But the download size is estimated by the Play Console at 12.4 to 13.4 MB, and when I tried the download for my own main device it was 13.8 MB. That's a savings of a little over 16 MB or 54%, which makes it a little more in absolute terms and a little less in relative terms than we estimated earlier. |
We don't want to be using JavaScriptCore forever, if we can avoid it; we're tracking the switch to Hermes as zulip#4131. In fact, Hermes doesn't yet support Intl. For now, this tiny code change will allow `react-intl` to work on Android. A `react-intl` doc [1] links to instructions [2] [3] to use a variant of JavaScriptCore that supports `Intl`. So, follow those instructions. Reportedly, this change will add 6MiB per architecture. zulip#3547 was recently resolved, though, giving us some wiggle room. [1] https://formatjs.io/docs/react-intl/#react-native [2] https://github.com/react-native-community/jsc-android-buildscripts#international-variant [3] They're slightly out-of-date, currently, but it's still easy to tell what to do; see facebook/react-native@d7f5153cd#diff-b8dd15c78827c1b48f9fe21c45686142R100-R111 for the new edit to make to `android/app/build.gradle`.
We don't want to be using JavaScriptCore forever, if we can avoid it; we're tracking the switch to Hermes as zulip#4131. In fact, Hermes doesn't yet support Intl. For now, this tiny code change will allow `react-intl` to work on Android. A `react-intl` doc [1] links to instructions [2] [3] to use a variant of JavaScriptCore that supports `Intl`. So, follow those instructions. Reportedly, this change will add 6MiB per architecture. zulip#3547 was recently resolved, though, giving us some wiggle room. [1] https://formatjs.io/docs/react-intl/#react-native [2] https://github.com/react-native-community/jsc-android-buildscripts#international-variant [3] They're slightly out-of-date, currently, but it's still easy to tell what to do; see facebook/react-native@d7f5153cd#diff-b8dd15c78827c1b48f9fe21c45686142R100-R111 for the new edit to make to `android/app/build.gradle`.
We don't want to be using JavaScriptCore forever, if we can avoid it; we're tracking the switch to Hermes as zulip#4131. In fact, Hermes doesn't yet support Intl. For now, this tiny code change will allow `react-intl` to work on Android. A `react-intl` doc [1] links to instructions [2] [3] to use a variant of JavaScriptCore that supports `Intl`. So, follow those instructions. Reportedly, this change will add 6MiB per architecture. zulip#3547 was recently resolved, though, giving us some wiggle room. [1] https://formatjs.io/docs/react-intl/#react-native [2] https://github.com/react-native-community/jsc-android-buildscripts#international-variant [3] They're slightly out-of-date, currently, but it's still easy to tell what to do; see facebook/react-native@d7f5153cd#diff-b8dd15c78827c1b48f9fe21c45686142R100-R111 for the new edit to make to `android/app/build.gradle`.
This bit of code doesn't currently do anything, because we build a single APK for all devices. It would if we started building split APKs per ABI. This sort of thing was required for publishing an app as multiple APKs on Google Play. (The docs link in the comment is broken; a current version appears to be: https://developer.android.com/google/play/publishing/multiple-apks#VersionCodes .) Google Play would use the different version codes as tiebreakers to decide which APK to give to a device when several were supported. But on Google Play, publishing multiple APKs has been obsolete for years. Instead, one uploads a single AAB, "Android App Bundle", and then Google slices and dices that into separate APKs for the per-ABI files, the per-screen-density files, the per-screen-size files, and so on. Each device downloads the specific combination of those pieces that applies to it. We never did publish multiple APKs on Google Play, and because it's now obsolete we never will; we've been using AABs since zulip#3547 in 2020. We do intend to start publishing multiple APKs, which would cause this bit of code to start having an effect. But this convention doesn't seem to be useful anywhere else: for a user installing directly from our GitHub release it's invisible and unhelpful, and the one known downstream distributor of our APKs plans to just distribute the one most widely-supported of them anyway: zulip#1270 (comment) which will make this hack have no use there either. So it seems like messing with the version codes like this would only cause confusion. Instead, just let the different per-ABI APKs for a given release have the same version code as each other, and as the AAB does. That way the next release after v27.181 will have version code simply 182, rather than 182003 et al.
The great bulk of the size of our APK comes from the native libraries in it (most of all libjsc.so). Those exist in a separate copy for each of our 4 ABIs, but any given device is going to use only one of those. So, build a separate APK for each ABI. The new APK for arm64 (the most common) is 40.3MB, compared to 132.3MB for the old all-in-one APK. This has no effect for the many Android users who get our app via the Google Play Store: there, we already upload an AAB, which Google splits up into several APKs still more finely. See zulip#3547. Fixes: zulip#5295
The great bulk of the size of our APK comes from the native libraries in it (most of all libjsc.so). Those exist in a separate copy for each of our 4 ABIs, but any given device is going to use only one of those. So, build a separate APK for each ABI. The new APK for armeabi-v7a (the most widely-supported) is 35.1MB, compared to 132.3MB for the old all-in-one APK. This has no effect for the many Android users who get our app via the Google Play Store: there, we already upload an AAB, which Google splits up into several APKs still more finely. See zulip#3547. Fixes: zulip#5295
This would be nice to do because it would probably make our app somewhat smaller to download. Major apps with lots of developers reportedly get 10-40% smaller. Our recent releases are about 11MB as APKs.
Also, I get a reminder about this every time I upload a new release to the Play Store, or promote a release to beta or production.
Some information here (including the figures I've summarized as "10-40%"), and links to more info:
https://developer.android.com/platform/technology/app-bundle
Relevant in particular for us:
https://developer.android.com/studio/build/building-cmdline#bundle_build_gradle
The text was updated successfully, but these errors were encountered: