Monday, June 8, 2015

Developing for Android VIII The Rules: User Interface

Hot off the press (do people even say that anymore), the latest installment from Google Developers - Developing for Android VIII The Rules: User Interface.

tl;dr : Some important UI details and patterns as they pertain to user experience and performance (which are related).


  • Avoid Overdraw 
    • Enable Debug GPU overdraw in developer settings
    • Avoid opaque views covering other views
  • Avoid Null Window Backgrounds (had not thought of this much before)
    • Eliminating can be valid, but introduces new issues trying to solve overdraw.
    • Instead of setting background in manifest, set background in onCreate() by doing getWindow().setBackground(null) - warning, this can cause issues.
    • The correct way is to use the starting window with the background you want!
  • Avoid disabling Starting window
    • This causes the slow start time of the app. 
    • use a custom drawable if necessary to customize the starting window
  • Allow Easy Exit from Immersive Mode
    • Unless in a game, make it easy to leave immersive mode by tapping. 
    • Check the developer guide (link in the article)
  • Set Correct Status/Navigation Bar Colors in Starting Window
    • Theme the Starting window as you would your app.
      • android:statusBarColor
      • android:navigationBarColor
    • For the activity you can modify them via onCreate
      • getWindow().setStatusBarColor()
      • getWindow().setNavigationBarColor()
  • Use the Appropriate Context
    • For UI context, use activity context, not application.
    • For resources for your activity, use activity context.
  • Avoid View-Related References in Async Callbacks
    • Avoid referencing View/Activity/Fragment in network operation / long running async task. 
    • Consider using weak callbacks.. 
    • It also says consider an event bus, but I personally don't like the event bus because it does not honor the application lifecycle, and you must program around corner cases. (more on this later probably)
  • Design for RTL
    • As of API 17, applications should use start/end instead of left/right
    • You can enable RTL in Developer options
  • Cache Data Locally
    • "Cache Locally, Sync Globally"
    • You should create a local db that keeps data in a meaningful way (not just serialized server response).
    • Update your UI from local data whenever possible
    • Google I/O 2010 has video, Android REST Client Applicaitons. And personally once again, I would avoid the recommendation of an EventBus. Not even needed if you read your data from a db.
  • Cache User Input Locally.
    • Cache any user input locally, then send it to the server, this avoids it getting lost.. 
    • Have some UI indication that the data is pending vs. complete.
  • Separate Network and Disk Background Operations
    • Have two different thread pools one for network one for disk

Some of these things I was not aware of, partially because I had never done some of the 'don't do this' things.. Others I actively do (Syncing data), and other things were totally new, and a great idea, such as having two different thread pools.

Sunday, June 7, 2015

Developing for Android VII The Rules: Framework

Still keeping on track and trying to keep up with all these articles getting pumped out of Google Developers.. If anyone has any others for me to look at and tl;dr, let me know.

This article is entitled : Developing for Android VII The Rules: Framework - Basically going over Android specific APIs, how to use them, and how not to re-architect what is already there.

tl;dr : If Android framework provides a way to interact with interact with the operating system, use them (based on particular semantics with the OS). - Just read this one it is short enough..


  • Activities : top-level UI entry point into your app, there can be many entry points. Use activities when you want others (internal components / 3rd party apps) to launch specific portions of your app. 
  • Service : This component tells the OS you need a longer running operation outside UI.  Can be self running, running on behalf of others.. If you don't need that, use AsyncTask, Loader, HandlerThread. Also note that AsyncTask does not play as well with Activity lifecycle as a Loader.  Oh also, checkout IntentService too - not covered by this article, but something I wanted to point out.
    • Services should be bound or started (NOT BOTH)
    • Use services for processes with state and on-going lifecycle.
  • Broadcast Receiver : how applications can advertise they want to be notified of system events
    • Use broadcasts for delivering independent events
  • Don't pass large objects over binder (say a huge bitmap - send a URI to that bitmap instead).
  • Isolate UI from Background - think of music app w/ background service actually playing the music. 

Thats it, kind of a short article. Probably good to just read it over, can't wait to see what is next.. 



Thursday, June 4, 2015

Developing for Android VI The Rules: Storage

Totally forgot to post this previously, the blog has a new home - www.androidtldr.com - ok back to regularly scheduled programming.

Hot off the press - it was posted 3 minutes ago! The latest in the series : Developing for Android VI The Rules: Storage

