You are on page 1of 19

12/2/13

40 Developer Tips for Android Optimization - OpenSignal

OpenSignal Blog
40 Developer Tips for Android Optimization
Posted on July 30, 2013 by James

Heres a good way to get into Android programming: Find some code that does something similar to what you want to do Adjust it to try to make it do your thing Watch it fail Troubleshoot using StackOverflow Repeat the process for the each feature you want to add. This method will keep you motivated and, because you keep iterating, youll also learn a lot without realising it. However, youll need to go a bit further when you release the app. To go from having some code that works pretty well to having an awesome app is a big jump, much bigger on Android than it is on iOS. When publishing on iOS your app jumps from one device your phone to a lot of devices that are pretty similar same size screen, all with pretty good hardware, 95% running the same OS version. On Android, your app leaps into the void. Your app must be able to handle whatever comes its way: in terms of screens, processor, custom OS, API level, and any other device specific quirks. Here are my personal tips for making Android awesome.

Targeting screen size and resolution


There are currently over 100 different screen sizes on Android, and an even greater profusion of resolutions. To make your app look good on different screen configurations there are two things youll need to make sure of: 1. You have a good layout or structure for different screen sizes

opensignal.com/blog/2013/07/30/40-developer-tips-for-android-optimization/

1/19

12/2/13

40 Developer Tips for Android Optimization - OpenSignal

2. Your images work well at different resolutions These are independent tasks, you might have a super tablet layout, but your graphics could look horribly bobbly on it. Well look at them in turn.

Designing layouts for multiple screen sizes


Tip 1: ScrollViews and ListViews are an easy win. While there are a huge array of screen sizes, most of the variation for phones at least is in the screen height. For this reason ScrollViews and ListViews work well. Theyre not appropriate for all views, however. For the dashboard tab in OpenSignal users should see everything all in one go, without scrolling. For the more advanced stats tab, scrolling is not such a bad thing. If you can design your layouts so they work well across all screens without using a scrollview, do so, but its an easy way of making sure it works on a lots of screens.

Dashboard style screens shouldnt scroll Tip 2: Use the folder structures. The resource folder structure is powerful in Android, it allows you to vary images/strings/layout files/dimensions/colours depending on the api level/language/screen size/screen resolution among other things. Heres an example of some of the things you can do with it:

opensignal.com/blog/2013/07/30/40-developer-tips-for-android-optimization/

2/19

12/2/13

40 Developer Tips for Android Optimization - OpenSignal

In values-small (above) I have a bools.xml file, this contains a line:


< r e s o u r c e s >

< b o o ln a m e = " s m a l l _ s c r e e n " > t r u e < / b o o l >

< / r e s o u r c e s >

opensignal.com/blog/2013/07/30/40-developer-tips-for-android-optimization/

3/19

12/2/13

40 Developer Tips for Android Optimization - OpenSignal

In the code I reference that like so:


i f ( g e t R e s o u r c e s ( ) . g e t B o o l e a n ( R . b o o l . s m a l l _ s c r e e n ) ) { g e t S u p p o r t A c t i o n B a r ( ) . h i d e ( ) ; }

On small screened devices that boolean is found to be true and I hide the ActionBar to save space. This is actually using the marvellous ActionBarSherlock, more on that later. In values-sw360dp so for screens wider than 360dp I have
< r e s o u r c e s >

< b o o ln a m e = " s m a l l _ s c r e e n " > f a l s e < / b o o l >

< / r e s o u r c e s >

For large screens, the ActionBar is not hidden. I dont need to include the bools.xml file in values-sw400dp, because of the way that the OS searches for resources. For example for a device of width 600dp (600/160=3.75 inches, so this is what we generally call a 7 tablet) the OS will look for a bools.xml in values-sw600dp and fail, look again in values-sw400dp and fail, then look in values-sw360dp and look no further. Tip 3: 160dp = 1 inch. 320 dp = 2 inches. dp == dip Tip 4: you can use these folder structure tricks for all resource types For example you can use the system of appending folder names for XML layouts e.g. layout-sw360dp can be used if you have a layout file you want to target to screen width 360dp. If you want to switch the layout between portrait and landscape you can go one step further: layout-sw360dp-land layout-sw360dp-port But wait, half your users will speak Arabic? You probably want to flip your layout right

