Google has brought Android Nougat to its second iteration with the 7.1 version (API 25), but this one is not a minor release, as a matter of fact it bundles some interesting features under the hood. One of these extra features is App Shortcuts.

TL;DR

App Shortcuts are great for exposing actions of your app and bring back users into your flow

they can be static or dynamic

static are set in stone once you define them (you can only update them with an app redeploy)

dynamic can be changed on the fly

you can create a back stack of activities once you open one through a shortcut

shortcuts can be reordered, but only in their respective type and static shortcuts will come always at the bottom as they're added first (there's no rank property to be defined on them)

the labels of the shortcuts are CharSequence so you can manipulate them through spans

In the meta-data, tag the android:resource key corresponds to a resource defined in your res/xml/shortcuts.xml. Here you need to define all of your static shortcuts. Let's add one that will open a certain activity from your app (in my case I've created a dummy StaticShortcutActivity):

You can see that the root tag of this file is <shortcuts>, which can hold multiple <shortcut> blocks. Each of them, as you may have guessed, represents a static shortcut. Here, the following properties can be set on one shortcut:

enabled: as the name states, whether the shortcut is enabled or not. If you decide to disable your static shortcut you could either set this to false, or simply remove it from the <shortcuts> set

icon: the icon shown on the left hand side of the shortcut. In my case, I created a simple Vector Drawable from within Android Studio and assigned it as an icon

shortcutDisabledMessage: when you disable your shortcut, it will disappear from the ones that the user can reveal by long pressing your application icon, but one can pin a shortcut to the launcher (by long pressing and dragging it on the desired launcher page), so when disabled the pinned shortcut will appear greyed out and upon tapping it a Toast with this message will appear

shortcutLongLabel: longer text of the shortcut shown when the launcher has enough space

shortcutShortLabel: a concise description of the shortcut. The field is mandatory. Most probably this will be the one which will appear on your launcher

intent: here you define your intent (or more intents) that your shortcut will open upon being tapped

Let's take a look how our static shortcut looks like:

Nice and easy, but you can notice that upon pressing back, the user is taken back to the launcher. What about rather getting back into the app? To do so, we can add multiple intent tags under the previous shortcut ones:

Notice how we added an extra <intent> before the one that we had, pointing to the MainActivity. This will create a back stack of intents, the last one being the one opened by the shortcut. In our case the back stack looks like MainActivity -> Static ShortcutActivity, so when pressing back the user is taken into the MainActivity:

Dynamic shortcuts

As their name suggests, the dynamic shortcuts can be modified at runtime without the need of redeploying your app. As you may have guessed, this ones are not defined through a static resource (shortcuts.xml) as the static ones, but created in code.

Let's add our first dynamic shortcut! In order to do so, you will have to make use of the ShortcutManager and the ShortcutInfo.Builder. I'll be constructing the first dynamic shortcut in my MainActivity.#onCreate():

Here we acquire the shortcutManager and construct a ShortcutInfo. By using the ShortcutInfo.Builder we can set various properties for the shortcut we want to create. All the builder methods we use above correspond to the same properties used for a static shortcut, so I won't be explaining them again. However, one property that is a bit hidden, is the id of the shortcut which is defined in the StaticInfo.Builder constructor as second parameter - shortcut_web. I've defined the Intent being one that will open my website. Finally, I set the dynamic shortcut on the ShortcutManager. Let's see now how our shortcuts look now:

Great! Now we have 2 app shortcuts in our app - one static and one dynamic.

Let's add another one that will point to an activity inside the app and see how we can create a back stack for it:

You can see now that we now setIntents() on the builder in order to build a back stack:

the first intent corresponds to the MainActivity. We specify a FLAG_ACTIVITY_CLEAR_TASK flag, in order to clear any existing tasks related to the app and make the MainActivity the current root activity

the second one corresponds to the DynamicShortcutActivity (which is just an empty activity that I created). In order to do so, we need to provide an Intent with a specific action, which is defined as a static String in DynamicShortcutActivity and corresponds with the intent-filter action defined in AndroidManifest.xml for the same activity:

By declaring this array of intents in this order, we ensure that when the user presses back after opening DynamicShortcutActivity through the shortcut we created, the MainActivity will be opened.

