Optimising Android application before release
JavaAndroidOptimizationJava Problem Overview
I'm in a "special" situation about efficiency of my program. Now I'm at a phase where I need to improve the performance of the application and reduce battery consumption.
Before the question:
- First of all, my application work. It runs fine - no errors whatsoever.
- Secondly, I have read Optimizing Battery Life on Android developers website and I have optimised small things they've requested. No problems whatsoever.
Now, I'm curious to know about other developers' special fixes which they have used to optimise their own applications. Stuff that users may never recognise or pay attention to. However, the fixes will either increase the battery life or help improve maintenance of the application.
So, what's your unique optimizing trick(s)?
I'm in a particular situation where I'm really looking for knowledge and I think this will be a great opportunity to share developers knowledge about a situation they've all been in.
Please, vote up great answers as that will encourage great developers to share their knowledge.
Java Solutions
Solution 1 - Java
At some point you are going to get to the point where using known tricks will hit their limits. The best thing to do at this point is profile your code and see what areas are the bottle-necks based on your specific requirements.
Investigating RAM usage using MAT and Using Traceview: an article on how to use the tools to profile your application.
Solution 2 - Java
Track and squash allocations. The more you allocate, the more often the garbage collector will need to run, stopping your process from doing anything else for relatively long periods of time, such as 100ms or so.
The best tool I know for this is the Allocation Tracker included in DDMS.
Not only GC can have an impact on the user experience, but superfluous allocations and GC do consume some computing resources.
Here's an example and a small trick. In my app, I have a clock which shows the current (audio) time, including tenth of seconds. This is updated often. And TextView performs allocations internally whenever you call setText() with a CharSequence. But it doesn't allocate anything with the setText(char[] text, int start, int len) variant. This isn't documented, and no one answered when I asked about it.
There are many ones like this. And this is one of the reasons why my app contains 50% native code (but there are other reasons).
Apart from this, I can recommend that you experiment with ProGuard. It performs several optimization passes, and logs such informations as unused methods within the project, which can help you removing leftovers in your code.
Solution 3 - Java
If your app will have a lot of screen time, use black wherever you can. That will reduce the battery consumption of the worst part of the device: the screen, specially in the AMOLED phones and tablets.
Solution 4 - Java
For applications with multiple activities, check you are not restarting activities that just need to be brought to the front by using the appropriate Intent flags. Check that your heap is under control, and that unnecessary views, bindings and contexts aren't being created.
I find the best tool for showing you all these as the app runs is:
adb shell dumpsys meminfo 'your apps package name'
Solution 5 - Java
When using SQLlite, put special attention on indexes. Don't assume anything. I got tremendous speedups in Zwitscher, when I put indexes on columns commonly used for search.
Solution 6 - Java
A few tips that can help you optimize your app in terms of UI:
-
use
convertView
for list adapters - it would be very expensive if you create a new view insideAdapter.getView()
as this routine is called for every position in the list. UsingconvertView
lets you reuse the already created view. Good example (together with the use ofViewHolder
) can be found in ApiDemos. -
It might happen that your layouts are not fully optimized and can be improved (for instance by using merging or removing parents). Android tool layoutopt will find such a situation for you. It can be used with HierarchyViewer for inspecting individual views. More info here.
-
remove the background drawable - Android framework used to have (does it still have?) a problem with detecting what views should be drawn. There is a chance that your (default) background drawable will be drawn only to be subsequently hidden by your opaque UI. To get rid of this wasteful drawing simply remove background drawable.
It can be done using a custom style
<resources>
<style name="Theme.NoBackground" parent="android:Theme">
<item name="android:windowBackground">@null</item>
</style>
</resources>
A few tips that can help you optimize your app in terms of battery usage:
-
check networking type and wait until user gets in the area with wifi or 3G (and not roaming) and only then allow him to use connection
-
use gzip for textual data whenever possible to speed up download and parsing
-
recycle complex java objects such as
XmlPullParserFactory
/BitmapFactory
/StringBuilder
/Matcher
etc.
For more battery tricks see Coding for Life - Battery Life, That Is.
Solution 7 - Java
Something to think about: DO NOT overuse String, for example in a huge loop. This will create a lot of String objects that have to be GC'ed. The "Bad coding" example will produce 2 string objects every loop. Next example will produce only one final String and a single stringbuilder. This makes a huge difference when optimizing huge loops for speed. I used stringbuilder a lot when making my Wordlist Pro Android app, and it got really speedy when going through 270000 words in no time.
//Bad coding:
String s = "";
for(int i=0;i<999999;i++){
s = "Number=";
s = s + i;
System.out.println(s);
}
//Better coding
final String txt = "Number=";
StringBuilder sb = new StringBuilder();
for(int i=0;i < 999999;i++){
sb.setLength(0);
sb.append(txt);
sb.append(i);
System.out.println(sb);
}
I wrote a more extended blogpost about the matter. read here
Solution 8 - Java
I guess using "final" variables everywhere where it's possible could also improve execution speed.
Solution 9 - Java
Optimize your PNG pictures with tools like OptiPNG and PNGCrush to shave off some (kilo)bytes from APK size. Image optimization tips for websites apply here too: use appropriate picture formats, play with JPG compression, consider using binary transparencies instead of 8-bit transparencies etc.
If you ship big PNGs with alpha channel, you can trade some APK size for startup speed and use separate JPGs for RGB and A channels.
If you're making HTTP connections, check that your HTTP client utilizes content compression. If it caches received HTTP responses, check that it understands and uses caching-related HTTP headers correctly.
Solution 10 - Java
If you have network operations try re-using same httpclient instance. Avoid using regular expressions.
Solution 11 - Java
Try using DDMS to track all the threads running in the system. For example i have noticed that I was using webview to display html content, i noticed that it creates few threads for cookie management session management etc..which increased my memory foot print. So unless you have a serious need for displaying complex html try using normal utility class "Html" in android to display html content. This might be useful for people who are displaying Eula since eula typicall contains html text.
If you have to do network operations try using AndroidHttpClient if you are beginner, it has got some good capabilities for Caching SSL sessions and all it really helps in improving your performance. Always set your socket connection timeouts to something around 60 seconds or some finite values because infinite timeouts can cause deadlocks especially if you drop your connection during ssl handshake.
Solution 12 - Java
Use the Android Resource Tracker to find unused resources in your project that can be deleted.
Solution 13 - Java
Avoid using XPath if you can parse your XML input by using string manipulation routines to get the text between the tags. I have tested and can confirm a 10x improvement in this case, on a 50000 items data set, on a HTC Desire.
Solution 14 - Java
I know I am joining a bit later to this conversation but it would be perfect to have a lot of good tips in one place, so I hope this thread will be alive and updated pretty often. My tips:
- Don't block UI thread with expensive jobs, user will leave if there is no response from app (use AsyncThreads).
- Use the LINT, new tool which scans Android project sources for potential bugs.
..will be updated..