-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
Reduce size of APK #3097
Comments
And for completion, I also get this warning in the Play Store:
It's an odd error because the number of devices on v1.22.0-beta.0 and v1.22.0-beta.1. are the same. I bet it's because of the native platforms change. |
Step 1. Confirmed; Mapbox is the culprit. Release APK built on
Release APK built with the same command after stubbing out calls to Mapbox classes and removing the two
|
The size change is 5.9 MB to 14.2 MB — an increase of 8.3 MB or a factor of 2.4x. |
https://proandroiddev.com/reducing-apk-size-by-using-abi-filters-and-apk-split-74a68a885f4e and the refs at the bottom have good info on what we should include/exclude if we want to build one APK.
|
Based on https://developer.android.com/ndk/guides/abis.html, it seems to me that:
@yanokwa This differs from your assessment—could you confirm if I am reading that right? |
If I drop
The size only reduces from 14240464 to 14083793, a savings of 156 kB or 1.1%. 😕 Native libraries are huge! |
Here is a list of all the phones from phonedb.net that have an Intel or AMD processor, run Android 4.1 or higher, and have GPS capability: There are 155 models. Consolidating similar models, this list simplifies down to:
Using this list, I created a Report named "x86 devices, 2018-2019" in Google Analytics with the following conditions:
The report shows 25 models used since January 1, 2018, accounting for 1,026 users (0.10% of users) and 254,910 sessions (0.10% of sessions): |
@zestyping I'm still thinking about your earlier question at #3097 (comment). While I do that, do you have a sense for how bad the performance difference is between say arm64-v8a and armeabi-7a? Is is the type of thing that the average user would notice? |
Well, ignore my previous comment. According to https://developer.android.com/distribute/best-practices/develop/64-bit, starting August 1, 2019, we will need to ship with a 64-bit library if we use native code. So, we have to include arm64-v8a and one of armeabi-v7a or armeabi depending on what API level we want to support. If we include x86, then we have to include x86_64. |
Aaaaahh, FU, Google. What a useless waste of space and bandwidth for people who don't need the (probably minimal) speedup that going from 32-bit to 64-bit delivers. Yet again, thinking only of those privileged with ubiquitous and plentiful Internet bandwidth, who don't pay by the megabyte, and who can afford to throw away their phones every couple of years. |
The Google giveth and the Google taketh away! One option is that we publish APKs for every ABI. That's a tough thing to do logistically. Uploading multiple APKs, keeping the versionCodes different, sound like a nightmare. Maybe there are tools that automate the process? Another option is that we use App Bundles. This option feels more promising but I have done zero research so who knows what dragons lay ahead. |
The problem with both those solutions is that they totally break Bluetooth app transfer. |
(Or local serving of an APK file, which is super useful in the field.) |
Okay, I've finished making all these builds so we can compare them:
Our baseline is the I was going to recommend the v7a build (8.2 MB), which is a tolerable +2.3 MB (1.4x) increase, runnable for 99.90% of our users. But Google wants to use its monopoly power to force us to distribute the v7a-v8a build (10.2 MB) or v7a-v8a-x86-x86_64 (14.2 MB), which are 1.7x bigger and 2.4x bigger respectively. |
Another option we could consider is that we could publish two APKs: v7a and v7a-v8a. We publish the v7a-v8a version only to satisfy Google's pointless requirement. Both versions are safe to distribute over Bluetooth, but the v7a-v8a version is only a formality. We distribute v7a as the true, official version. (It might even be possible to write the v7a-v8a version so that it downloads and replaces itself with the v7a version upon installation, ensuring that Bluetooth transfers are fast.) I imagine the ability to run 32-bit apps is unlikely to go away for 4–5 years. The Play Store will continue to serve 32-bit apps to all devices until August 2021; after that, 64-bit devices won't see them anymore, but 32-bit apps will still be served to 32-bit devices indefinitely. Even when 2021 comes, there is no reason to actually make 64-bit phones that suddenly can't run apps > 2 years old. |
Okay, here are all the options I can think of. We don't have to decide on the long-term plan immediately; we can choose to postpone some or all of the decisions until v1.23 or until August. Options we have now:
Options we will have after August 2019:
|
@yanokwa Thoughts on next steps? I think this should be your call. (My personal leaning is toward releasing a v7a-only APK for now so we start getting feedback on Mapbox right away, but pretty happy to go with anything you decide.) Let me know if there's any more data I can get for you that would factor into your decision. |
Quick note that the size in the Play Store is a little bit smaller than what gets uploaded (because ???). Right now the beta is showing up as 11.53mb. What happens to users on API 16 with v7a only? Are they cut off from updating Collect just like the x86 users or can they update but Mapbox won't work? |
I think we should ship v7a+x86 to get everyone for now, communicate in the release notes why the app size has gone up, and communicate about upcoming file size changes and potential dropping of x86. Reaching everyone is important because there are good features in this release independent of maps: logic in field lists and track changes. There might be a performance hit on 64-bit devices with this approach, but I doubt it'll be severe enough for people to notice (I have an email out to Mapbox asking about this). Also, since Mapbox isn't the default, it shouldn't affect most people. I don't love that we are burdening v7a folks with an extra 2 MB just to support x86, but they'll have to download even more anyway in August with the 64-bit requirement. If bandwidth is a huge problem, we still let people download from GitHub and sideload. Also, at the end of the day, even 10-15 MB isn't terrible. Magpi is 23 MB, Commcare is 20 MB, DHIS2 Capture is 15 MB. Question that is blocking the release is the same as @lognaturel's. What happens to API 16 people? |
@lognaturel Good point about API 16. You're right, this is the big open question, and it bears on both the API 16 question and on the decision to include x86. I had assumed that the APK without the right native libraries would still run but only fail when trying to make native calls into the native library (thus API 16 and x86 users would only miss out on Mapbox but everything else would still work) because that's the obviously more sane behaviour, but that probably means we should be cautious that it might not be the case. |
To clarify—it seems almost certain that it's possible to deploy an APK that gets served to all users with only the Mapbox part not working for API 16 and x86 users. It's just a question of how hard the Play Store is going to make it to accomplish that. (In the worst case, we could publish a fat APK containing armeabi and arm64-v8a and x86 libraries that are full of empty stubs.) |
Okay, I've confirmed that I can build and install an APK that lacks the native library for a given platform, and we can detect this in the code (so we could gracefully disable the Mapbox option in such a case). But I haven't confirmed that the Play Store will serve it. @yanokwa I'll confirm this later today if I can. But you don't need to block on that confirmation—if you want to proceed, the quickest way around the problem is to ship with |
If we can ship |
If we are okay with the size increasing to ~10 MB, I see no reason not to do that until August. The only performance impact this could possibly have is that the Mapbox library might run a bit slower than a hypothetical build with |
Oops. I spoke too soon. Mapbox dropped support for |
Okay. I tried publishing an app on Google Play that contains only an I expect that API 16 users will have this experience if we ship with If the Play Store refuses to serve to an API 16 device, then we will have to either add stubs for |
Oh, I have one more idea. What if we drop in a zero-byte file for |
I also expect that API 16 users would not be able to upgrade if the build only has
This is a really good idea. Any results? On another note, do we know for sure that shipping App Bundles precludes bluetooth transfer? Is the fastest way to confirm one way or another to try it? |
My new ideal would be ship |
@yanokwa Okay, I did an exploration of this today that led me down several garden paths. I'll try to write a shorter summary soon, but here's a description of everything for now—apologies for the length! See the last bullet point for the TL;DR on what we can do now.
|
Thanks for that deep dive, @zestyping. I know it's probably a lot more than you wanted to know about all this. No summary needed for me.
To be explicit about one thing that you explained to me that I don't think has made it into this thread -- while it's likely that there are some devices that run Collect from Android API 16 and ARM processors that don't support the armv7 instruction set, it's probably not very many. For example, The Alcatel M'Pop I have that runs Android 4.1.1 has a processor that supports the armv7 instruction set. So not having an
Alternately we can ship separate |
That's correct. According to https://source.android.com/compatibility/4.4/android-4.4-cdd.html#section-3.3.1, all Android devices from 4.4 up (API level 19+) are required to support Some of those devices are listed at https://forum.xda-developers.com/showthread.php?t=1596800 . The ARMv5 and ARMv6 lists look long, but I expect they would be a small minority of devices still in use today, even among our target audience. |
If anyone is curious to check a particular phone, the fastest way to find out the supported architectures is
|
I'm leaning towards using the zstd library trick to build a single binary for armeabi-v7a and x86. It feels low risk to me. @zestyping, any reason why you didn't recommend it as the approach for v1.22? |
Adding zero-byte stub binaries was indeed the main goal of the entire exercise. The only reason I didn't do that last step is that I had spent the whole day exploring all these possibilities already, it sounded like we wanted to release to go out today or tomorrow, and I didn't have the energy to figure out how to build our own package with stub binaries in the time left—I didn't realize it was so trivial to create an .aar file. Looks like I was closer to the finish line than I realized—glad you figured out the last step! |
@zestyping You did all the hard work! Glad I could chip in a little bit. |
Gradle sucked all the life out of me! I'm glad you tagged in. |
Historically, the Collect apk has been small (~4MB). Version v1.22.0-beta.1 has grown to 12.3MB. This is likely due to the addition of the Mapbox SDK. 12MB isn't terrible, but for large scale projects it will add up to a lot of time and money.
I'm using
./gradlew clean assembleOdkCollectRelease
to build the APK. The attached screenshot is what the Play Store sees as a difference between v1.22.0-beta.0 and v1.22.0-beta.1.Some next steps:
The text was updated successfully, but these errors were encountered: