Reaching more Android devices

A small article from a friend:

https://www.linkedin.com/pulse/reaching-more-android-devices-emmanuel-marty?trk=hb_ntf_MEGAPHONE_ARTICLE_POST

If you're currently publishing apps to the Google play store, you may be artificially limiting your target audience in terms of download size and devices that your app is compatible with. I'd like to share some tips to increase your downloads and device compatibility, that aren't widely available online.

Reduce your download size

Everything else being equal, a smaller apk size will measurably get you more downloads, especially for apps that are free and monetize with ads. The bulk of mobile usage growth is currently in developing countries that typically have metered data plans and no easy access to WiFi. Even in developed countries, many users download apps over 3G or 4G and have metered data usage. A smaller app will measurably get downloaded more than the same, bigger app.

I won't discuss well-known tips here, such as using Proguard to reduce the size of your Java code.

1. Significantly reduce your native code size

If you're using the NDK to build native code, as is common for many games and performance-sensitive apps, add some build flags to the Android.mk of your native library (as well as all static libraries you are building together with your app):

LOCAL_CFLAGS := -ffunction-sections -fdata-sections -fvisibility=hidden
And some linker flags to the native library of your app only:

LOCAL_LDFLAGS += -Wl,--gc-sections
Provided that you export all public entry points to your app's native library with JNIEXPORT, this will significantly reduce the size of your native .so files without breaking anything, by dumping unused code and dumping all symbol information except for the public symbols you defined. Multiplied by the number of CPUs you build for (armv7, armv7-eabi, x86..) you will end up saving one to several megabytes in the compressed apk. If your native library stops loading after you rebuild it with these flags, again make sure that all the public entry points (the ones referenced by your java code in your native{} declarations) are declared with JNIEXPORT.

2. Recompress your pakfiles

If you are using a pakfile with all of your assets (if you're not, why aren't you?), and use deflate/zip, note that there are better compression tools than zip itself, that still allow decompressing with the same libraries and tools.

Hot tip: compress your pakfile with 7-zip in zip mode instead, and save 10-15% on the compressed size of your assets, without increasing decompression time or changing anything in your runtime.

Example command line to create a zip archive with 7-zip (the free tool is available on PC and Mac):

7z a -tzip -r -mmt=4 -mx=9 data.zip data
Expand your device compatibility

This tip is really counter-intuitive, but so is most of Android. If you are using ad networks to monetize your app for instance, you are most probably declaring some permissions, such as:

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
When you request those permissions, Android by default requires your app to have the corresponding hardware, such as WiFI and GPS for geolocation. Devices that do not declare those capabilities (either because they don't have them, or more often, because of an incomplete manifest from the manufacturer) will not see your app in the play store at all.

The solution is to declare that hardware as not required by adding a few extra lines to your app manifest. If your app doesn't itself use, or can potentially live without a bunch of hardware requirements, you may be able to increase device compatibility by currently up to 1000 devices by copy-pasting the few lines below just above your <application> tag. If your app requires some of that hardware, you'll want to delete the corresponding declarations.

<uses-feature android:name="android.hardware.bluetooth" android:required="false" />
<uses-feature android:name="android.hardware.location" android:required="false" />
<uses-feature android:name="android.hardware.location.gps" android:required="false" />
<uses-feature android:name="android.hardware.location.network" android:required="false" />
<uses-feature android:name="android.hardware.wifi" android:required="false" />
<uses-feature android:name="android.hardware.telephony" android:required="false" />
<uses-feature android:name="android.hardware.telephony.cdma" android:required="false" />
<uses-feature android:name="android.hardware.telephony.gsm" android:required="false" />
<uses-feature android:name="android.hardware.microphone" android:required="false" />
<uses-feature android:name="android.hardware.nfc" android:required="false" />
<uses-feature android:name="android.hardware.sensor.barometer" android:required="false" />
<uses-feature android:name="android.hardware.sensor.compass" android:required="false" />
<uses-feature android:name="android.hardware.sensor.light" android:required="false" />
<uses-feature android:name="android.hardware.sensor.proximity" android:required="false" />
<uses-feature android:name="android.hardware.camera" android:required="false" />
<uses-feature android:name="android.hardware.camera.flash" android:required="false" />
<uses-feature android:name="android.hardware.camera.front" android:required="false" />
That's all you need to do! Build and upload a new version to the store and in the changes summary window, the store will denote the increase in supported devices.

Happy hacking and happy holidays to you and your families!

Comments

Sign In or Register to comment.