opensignal.com/blog/2013/07/30/40-developer-tips-for-android-optimization/

4/19

12/2/13

40 Developer Tips for Android Optimization - OpenSignal

to left, try: layout-sw360dp-land layout-sw360dp-port layout-sw360dp-land-ar layout-sw360dp-port-ar The first two files will get served for all other languages, your -ar files just for Arabic. Tip 5: Resource rules of thumb: XXX // i.e. no append to the folder name: default use this for Nexus One, Droid 2, S2 XXX-sw360dp // larger phones Galaxy Nexus, S3, S4 XXX-sw600dp // 7 tablets XXX-sw720dp // 10 tablets For Kindle devices things differ, use: XXX-large-mdpi // kindle fire 7 XXX-large-hdpi // kindle fire 7 HD Tip 6: you dont have to tailor all your layout files, you could instead tailor the dimens.xml files. In the screenshot a few paragraphs up, youll notice that I have a lot of dimens.xml files in my values folders, thats because I prefer to work with a single set of layout.xml files, within each layout file I have code like:
< I m a g e V i e w a n d r o i d : l a y o u t _ c e n t e r H o r i z o n t a l = " t r u e " a n d r o i d : l a y o u t _ m a r g i n T o p = " @ d i m e n / s m a l l _ m a r g i n " a n d r o i d : l a y o u t _ w i d t h = " @ d i m e n / d a s h B o a r d W i d t h " a n d r o i d : l a y o u t _ h e i g h t = " @ d i m e n / d a s h B o a r d H e i g h t " a n d r o i d : i d = " @ + i d / d a s h b o a r d " / >

Where e.g. small_margin is defined in a dimens.xml file:


< r e s o u r c e s >

opensignal.com/blog/2013/07/30/40-developer-tips-for-android-optimization/

5/19

12/2/13

40 Developer Tips for Android Optimization - OpenSignal

< d i m e nn a m e = " s m a l l _ m a r g i n " > 4 d p < / d i m e n >

< / r e s o u r c e s >

That 4dp varies between all the dimens files. I have an Excel file that creates all these different dimension definitions based on scaling up by a certain factor. You might ask: why not just let the Android OS handle all the scaling? Wy not, instead of hardcoding all values, just use one values folder and one layout folder? That would work, everything would get scaled if it was properly set up, but some elements look stupid scaled. Tip 7: Let whitespace scale more than graphics. Let graphics scale more than buttons. Buttons, checkboxes, toggles look stupid when scaled up. A button thats 100dip (0.63) on a phone does not want to become 200dip (1.25) on a tablet of twice the screen width. Just because the screens are bigger, it does not mean that tablets are used by giants. Instead, let the space between buttons increase while your shiny dials and images expand. Tip 8: Use the GraphicalLayout tool for fast previews. GraphicalLayout is the WYSIWG editor for XML files. I prefer to write all my elements directly instead of dragging and dropping but after adding some elements, test out your layout on various screen sizes by toggling the GraphicalLayout selecting from the dropdown.

opensignal.com/blog/2013/07/30/40-developer-tips-for-android-optimization/

6/19

12/2/13

40 Developer Tips for Android Optimization - OpenSignal

Lots of options, use them.

Scaling Images
Tip 9: Dont scale all your images. Getting the layout files to adjust to different screen-sizes is just half the battle, the elements themselves (e.g. images) must work when blown up onto high-res screens. The conceptually simplest way of doing this is to produce a whole host of images and pop them into a matching plethora of drawable folders: drawable-sw600dp-ldpi drawable-sw600dp-mdpi

opensignal.com/blog/2013/07/30/40-developer-tips-for-android-optimization/

7/19

12/2/13

40 Developer Tips for Android Optimization - OpenSignal

drawable-sw600dp-hdpi drawable-sw600dp-xhdpi drawable-sw600dp-xxhdpi And the same for other screen widths. Dont do this. You will go insane in the membrane. Having drawble-ldpi, drawable-hdpi, etc. folders might be worthwhile, but you dont necessarily need to have all of them. Tip 10: Avoid bitmaps (jpg, png). For some images such as icons bitmaps might be the best option, as they are simple to include. But where possible avoid them, you can save a lot of space and achieve much sharper results by using different methods. Tip 11: Use XML Drawables. Wherever you can use XML drawables instead of bitmaps. XML drawables wont let you do everything, but I was surprised by how flexible they are. Android developer docs have a full overview, but herere some tasters:
< s h a p e x m l n s : a n d r o i d = " h t t p : / / s c h e m a s . a n d r o i d . c o m / a p k / r e s / a n d r o i d " a n d r o i d : s h a p e = " r e c t a n g l e ">

< c o r n e r s a n d r o i d : b o t t o m R i g h t R a d i u s = " 1 4 d p " a n d r o i d : b o t t o m L e f t R a d i u s = " 1 4 d p " a n d r o i d : t o p L e f t R a d i u s = " 1 4 d p " a n d r o i d : t o p R i g h t R a d i u s = " 1 4 d p " / >

< g r a d i e n t a n d r o i d : s t a r t C o l o r = " @ c o l o r / o f f _ w h i t e " a n d r o i d : e n d C o l o r = " @ c o l o r / p a l e _ y e l l o w " a n d r o i d : a n g l e = " 2 7 0 "

opensignal.com/blog/2013/07/30/40-developer-tips-for-android-optimization/

8/19

12/2/13

40 Developer Tips for Android Optimization - OpenSignal

a n d r o i d : t y p e = " l i n e a r " / >

< s t r o k e a n d r o i d : w i d t h = " 4 d p " a n d r o i d : c o l o r = " @ c o l o r / o s m _ d a r k e r b l u e " / >

< / s h a p e >

This defines a rectangle with rounded corners, a border (darker blue) and a gradient. In layout files you can set it whatever width you like and it will look crisp on any screen. Ideal for buttons. Tip 12: Use more XML Drawables. Just to get you a bit more excited about XML drawables, the radar background below is a rather more complex example:

opensignal.com/blog/2013/07/30/40-developer-tips-for-android-optimization/

9/19

12/2/13

40 Developer Tips for Android Optimization - OpenSignal

No bitmaps were harmed in the making of this UI (except the icons). Tip 13: Use yet more XML Drawables (with bitmaps if you must). How did we build the super cool icons for WeatherSignal the lightbulb that dynamically fills up depending on light intensity and the pressure needle that rotates? Here we used bitmaps in conjunction with XML:

opensignal.com/blog/2013/07/30/40-developer-tips-for-android-optimization/

10/19

12/2/13

40 Developer Tips for Android Optimization - OpenSignal

For the lightbulb we used two PNGs: icon_magnitude_min (an empty lightbulb) and icon_magnitude_max (one filled with light) and we dynamically cropped the latter. To set this up I used:

< l a y e r l i s tx m l n s : a n d r o i d = " h t t p : / / s c h e m a s . a n d r o i d . c o m / a p k / r e s / a n d r o i d " >

< i t e m a n d r o i d : d r a w a b l e = " @ d r a w a b l e / i c o n _ m a g n i t u d e _ m i n " / >

< i t e m>

< c l i p a n d r o i d : c l i p O r i e n t a t i o n = " v e r t i c a l " a n d r o i d : d r a w a b l e = " @ d r a w a b l e / i c o n _ m a g n i t u d e _ m a x " a n d r o i d : g r a v i t y = " t o p " / >

opensignal.com/blog/2013/07/30/40-developer-tips-for-android-optimization/

11/19

12/2/13

40 Developer Tips for Android Optimization - OpenSignal

< / i t e m >

< / l a y e r l i s t >

In the java I get I reference to the clipdrawable and control its level based on light intensity. Tip 14: Why use 9-patch (when you can use XML drawables)? Android have the option to use 9-patches to define drawables, a number of tutorials illustrate how to use them to make a button that can stretch while keeping the same corners (and avoiding pixellation). If you know how to use 9-patches already, perhaps from web design, then they might be worth using. If youre unfamiliar with 9-patches I would advocate remaining that way. Creating 9 patches is more involved than creating most bitmaps and if you want to adjust anything e.g. corner radius or the colours, its back to the graphics editor. Much of what 9-patches are used to achieve can be done through XML. Tip 15: Create custom views by overriding onDraw(). There are some things XML just isnt so great at, we draw a lot of graphs in OpenSignal and WeatherSignal and there are libraries for this, but we coded our graphs custom. Its kind of fun. You might never need to do it, but to make graphics that are highly dynamic and custom it is often the only way to go. Tip 16: Use SVG where you cant use XML. Sometimes overriding onDraw() and painstakingly coding up all the lines and arcs you need to draw your custom view is overkill. After all, there is a language for vector graphics, its called Scalable Vector Graphics. Its what powers one of the coolest Android apps ever Androidify. In fact they built the library just for that app, and they released it here: SVG for Android Its what we used to draw the dashboard in OpenSignal. Tip 17: GZip your SVG files. Makes them smaller and they parse quicker. Tip 18: The SVG library doesnt support everything. In particular some alpha channels dont seem to work, you may even have to edit them out in the code.

opensignal.com/blog/2013/07/30/40-developer-tips-for-android-optimization/

12/19

12/2/13

40 Developer Tips for Android Optimization - OpenSignal

Targeting consistent appearance across all Androids versions


Tip 19: On some Android OSs (TouchWhizz/HTC Sense/MotoBlur etc) the default buttons and other UI widgets will look very different to how they look on stock Android. I wish it werent so, but there it is. Tip 20: Customise your UI widgets. To make sure your app looks the same on all devices, youll need to customise everything, its not as hard as you might think and in doing so youll get a lot more control over how your app looks. Tip 21: Selectors are super for building buttons. We saw above how to define a button background in XML, but what do you do to create a button that changes when clicked? Easy: define the background to be an XML file as below, which will receive the button state and serve up the appropriate drawable.
< ? x m lv e r s i o n = " 1 . 0 "e n c o d i n g = " u t f 8 " ? > < s e l e c t o rx m l n s : a n d r o i d = " h t t p : / / s c h e m a s . a n d r o i d . c o m / a p k / r e s / a n d r o i d " >

< i t e ma n d r o i d : s t a t e _ p r e s s e d = " t r u e "a n d r o i d : d r a w a b l e = " @ d r a w a b l e / b t n _ b g _ s e l e c t e d "/ > < i t e ma n d r o i d : s t a t e _ f o c u s e d = " t r u e "a n d r o i d : d r a w a b l e = " @ d r a w a b l e / b t n _ b g "/ > < i t e ma n d r o i d : d r a w a b l e = " @ d r a w a b l e / b t n _ b g "/ >< ! -d e f a u l t>

< / s e l e c t o r >

Tip 22: The ActionBar and many animation styles didnt exist pre Honeycomb, use ActionBarSherlock and NineOldAndroids instead. Jake Whartons Android libraries are a tour de force of backwards compatibility. As a bonus, it ABS also gives you more power of customising the ActionBar.

Targeting speed
Tip 23: Test on slow phones. Youll not only see any problems with slowness, but theyll drive you nuts, no-one likes a slow app.

opensignal.com/blog/2013/07/30/40-developer-tips-for-android-optimization/

13/19

12/2/13

40 Developer Tips for Android Optimization - OpenSignal

