5

I have implemented an Android application using Xamarin:

The size of the .apk is 13.6MB with:

  • Configuration: Release
  • Linking: Sdk Assemblies Only
  • Suported architectures: armeabi,armeabi-v7a

Here is the overview of sizes of the main components taken from the compiled .apk:

(these are the uncompressed sizes, I unarchived the .apk to a directory and looked to the files in Windows Explorer):

  • classes.dex (1.23 KB)
  • the two libmonodroid.iso (armeabi + armeabi-v7a) (5.58 MB)
  • all Mono.xxx.dll (3.89 MB)
  • mscorlib.dll (1.51 MB)
  • all System.xxx.dll (2.56 MB)

  • My app assemblies (the Droid app + one PCL) (204 KB)

  • MvvmCross + plugins (599 KB)
  • Xamarin ActionbarSherlock (348 KB)
  • ZXing.monoandroid (413 KB)
  • PCL Newtonsoft.Json (398 KB)
  • PCL Microsoft HTTP Client libraries (System.Net.Http.dll) (110KB)

  • 'res' folder (Size: 451KB Size on disk: 816KB) - because some files are 1KB they produce fragmentation, so Actual size vs Size on disk is significantly different

  • all PNG files (Size: 325KB Size on Disk: 496KB on disk)

What can I do in order to reduce the size of the compiled .apk?

I find it pretty big.

SeyedPooya Soofbaf
  • 2,654
  • 2
  • 29
  • 31
WriteEatSleepRepeat
  • 3,083
  • 3
  • 33
  • 56
  • 3
    Did you include any icons or splashscreens in the .apk? – joostmakaay Dec 13 '13 at 14:58
  • Some of these libraries are redundant to Android's libraries like Newtonsoft.Json and System.Net.Http. – Corey Ogburn Dec 13 '13 at 15:00
  • @CoreyOgburn good point but I am using the PCL version of the libraries, they are refernced by my PCL assembly; I updated my list. – WriteEatSleepRepeat Dec 13 '13 at 15:10
  • I'd say do a sanity check and do a 'du -m' on your apps root directory. Flush out any big files that you may not be thinking of. With just small amounts of code apps should really be in the 1-3 MB range. – Erik Kerber Dec 13 '13 at 15:20
  • @ErikKerber that's a unix command. this is a Xamarin Android app. I am looking to the unarchived .apk. – WriteEatSleepRepeat Dec 13 '13 at 15:36
  • Sigh... it's a command that works on OS X or any POSIX system. If you're stuck in Windows-World, then there's WinDirStat. The point is there is you are either *not* doing any linking, or there is something that you are packaging up that you are not disclosing above. – Erik Kerber Dec 13 '13 at 15:55
  • @ErikKerber there isn't anything I am not aware of in terms of resource files or anything like that – WriteEatSleepRepeat Dec 13 '13 at 15:57
  • 3
    13MB is a mean size of a normal Xamarin.Android app. I never managed to get lower than 8MB on Android. On iOS i managed to get 4 MB. – Softlion Dec 14 '13 at 22:39
  • @Softlion thanks for sharing your experience, it's helpful – WriteEatSleepRepeat Dec 15 '13 at 14:52
  • @AndreiN. Have you reduce your apk size ? If yes, please tell me how can I also ? – Ajay Sharma Jan 12 '16 at 10:43
  • 13mb is good. Mine is around 20mb and it includes almost no images and just v4 and v7 libraries + Newtonsoft.Json and Picasso. – Vahid Amiri Jul 15 '16 at 12:46

1 Answers1

2

Use linking: Sdk + User Assemblies, and go through the difficult process of marking classes with the Preserve attribute (see http://docs.xamarin.com/guides/ios/advanced_topics/linker/). You can check which class is missing when your app crashes in the android log. It should be only the classes used dynamically by reflection or using an IoC.

You can also create 2 separate packages, one with armeabi only (for very old devices), one with armeabiv7a, and one with x86 (currently your app will just crash on x86 android devices). Google play supports having 3 separate packages with different capabilities (don"t forget to change the capabilities in your manifest file for each package)

Softlion
  • 12,281
  • 11
  • 58
  • 88
  • awesome answer. I was aware already of these options. 2nd option looks easy and really viable. 1st one however I don't think it's so easy. Imagine a very specific class which get used ONLY in a specific moment and scenario in the app. Requires testing thoroughly and repeat it for each new feature or modification done in the app. I will wait a bit more before marking your comment as answer. thanks again – WriteEatSleepRepeat Dec 15 '13 at 14:29
  • I wonder why when using Sdk + User Assemblies the Linker is not able to know by itself the classes being used. If it's too much – WriteEatSleepRepeat Dec 15 '13 at 14:53
  • It knows classes being used, but not classes that are loaded dynamically, or instantiated through reflection. And it does not know methods called through reflection. There should not be much in your app. But sure, it is a hard process. – Softlion Dec 15 '13 at 15:07
  • yes, code which is dynamically loaded might be a bit out of scope for a linker, but maybe Xamarin or someone else writes a tool? I guess this means being able to parse the IL to catch dynamic loading. I probably won't do too much dynamic loading myself but the libraries I am using might be. – WriteEatSleepRepeat Dec 15 '13 at 16:13
  • If you use mvvmcross or an IoC then yes you use dynamic loading. Complete static analysis of dynamic programs work only in a functional language like F# or any lambda based program. See http://en.wikipedia.org/wiki/Lambda_calculus for further informations. – Softlion Dec 16 '13 at 14:01