Previously in this series we’ve looked at various ways in which we can improve the experience for our user in terms of both simple aesthetics (making the app look nicer) and improving the controls and navigation through the app. In this final article in the series, we’ll focus on how we can speed the user directly to the content that they want as quickly as possible.
When we first developed the Bluetooth LE upon which we’ve based this series, the aim was to demonstrate the various steps that we need to go through in order to connect to and obtain data from the TI SensorTag device. However what works well as an explanation for developers does not necessarily make for something which will be well suited to an end user.
Although fairly simple, our app requires the user to perform a number of steps before they will see the temperature obtained from the SensorTag:
- They launch the app
- They start scanning for devices
- Wait for the device scan to complete
- Select one of the discovered devices
While this may not seem very much, let’s consider how the average end-user may differ from the developer. I have two SensorTag devices, so the ability to switch between them is an advantage, but a typical end-user is much more likely to have a single device. If that’s the case then it’s actually a bit of a pain to have to go through the entire device discovery phase again. Even for me with multiple devices, having to go through device discovery each time I start the app is quite painful because many times I am using the same device and it would be much smoother if it remembered the last device. In Part 4 of this series we added the ability to return to the DeviceListFragment from the DisplayFragment in order to scan and select a different device. Because we have that functionality in place, it would make sense to attempt to re-connect to the previous device when the app starts.
The code to do this is not particularly tricky, so I’m not going to attempt a full line-by-line breakdown here. To do so would result in 2 to 3 long but fairly uninteresting blog posts. The full, completed code is available, and anyone interested in seeing the exact changes can look at a delta between the code on branches Part5 and Part6.
The things that I have implemented to achieve this are as follows:
When the user connects to a device following device discovery, the MAC address of the BLE device are stored to SharedPreferences. If the user manually disconnects from the device from the “Disconnect” option in the ActionBar, the SharedPreferences entry is cleared.
When BleService receives a
MSG_REGISTER event (which occurs during app startup) it checks SharedPreferences to see if there is a stored MAC address. If not, it goes in to IDLE state (as before). If there is a MAC address stored it will automate the device discovery process, exiting discovery as soon as a device matching the MAC address is seen. It will then go through the rest of the stages of connection, service discovery, and notification registration.
There is an edge-case that needs to be handled – the device is no longer in range or otherwise available during auto-reconnection. In this case, a delayed handler has been added to DeviceFragment. If no data has been retrieved within 15 seconds of the Fragment being attached to an Activity it will assume a connection failure, the DeveiceListFragment will be shown, and the SharedPreferences entry will be cleared.
When we run this we can see the auto-reconnect behaviour if we quit the app and restart, and also the timeout if we do the same when the SensorTag is no longer available:
That concludes are look at improving the overall look and feel, and the user flow through the app. While it’s still by no means a fully polished app (we could make the DevliceListFragment a bit prettier, for example) the techniques for doing so are probably not as interesting as some of those already covered in this series, hence we’ll skip them.
The source code for this article is available here.
© 2014, Mark Allison. All rights reserved.
App UI / UX – Part 6 by Styling Android is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. Permissions beyond the scope of this license may be available at http://blog.stylingandroid.com/license-information.