Tip 24: Keep your XML layout hierarchy flat. More layers means the system does a lot more work parsing your code and it can take views longer to deploy. Tip 25: Use Android Lint. Right click on project folder in Eclipse>Android Tools>Run Lint. This can catch a host of things that can improve speed, or just make your code cleaner. Tip 26: Android Lint can get it wrong. It can suggest things that will break your code in subtle ways, so do understand what it suggests before you make changes. Tip 27: Using <merge> can help flatten your view hierarchy. Simple way of getting rid of superfluous layers. Great post explaining this and the difference it makes on Android Developers. Tip 28: Use HierarchyViewer to see your layout hierarchy in its gory glory. This is a brilliant tool which shows just how many layers of layouts you have and which of them are slowing things down. Tip 29: Use RelativeLayout whenever you can. AbsoluteLayout is deprecated, dont use it. Often you will have a choice between RelativeLayout and LinearLayout, go with RelativeLayout as youll almost always end up with fewer layers in your view hierarchy. An example, suppose you want to make a view something like: Box A takes up left half of the screen | Box B takes up right half of the screen Your first instinct is probably to use: <LinearLayout android:layout_width=match_parent android:layout_height=wrap_content android:orientation=horizontal > <TextView android:text=Box A takes up left half of the screen android:layout_width=0dip

opensignal.com/blog/2013/07/30/40-developer-tips-for-android-optimization/

14/19

12/2/13

40 Developer Tips for Android Optimization - OpenSignal

android:layout_height=wrap_content android:layout_weight=1 /> <TextView android:text=Box B takes up left half of the screen android:layout_width=0dip android:layout_height=wrap_content android:layout_weight=1 /> </LinearLayout> That works just fine, but you could also use: <RelativeLayout android:layout_width=match_parent android:layout_height=wrap_content android:orientation=horizontal > <TextView android:text=Box A takes up left half of the screen android:layout_width=match_parent android:layout_height=wrap_content android:layout_toLeftOf=@+id/dummy_center /> <View android:id=@+id/dummy_center android:layout_width=0dip android:layout_height=0dip android:layout_gravity=center /> <TextView android:text=Box B takes up left half of the screen android:layout_width=match_parent

opensignal.com/blog/2013/07/30/40-developer-tips-for-android-optimization/

15/19

12/2/13

40 Developer Tips for Android Optimization - OpenSignal

android:layout_height=wrap_content android:layout_toRightOf=@+id/dummy_center /> </RelativeLayout> This second form doesnt look much better than the first, in fact it looks worse: weve introduced a whole new element. But suppose we want to add in image into each box, schematically: Box A takes up left half IMAGE | Box B takes up right half IMAGE Pursuing the first method, youd need to introduce a second level of LinearLayouts, pursuing the second you could put your images directly into the same RelativeLayout for example by specifying that the first image should be to the left of dummy_center and TextView A should be to the left of that. So youd have 7 elements across 3 levels of view hierarchy (LinearLayout way), versus 6 elements across 2 levels (RelativeLayout). All this stuff adds up. Tip 30: Use external profilers as well as DDMS. These help you see unnecessary network calls, watch power usage, garbage collection, state changes (e.g. when onStop and onDestroy are called). LittleEye is my current favourite. Tip 31: Use AsyncTasks. The Android team must have got so fed up with people making network calls on the UI thread that they turned it into a compile error a few API levels back. But theres probably a lot of other work in any app that can be take off the UI thread, allowing layouts to render faster and improving its responsiveness.

Targeting low file size


Tip 32: Some Android devices have a 100mb limit. Things are changing, but theres still a lot of users out there who will have to think a lot about whether a 5Mb app deserves its space. If you allow users to install to the SD card, its not a problem but you shouldnt allow this if your app needs to start onBoot (e.g. for most widgets). Even for newer devices, users are going to be happier if your APK is small so it

opensignal.com/blog/2013/07/30/40-developer-tips-for-android-optimization/

16/19

12/2/13