tl;dr - Don't be lazy - It is easy while developing to start hard coding values for things such as file paths, or creating databases instead of tables in a database. Seriously, spend some time doing it right, your users and your app will thank you later!


  • Avoid Hard-coded File paths - Just don't!
    • Instead of /sdcard use APIs like Environment.getExternalStorageDirectory()
    • Instead of trying to hardcode application path, use Context.getDatabasePath() or Context.getFilesDir()
  • Persist Relative Paths Only - Backup/Restore as example
    • Save the relative path only, as user may change device.
    • Avoid heavy canonicalization except for security related reasons. 
  • Use Storage Cache for Temporary Files
    • Files which can be cached, store them in Context.getCacheDir()
    • Files in these folders can be deleted when space needs to be reclaimed by system.
    • Files are never backed up in this folder, unlike data directory which are backed up
  • Avoid SQLite for Simple Requirements
    • Using SQLite for storing some key/value pairs does not make sense, use SharedPreferences - Read the article for important notes about Memory Leaks w/ Shared Prefs
    • Use append-only log files, and rotate them periodically.
    • Use LevelDB if all you need is NoSQL and are comfortable with JNI (this is new to me)
  • Avoid Using Too many Databases
    • Most applications should have at most, one database
    • Besides, if you have one, then you can easily query across your tables.
  • Let your user choose the content storage location
    • Some devices have more than one storage location, utilize Storage Access Fragmework.
    • Use intents w/ content:// URI to open / save files. 
    • DocumentFile support library helps you adapt existing code to traditional file-style API.

This post is really quite good as storage is kind of boring, you set it up, you use it, and cross your fingers that it works. This particluar post gives some good tips, and good methods to use to get the right directory for your project, it also made me aware of LevelDB - had not heard of it before. I was also made aware of the Storage Access Famework.. Most of the work I do though does not involve users saving / opening files to the file system, more database/shared preferences.. But it is always good to have this information around as reference material so you can pivot and use best practicies when you need them. 

Developing for Android V: The Rules: Language and Libraries

The 5th in the series from Google/Android developers - Developing for Android V: The Rules: Language and Libraries.  This covers some core Java language and libraries.

tl;dr : This article I think starts to really dive into where traditional Java methodologies fails when running on Android, and you need to look at what is provided for you by the framework to achieve the same task while minimizing performance impacts.

  • Use Android-Appropriate Data structures - for smaller collections, use android (ArrayMap/SparseArray) which avoids autoboxing
  • Use Parcels not Java Serialization - Also talks about Persistable Bundles
  • Use JSON/XML for web services, use SQLite or SharePreferences to store the data
  • Avoid JNI - but if you don't here are some tips
  • Favor Primative Types.


I really don't have much to add to what they go over in this article, but I think Engineers with a Java background could gain quite a bit of information just from this one post that will probably help them in the future. It discusses Bundles, SharedPreferences, SQLite, PersistableBundle, JNI, and several collection classes on Android which should be used if possible. ArrayMap, SimpleArrayMap, SparseArray, SparseBooleanArray, SparseIntArray, SparseLongArray, and LongSparseArray.

What did I learn from this post? Probably to spend a bit more time when using collections, and see if I can find an Android specific one that suites the use case better.



Developing for Android, IV: The Rules: Networking

Google developers are at it again with part 4 in their who knows how many part series with Developing for Android, IV: The Rules: Networking

tl;dr: One of the largest consumers of battery is network / data transmission.
  • Be stingy when and how often you get your data. 
  • Use tools like GCM, JobScheduler/GCM Network Manager. 
  • Don't ever poll. 
  • Don't sync everything.
  • Don't assume the network is up
  • Use exponential backoff when requests fail
  • Develop for the low end network - slow / packetloss. 2G networks
  • Create mobile specific APIs which return the data that the user needs. 
Expanding on these bullet points, I think one which is overlooked the most, and probably requires the most work, is having mobile specific APIs. It may be fine for your website to make 5 different requests to look up data to render on a page, but if you have a native app, tailor the API to a single call, and only return the data that is needed by the client. I don't know how many times I have seen APIs where I have to request a second API to get some little bit of data that could have been included in the first, but I have to download a 80KB json file, and parse it just to get the single field. The other recommendations are fine, and can usually be handled by the mobile engineer. Getting the resources to customize / write new APIs for mobile can be a much larger challenge. Expend your engery on it, it will make your life much easier down the line, and make your users much happier. 

Developing for Android, Part III - The Rules - Performance!

The next post in the series is Developing for Android, III: The Rules: Performance.

tl;dr : While performance and memory are closely intertwined, this article is more about runtime performance not memory-related.  Some basics that come out of article are:

* Avoid Expensive Operations during Animations and User Interaction - this can cause Jank
   - Measurement and layout is an expenive operation
   - Inflation happens on UI thread, and can be expensive (larger view hiearchy, more expensive)