Let's see how they look like:

Shortcut ordering

Now that we have 1 static shortcut and 2 dynamic ones, how can we specify a custom order for them. Taking a closer look at the ShortcutInfo.Builder methods one in particular captures our attention: setRank(int). By setting a custom rank to a dynamic shortcut we can control the order they appear when revealed: the higher the rank, the most top the shortcut goes.

Say we want shortcut number 2 (catinean.com) to sit at the top. We can dynamically change the ranks of the already added dynamic shortcuts. Let's do this when pressing a button from MainActivity:

In the click listener of the button, we create new ShortcutInfo for each shortcut we have previously added, with the same IDs, but now we set a higher rank to the shortcut_web one and a lower one for shortcut_dynamic. Finally, we use the updateShortcuts(List<ShortcutInfo>) method of the ShortcutManager in order to update the shortcuts with the newly set ranks:

You can see from the above gif that the static shortcut sits at the bottom of the list. It turns out that you cannot change the rank of a static shortcut as they will be shown in the order they're defined in the shortcuts.xml file. Since we have only one static shortcut, it has the default rank of 0 which cannot be changed.

Extra bits

If we take a closer look at the setShortLabel(CharSequence) method of ShortcutInfo.Builder, we can see that it accepts a CharSequence as a parameter. What does this mean? Well, it means that we could play with it since we can attach custom spans to it.

Let's say we want to change it's colour to red when pressing the above created button. We can create a SpannableStringBuilder and set to it a ForegroundColorSpan with the desired colour and then pass the spannableStringBuilder as a shortLabel (as the SpannableStringBuilder is a CharSequence):

The last couple of days were full of excitement in the Android world as Google I/O took place. In no surprise, some of the rumours came true and Android M was announced (with a possibility to download the preview as last year), which comes with a bunch of new APIs.

One of the new API that caught my eye is the Data Binding Library. In short, it lets you bind data directly into your layouts by having a POJO - variable declaration pair. Let's take the example from the official documentation:

So far so good, nothing really complicated or hard to comprehend. In a way, this removes a bit of boilerplate code (not having to findViewById() or setText()). My first impression was that this is the aim of this API.

Things start to take a slippery slope

Going forward with reading the documentation, you can see that you can do a lot more with Data Binding than to simply remove the need of findViewById() and attach simple data to your views.

You can actually import java classes in your layouts and use them directly in place:

And you can do a lot more with having Observable Fields, Observable Collections or custom bindings. All of these can be found in the official documentation.

This is more than binding simple data to your views and avoiding the boilerplate code. To me, this is actually mixing business logic in your UI layouts. Your views should be as dumb as possible, adhering to the Single Responsibility Principle with the only responsibility to show data. This could lead to a complicated, cluttered and unclean codebase.

We've seen some of the examples of the Data Binding API. I'm sure that this API was created in order to ease the developers' work and avoid boilerplate, but one can overuse it and accidentally create chaos in his code. Mixing Java in your view code has never been a good idea. Does JSP ring a bell?

I'm looking forward to seeing the different use cases in which developers will make use of the Data Binding API. How would you use it?

In the first part of the tutorial we've covered the basics of creating a digital Android Wear watchface. In this part we will see how one can add a settings panel for her watchface in the Android Wear mobile application. By the end of this article you will be able to control the background colour and the time and date colours of your watchface from inside the Android Wear application on your mobile device.

In order to establish a communication channel between the watch and the mobile device, you must use the Wearable Data Layer API which is part of Google Play services. As the official documentation states:

Because these APIs are designed for communication between handhelds and wearables, these are the only APIs you should use to set up communication between these devices. For instance, don't try to open low-level sockets to create a communication channel.

With the help of the Wearable Data Layer API you can send accross your devices multiple types of objects:

For our communication channel we will be using the DataApi to send DataItems from the mobile device to the data layer while the watchface will be listening for any modifications.

Creating the mobile settings activity

As we have seen above, the API we will be using is part of Google Play services, so you will have to specify a meta-data entry in your mobile/src/main/AndroidManifest.xml file under the <application> tag:

Next, create an empty activity in mobile/src/main/java/your_package that will serve as the settings activity for your watchface. Let's call it SimpleWatchFaceConfigurationActivity. In order the activity to be perceived as a settings activity for your watch face, you will have to specify an <intent-filter> in your mobileAndroidManifest.xml:

As you can see, you have to specify a custom <action> for your intent filter alongside the categories. In our case, the action name is formed out of the package name and a config string: com.catinean.simpleandroidwatchface.CONFIG_DIGITAL.

On the wear module side, you will have to add an additional <meta-data> field to your previously created <service> entry in the AndroidManifest.xml file:

See how the meta data value corresponds with the action name of our activity.

For now, our activity is empty. Let's populate it with two entries in order the user to be able to configure the watchface background colour and the date and time colours. It's layout will be simple, formed of a LinearLayout with two elements (one for the background colour and one for the date and time colours). The mobile/src/main/res/layout/activity_configuration.xml will look like this:

The toolbar element will act as an action bar for our activity (here you can find more information about toolbar). Below the toolbar we have our vertical LinearLayout that contains two RelativeLayouts as the rows (each of them containing a TextView and a preview colour represented by a simple View).

Going back to our activity, we would want to display a dialog with colour names for each of the elements. For this, we will create a simple ColourChooserDialog that will contain a simple list of colours and will be displayed whenever the user clicks on an element from the activity.

You can see that it is a simple DialogFragment that displays a list AlertDialog backed by a string arrayR.array.colors_array (for more information about dialogs in general, you can read here the official documentation).

The string array is just a resource inside mobile/src/main/res/values/arrays.xml:

The dialog provides an interface in order to notify the activity of the chosen colour. Since we will have multiple dialogs created (one for the background colour and one for the date and time colours) we will have to differentiate them by their tag.

If now you run your wear module on your wear device and then the mobile module on the mobile device, navigate to the Android Wear application, you will be able to access the settings activity.

Sending data to the Data Layer API

Now that we are able to capture the chosen colour, it is time to see how we can send it to the Data Layer API. You will have to use the GoogleApiClient class in order to connect and to send the data. In onCreate() of our activity we create the object, in onStart() we connect to the data layer and in onStop() we disconnect. Our enhanced activity will look like this:

You can see how a PutDataRequest is created on the specific path and every time we receive a colour we populate the map with it at a specific key. In the end, we send the request with the help of Wearable.DataApi.putDataItem(googleApiClient, putDataReq) method.

Now that we are able to send the colours, we have to handle them into the wear module, specifically in the previously created SimpleWatchFaceService.

Handling the received configuration in the SimpleWatchFaceService

Back in the wear module, we have to handle the configuration sent by the previously created SimpleWatchFaceConfigurationActivity in the SimpleWatchFaceService.

As we did in the configuration activity, in order to synchronize with the data layer API, we have to firstly connect to it through a GoogleApiClient object. We'll start by connecting to the API when the watchface is visible and disconnecting when not. Your SimpleWatchFaceService will look like this:

We create a GoogleApiClient object in onCreate() method of the SimpleEngine and connect when the watch face becomes visible and relase the client when the watch face is not visible anymore.

Next, we actually want to be notified when the background colour and the date and time colour values are changed in the mobile activity and every time the watch face connects to the data layer. In order to achieve this, we will have to use:

We can see that every time the watch face is visible we connect to the data layer and once connected we add the two listeners. onDataChangedListener will get notified every time there is a change in the data layer and onConnectedResultCallback is only notified when the service is firstly connected. In both cases we want to process the received DataItem - processConfigurationFor(DataItem). While processing the itmes we use the path (/simple_watch_face_config) and the keys associated with every item (we defined the keys in the SimpleWatchFaceConfigurationActivity) in order to get hold of the sent values. Once the items are identified, we pass them to the SimpleWatchFace to update the colours:

You are now set to test the whole configuration end to end. First run the wear module on your watch, then the mobile module on your phone. Jump into the Android Wear application on your phone and you can select the installed watch and access the settings screen for it. From here you can play with changing the colours for both the background and the date and time.

As usual, all the code is pushed to GitHub. I will appreciate any feedback provided.

When it was first launched, Android Wear stirred a lot of interest among the development community, especially among the developers who saw the opportunity of developing customised watchfaces for their smartwatches. Unfortunately, the first API realease didn't include official means of creating a watchface and those who wanted to achieve this had to implement various hacks and workarounds.

As of December 2014, Google has published the official Watch Face API for Android Wear so you don't have to find workarounds anymore.

This tutorial will guide you through the process of creating a digital watch face for your Android wear powered smartwatch. In this first part we will cover the basics of structuring your project and using the Wear API in order to create your first watchface.

The final watch face will look like this, providing the current time and date:

Project creation

I assume that you have already installed Android Studio. If not, you can grab it from here.

Start by creating a new project. Input your project name and package. Next, be sure to tick both Phone and tablet and Wear platforms on the Target Android devices screen as shown above.

Next, you won't need any activity created, so from the Add an activity windows (both mobile and wear), select Add no activity.

Lastly, click Finish and everything is set to proceed to the implementation. You will notice that two modules were created - mobile and wear.

The following implementation details are specific only to the wear module.

Moreover, the service has the android.permission.BIND_WALLPAPER permission and a series of meta-data that define a watch_face resource and preview images for rectangular and circular form factors (com.google.android.wearable.watchface.preview and com.google.android.wearable.watchface.preview_circular). The preview images are usually obtained as a screenshot after you fully implement the watchface and they are used as images when picking the watchface from your smartwatch.

The watch_face resource must be defined in wear/src/main/res/xml/watch_face.xml and it is a simple wallpaper resource:

<?xml version="1.0" encoding="UTF-8"?>
<wallpaper />

Implementing the SimpleEngine

As I said before, the SimpleEngine is an implementation of CanvasWatchFaceService.Engine which actually draws your watch face on the canvas and also contains a series of useful callbacks.

First things first, the engine provides an onCreate(SurfaceHolder holder) method where you can define your watch face style and other graphical elements. In defining the watch face style, you can customise how the UI elements such as the battery indicator are drawn over the watch face or how the cards are behaving in both normal and ambient mode. In order to make use of all of these you must call the setWatchFaceStyle (WatchFaceStyle watchFaceStyle) method. Our SimpleEngine class will look like this:

We are using different WatchFaceStyle constants to define various behaviour:

setCardPeekMode(WatchFaceStyle.PEEK_MODE_SHORT) - this will specify that the first card peeked and shown on the watch will have a single line tail (i.e. it will have small height)

setAmbientPeekMode(WatchFaceStyle.AMBIENT_PEEK_MODE_HIDDEN) - when the watch enters in ambient mode, no peek card will be visible

setBackgroundVisibility(WatchFaceStyle.BACKGROUND_VISIBILITY_INTERRUPTIVE) - the background of the peek card should only be shown briefly, and only if the peek card represents an interruptive notification

setShowSystemUiTime(false) - we set the UI time to false because we will already show the time on the watch by drawing it onto the canvas

With these 4 settings in place, we are done defining our custom watch face style. Next, we are going to explore the callbacks of the engine.

Engine callbacks

The CanvasWatchFaceService.Engine provides a series of callbacks that can be implemented in order to better understand the behaviour of the watch.

onDraw(Canvas canvas, Rect bounds) - probably the most important callback, this is called every time the watch face is invalidated. Here we will define the draw logic of the watch face using the provided Canvas and the Rect that defines the watch face bounds.

onTimeTick() - this callback is invoked every minute when the watch is in ambient mode. It is very important to consider that this callback is only invoked while on ambient mode, as it's name is rather confusing suggesting that this callbacks every time. This being said, usually, here we will have only to invalidate() the watch in order to trigger onDraw(). In order to keep track of time outside ambient mode, we will have to provide our own mechanism.

onVisibilityChanged(boolean visible) - this is called when the watch becomes visible or not. If we decide to override this callback, we have to call first super.onVisibilityChanged(visible).

onAmbientModeChanged(boolean inAmbientMode) - called when the device enters or exits ambient mode. While on ambient mode, one should be considerate to preserve battery consumption by providing a black and white display and not provide any animation such as displaying seconds.

void onPeekCardPositionUpdate(Rect rect) - called when the first, peeking card positions itself on the screen. The rect provides information about the position of the card when it's peeking at the bottom and allowing the watch face to be exposed. Here you can change the watch face appearance depending on where the card is on the screen.

onPropertiesChanged(Bundle properties) - called when the properties of the device are determined. For example, the bundle contains properties to indicate if burn-in protection is required (PROPERTY_BURN_IN_PROTECTION) or whether the device has a low-bit ambient mode (PROPERTY_LOW_BIT_AMBIENT).

Managing time

One of the most important part of building a watch face is to properly manage time, of course. As we've seen before in the engine callbacks, onTimeTick() is only called in ambient mode, every minute. What can we do in order to get notified every minute when the device is not in ambient mode? The official documentation mentions that you have to provide your custom time management system. The example presents the use of a Handler in order to schedule periodic ticks. We are using a Handler as opposed to a Timer with a TimerTask because the later will execute the job on a separate thread, but we want it to be executed on the main thread as we are going go call invalidate() as seen above. Our SimpleEngine will look like this:

In order to manage time, in our case we want to tick each second, two actors are involved:

timeTick - a Handler that will post a runnable only if the watch is visible and not in ambient mode (see startTimerIfNecessary()) in order to start ticking.

timeRunnable - the actual runnable posted by timeTick handler. It invalidates the watch and schedules another run of itself on the handler with a delay of one second (since we want to tick every second) if necessary.

As you can see, we want to invalidate the watch (i.e. schedule a draw) only when it is visible and not in ambient mode (our custom timer should tick only in this case). There is no reason to draw while the watch is not visible and, as we've seen above, the ambient mode tick has its own callback - onTimeTick() which is called every minute and where we just invoke invalidate() in order to schedule a draw.

In onDestroy() we want to remove all the callbacks to the handler in order stop it ticking.

Drawing the time and date

In order to actually draw the watch face, you must override the onDraw(Canvas canvas, Rect bounds) method of the SimpleEngine. Here we will perform all the drawing operations on the canvas. However, we will create another class - SimpleWatchFace that will be responsible with drawing the watch face in order not to clutter the engine.

For drawing on the canvas we will need:

a Paint that will hold all the information needed in order to draw (such as size, colour, antialising, etc)

a Time object for simplicity (as an alternative you could use Date or Calendar) in order to get hold of the current hour, minute, second and date

We first create the Paint objects for both the time and date and the Time object. Afterwards, we create a draw(Canvas canvas, Rect bounds) method that will actually draw the time on the canvas. In this method, we start by placing the time to the current time (time.setToNow()), drawing the black background and then drawing the time and date. We make use of the canvas.drawText(String text, float x, float y, Paint paint) method in order to paint the time and date strings. Moreover, we create some helper methods in order to compute the x and y offset of both time and date drawings.

The setAntiAlias(boolean antiAlias), setColor(int color) and setShowSeconds(boolean showSeconds) methods will be used in order to differentiate the drawing between interactive mode and ambient mode.

In onDraw() we simply invoke the draw() method on the watchFace object. Moreover, when the watch is in ambient mode we do not anti alias the text and we do not show the seconds in order to minimize the amount of animations (draws) for battery performance and we set the color to gray.

Now you can run your watch face on an emulator (or device - here you can find how to debug your device over Bluetooth) . Don't forget to select it after it has been installed.

The next part will focus on further customisations by providing a Settings activity and optimisations of the watch face.

The new release of Android 5.0 provides developers over 5000 new APIs to play with.

One of my favourite component that was relseased with the new SDK is JobScheduler. Briefly:

JobScheduler API that lets you optimize battery life by defining jobs for the system to run asynchronously at a later time or under specified conditions.

Unfortunately, the JobScheduler API is only available for minSdkVersion 21 as it uses system components only available in Android 5.0.

Scheduling a job

In order to schedule a job you must define 2 components:

JobInfo that holds the constraints of when the job should run (e.g. only on WiFi, only when plugged in, periodically, etc.)

JobService that is a service that handles the scheduled requests.

Lets start by defining our job constraints. Suppose we want to run a background task when the device is connected to WiFi and plugged in. In order to create our JobInfo object we use the JobInfo.Builder :

The JobInfo needs an integer id and a service component that will be our implementation of JobService. In order to define our constraints we setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED) in order the job to run only on WiFi connection and setRequiresCharging(true) for the device to be plugged in. The only remaining part is to actually schedule the job:

Upon calling jobScheduler.schedule(job) the job will be executed if the criteria are met. If you want to make sure that your job will be executed after a period of time regardless of the state of the criteria specified when creating the job, you can use the setOverrideDeadline(long) when building your JobInfo object:

There are a bunch of other parameters to play with when building your job, see them all here.

Creating the JobService

The JobService is the entry point of executing your scheduled job. You create your service by extending JobService and overriding the onStartJob(JobParameters jobParameters) and onStopJob(JobParameters params) callbacks. As their name suggest, the first callback is fired when the job starts - this is the place where the job logic should be implemented - and the second one when the job is stopped by the system because the criteria are not met anymore. You must take your job implementation from the onStartJob callback on another thread as this method is called on the application's main thread.

Lets start by defining our JobService in the AndroidManifest.xml file:

As it can be seen in the above code snippet, when a job is scheduled to start, we execute an AsyncTask that will sleep 5 seconds and then report that the job has finished.

Conclusion

The JobScheduler API is perfect when you want to run background non user-facing tasks when certain criteria are met. The only downside that I see for the moment is that JobScheduler is only available for api level 21 (Android 5.0).

Any modification (add, remove, change password) to any Account from the AccountManager will trigger a sync for all of the system's SyncAdapters, including the one you've just created in your app!

Context

In my attempt to better understand how a SyncAdapter works, I've followed the official documentation and created a sample application. However, I've stumbled upon a curious case when my simple SyncAdapter performs a sync even if it wasn't configured to: every time an application added an Account using the AccountManager I could see that onPerformSync() method was called. This caught my eye and I wanted to find out more, so I dived into the AOSP source code.

The problem

Taking a look at SyncManager - the class responsible with scheduling syncs - I could see that a BroadcastReceiver with a descriptive name is registered:

It turns out that when the broadcast is received, the SyncManager schedules a sync for every SyncAdapter. But who triggers the broadcast? Taking a step further and assuming, from the receiver's name, that it's something related with AccountManager, I started to take a look at AccountManagerService. Here I could see that there's one descriptive method that does exactly what I was looking for - triggering a broadcast for account change events:

Brieftly, whenever an application adds, removes or changes the password of an account, a broadcast is sent that triggers all the SyncAdapters to perform a sync. This is rather curious, especially because there's no documentation around it.

Moreover, if you're not aware of this behaviour your application can be trapped into some subtle bugs (e.g. your sync triggers a modification of an account and from here this triggers another sync and you're stuck into an infinite loop!).

Solution

If you don't want your SyncAdapter to perform a sync when an account is changed, you can easily make use of the Bundle that you can pass in the ContentResolver'srequestSync(Account, String, Bundle) or addPeriodicSync(Account, String, Bundle, long) methods:

This bundle will be received in the onPerformSync(Account, Bundle, String, ContentProviderClient, SyncResult) method of your SyncAdapter. Here you can check if the bundle contains your custom extra or not, and perform the sync operation only if it does (the sync triggered by the system when an account has changed will not contain your custom bundle):

NOTE: This is not a tutorial of what is or how to create your own SyncAdapter. If you're looking for this, the Android developer doc is your friend!

I've been recently playing with SyncAdapter and I found myself in the situation where I have to trigger a sync on user demand. This seems to be pretty straight forward, ContentResolver has an explicit method that does exactly what I want: ContentResolver.requestSync(Account, String, Bundle), here you can find the full Javadoc of the method.

This worked well until I randomly disabled synchronization for the entire system. Of course, with sync disabled, my SyncAdapter wouldn't refresh.

The solution is to pass the right extras to the bundle in the requestSync method. In order to force a sync and bypass user preferences (like disabling sync) you shuold use the following bundle and pass it to the requestSync method:

However, keep in mind that syncing on demand and requesting an immediate sync is a rather inefficient use of SyncAdapter because it bypasses all the network and power use optimisations. This solution should be used with extra care and only in situations when you are sure you want to perform an immediate on demand sync.

]]>Hi there!

I'm Andrei Catinean, a passionate Android Software Craftsman. I've finally decided to set up a blog in order to share my personal experiences on Android development and software in general.