40 Developer Tips for Android Optimization - OpenSignal

downloads quicker. Tip 33: Use XML resources (last time I recommend this, I promise) These save a tonne of space over PNGs, as you only need one for many screen configurations and a single XML file is almost always smaller than a PNG showing the same thing. Tip 34: When you must use PNGs always optimize (with PNGCrush or ImageOptim)

Targeting bugs
Tip 35: On the Android developer console check for any bugs that have been sent automatically. Tip 36: ProGuard is turned on by default now. Proguard is awesome (speeds up your app and reduces filesize) but it can make StackTraces very obscure. Youll need to retrace the StackTraces, to do this youll need to hang onto the Proguard mapping files created on each build, I put them into a folder with the version codes name. Tip 37: Adjust ProGuard config to show line numbers in StackTraces. Make sure your proguard.cfg has a line: -keepattributes SourceFile,LineNumberTable Tip 38: Use staged rollouts Test the waters on 5% of devices, watch for bug reports. Tip 39: Use a device testing lab Device Anywhere and Perfecto Mobile offer virtual testing labs where you can log onto a real device. I find them sort of clunky and often the devices are kind of messed up by being so unceasingly tested on. If you work out of a co-working centre, or have several Android developer friends get a device pool going. Tip 40: More code less blog posts. Nah, sharing is caring, I just cant think of a 40th.

opensignal.com/blog/2013/07/30/40-developer-tips-for-android-optimization/

17/19

12/2/13

40 Developer Tips for Android Optimization - OpenSignal

2 Responses to 40 Developer Tips for Android Optimization


Dreamics says:
August 3, 2013 at 5:43 am

Hi There Thanks for the great post. I was hoping you guys can answer a few detailed question Which devices do you guys focus on making sure you app is good? What is average time consumption on each devices and how many engineers? Any specific devices you guys outsource to third party services? Best Jason Z.
Log in to Reply

James says:
August 4, 2013 at 11:21 pm

Hi Jason, We do everything with one Android coder (me) and we dont outsource anything. I personally use an S4, Galaxy Nexus and a HTC Wildfire. The Wildfire is good because its a popular device, but a lot lower CPU and a small screen. Those 3 phones I test on a lot. I also use an old HTC Hero (even slower than the Wildfire) and a HTC Desire. We also have an S3 in the team. Its obviously important to make sure the really popular devices (S3, S4, HTC One etc) work well with your app, that doesnt mean you need to have all of them, but it certainly helps if you have a device with that screen size. Generally Android coders have pretty good Android phones, Id recommend they also invest in a low end device that runs a different Android skin (e.g. if they have stock Android Galaxy Nexus, get a Galaxy Ace or something low end that runs TouchWiz) as the skin might change the way your app looks, and sitting within a different skin your app will definitely feel different anyway. Best, James
Log in to Reply

OpenSignal

opensignal.com/blog/2013/07/30/40-developer-tips-for-android-optimization/

18/19

12/2/13

40 Developer Tips for Android Optimization - OpenSignal

Home Android iPhone About Jobs Blog Reports

Forum Developer Network coverage maps Knowledgebase Contact Insights for Operators

Download our Apps

Sign up for our newsletter


Email Sign up

Like us on Facebook
Thch 1.445 ngi thch ni dung ny. Hy l ngi u tin trong s bn b ca bn.

Latest News
We built an Android Arduino Cake
Posted on November 7, 2013 by Samuel

A glance at the Ofcom infrastructure report


Posted on November 1, 2013 by Samuel

Solar Interference: the cause of dropped calls?


Posted on October 11, 2013 by Samuel

How do the Big 4 compare for LTE in the biggest US cities?


Posted on October 10, 2013 by Samuel

PotterMad: Harry Potter Themed WiFi Names


Posted on September 13, 2013 by Samuel

Copyright 2013 OpenSignal, Inc. All rights reserved.

opensignal.com/blog/2013/07/30/40-developer-tips-for-android-optimization/

19/19

You might also like