* Launch Fast - User expects lightning fast feedback that the app is running
   - Android uses a Starting Window, which is blank but applies the applications theme (can have a specified background drawable)
   - Don't just use Starting window if your app takes seconds to deliver content.
   - Use a ViewStub as placeholder for views which can be expanded later, Avoid expensive ops like decoding large bitmaps.
   - Avoid Memory Churn
   - Avoid initilization code in your Application Object.

* Avoid Complex View Hiearchies - Find cheaper ways to represent nested content
   - Might try a custom view
   - If user can interact with an element (touch, focus, etc.) then element should be its own view vs combined.

* Avoid RelativeLayout near the top of the View Hierarchy
   - Expensive
   - Requires two measurement passes (gets exponential for each nested RelativeLayout)
   - Consider GridLayout - pre-processes child view relationship to avoid double measurement

* Avoid Expensive Operations on the UI Thread
   - This includes onDraw() or onLayout
   - Don't try to call webservices from UI Thread (will throw NetworkOnMainThreadException)
   - Don't do db transactions
   - Consider using Loaders (which handle android configuration changes / lifecycle)
   - Enable Strict Mode in Developer Options
   - UI Thread should be used for mainipulating view properties & drawing, everything else should be async

* Minimize Wakeups
  - Consider disabling BroadcastReceivers if you don't care about them
  - Make sure you carefully choose which intents your app should respond to - don't be overly broad.

* Develop for the Low End
  - Your primary dev device should not be a high end device
  - You should have a variety of devices including those with 512MB memory & 768x480 or less resloution

* Measure Performance
  - Use the tools to track performance
  - Aim for 60fps


Wednesday, June 3, 2015

Developing for Android, II - The Rules: Memory

The second post from our lovely Android Developers at google is entitled : Developing for Android, II The Rules: Memory

tl;dr - Don't do this crap! (mostly) - Use of memory in an application can be the single most performance modifier. Major topics are listed below.
- Avoid Allocations in Inner Loops
- Avoid Allocations when Possible
- Avoid Iterators
- Avoid Enums
- Avoid Frameworks & Libraries not written for Mobile
- Avoid Static Leaks
- Avoid Finalizers
- Avoid Excess Static Initialization
- Trim Caches on Demand
- Use isLowRamDevice
- Avoid Requesting a Large Heap
- Avoid Running Services Longer than Necessary
- Optimize for Code Size


This article covers various topics from the amount of memory that is consumed to how much memory churn (causing garbage collection - gc) can have an effect on runtime performance. Some of these items seem like poor java coding, but they end up improving the performance. Some trade offs will need to be made in performance vs. code cleanliness. Here Some basic things that came out of the article, if any of these look interesting or 'wrong' go read the article, it will clear some things up :
> Don't allocate new objects during onDraw()
> Use a cached object (avoid allocations in inner loops)
> Static objects in android are static to the process, but maybe multiple activities in the process.
> If using object pools, consider different configurations for lower end devices based on api checks / isLowRamDevice()
> Arrays / Array lists that don't need to be resized often are a good choice.
> Consider using ArrayMap / SimpleArrayMap vs. HashMap, these are more optimized than HashMap, and support iterating over entries w/out iterator.
> Consider setting an initial size of collection to avoid automatic resizing as it grows
> Consider mutating objects vs returning them (which creates new allocations)
> Avoid object types when primatives will do.
> You can use SparseIntArray and SparseLongArray that use primatives.
> Avoid Arrays of objects - eg: instead of Point[]  have a int[] x and int[] y.
> Avoid Iterators - explicit (List.iterator() or implicit for (Object o: myObjects) )
> Avoid Enums.
> Avoid Frameworks / Libraries not written for mobile : these can cause increased memory use & gc
> Avoid Static Leaks : Avoid using where objects should not persist over life of process (lifetime of static variable != lifetime of activity)
> Avoid Finalizers : should ONLY be used when object holds a native pointer.
> Avoid Excess Static Initialization : lazy load when you need it
> Trim Caches : using with bitmaps in a LruCache
> Use isLowRamDevice : disable / enable memory intensive features based on device memory
> Avoid Requesting a Large Heap : Using this as first step for memory management will impact the device and overall user experience vs fixing the underlying issues.
> Avoid Running Services Longer than Necessary : If you don't need a service, shut it down. There are androidy ways to spool it back up.
> Optimize for Code Size : Less code to load, faster to download and run.. Use Proguard (or dexGuard), be cautious in your library usage, understand auto gen code cost, favor simple direct solutions vs creating lots of infrastructure and abstractions.