Widgets In Complications

I’ve recently released version 7 of Wearable Widgets, which includes a feature I’ve been working on (and testing) for some time: the capability to display phone widgets as complications on Wear OS watch faces.

This was an idea that occurred to me at I/O 2016, when Google first announced watch face complications. Complications are really just widgets by another name, and since I’d already been in the business of bringing widgets to watches for a couple of years, it seemed a natural next step. And now, it’s finally ready.

What’s all this then?

If this all makes sense to you, go ahead and skip on to the next section. But if you’re sitting there, scratching your head and thinking what the $#!+ is all this, let me try to explain:

  • Start with widgets: a feature of Android phones that lets you add information and controls from various apps directly onto your home screen.
  • My flagship app, Wearable Widgets, brings those widgets from your phone to any supported smartwatch.
  • Separately, Google’s Wear smartwatch platform includes support for watch face complications: a way to customize a watch face with information and controls from other apps on your watch. Kind of like widgets, see?
  • And now, I’ve brought the ability to place phone widgets directly onto any watch face that supports the small-image complication type.

Does that help?

Some examples

On most watch faces, complications are tiny, so many phone widgets don’t work overly well. But some really do… Here are a double-handful of widgets that I’ve found to be especially useful as I’ve been dogfooding this feature for the last couple of months.

Disclaimer: I have no connection with any of the below apps, and am not responsible for them in any way. If you’re the developer of one of these and would like it removed from this list, drop me a line and let me know.

Cover artWifi OnOff


I’ll start things off with a basic one: turning your phone’s wifi on and off from your watch. I use this one frequently, saving my phone battery when I’m out and about, then reconnecting when I get home. As a bonus, this widget has multiple colors to show your phone’s wifi state on your watch face.

Cover artSignal Strength


While we’re on the subject of network connectivity, here’s a little widget to let you know how strong the signal getting to your phone is. It has options to show either wifi or cellular signal, and I’ve found the latter useful in areas of marginal coverage.

Cover artToggle B/T


Another network-related widget – we’ll move on in a moment, I promise – this one simply turns your phone’s bluetooth radio on and off. I use it to turn off BT before going out on my bike, so that Google Fit will use my watch’s GPS, then turn it back on after I return.

Cover artSilent Mode Toggle


Another remote-control for your phone: cycle it through silent, vibrate, and normal ringer modes with a tap on your watch face. Not one I use every day, personally, but I could certainly see situations when I would.

Cover artSharpTools


So, it also turns out that with a widget in a complication, you can control more than just your phone from your watch face. This widget enables you to set up actions to control linked smart home devices. I haven’t tried it myself (my home doesn’t lend itself to that sort of automation), but I know of WW users who rely on it.

Cover artTasker


And for the ultimate in flexibility, add a Tasker widget to your watch face. If you’ve ever used Tasker, you know that just about anything goes – and now it can go straight from your watch face.

Cover artBattery Widget


Moving on from actions for a bit, how’d you like to see your phone battery charge level on your watch face? This is another one that’s found a permanent home on my own wrist; as my Pixel XL battery is aging, its battery needs closer monitoring, and this is just the ticket.

Cover artBarometer Reborn


If your phone has a pressure sensor (and many flagships do, these days) you can add a barometer to your watch face. Great for an old-school weather geek like myself! Also, as an alternative to the previous item, note that the same dev has a battery widget.

Cover artSad Trombone


Finally, a bit of fun, and one of my all-time favorite widgets in any context: tap a complication on your watch and get the classic, corny, wah-wah-wah-waaaah trombone sound effect. Indispensable if you (or someone you know) thrive on bad jokes. The same dev, Colin O’Dell has other sound effect widgets too, including the good ol’ ba-DUM-tsshhh rimshot – a close runner-up in my book.

Of course, you’re not limited to the above list; you can use any widget that’s 2×2 cells or smaller. Got a widget you’d like to put on your own watch face? Install Wearable Widgets, give it a try, then tell us all about it in the comments below!


I/O 2017 Experiments Challenge Winner


My entry into the 2017 Android Experiments Challenge, Home Screen Arcade, has come up a winner! This means a free ticket to Google I/O, where HSA will be on display with the other winners in the Experiments Dome. If you’re coming to I/O, stop by and see us!

I’m quite honored to get this validation of my concept from the Google team, who called it “A great example of customization possible only on Android. Amazing creativity, well executed & super fun.”

You can see more of Home Screen Arcade at its mini-site, including APK download and a link to the source code. And, please also check out the rest of my Android app portfolio.

Sweet! 😎


It’s a question I’ve seen a few times now on the Google+ Wear developer community and StackOverflow: How do developers acquire the SYSTEM_ALERT_WINDOW permission on Android Wear devices running Marshmallow?

tl;dr: You don’t, at least not for now. Keep your apps on targetSdkVersion 22.

But for those of you interested in the longer answer… This question affects my leading Wear app, so after seeing it come up a couple of times – and wanting to know the answer myself – I did some research. I posted my findings on StackOverflow, but decided that the topic could use a bit more explication, so I wrote this post.

First, a bit of background. Why should anyone, developer or otherwise, care?

Well, SYSTEM_ALERT_WINDOW is the internal name for an Android permission that lets one app draw to the screen superimposed over other apps. Android Police has a good explainer on the subject in the context of Android phones – but here, we’re concerned about smartwatches. And it turns out that this is really quite a handy thing to do on a watch, mostly because it allows apps to add functionality to the Android Wear homescreen, aka its watch face:

  • Wear Mini Launcher (and other third-party app launchers) let you swipe in from an edge of the screen to open their app list, or a quick-settings panel.
  • Similarly, Tappur uses a swipe-from-edge gesture to access actions, like turning smart light bulbs on and off.
  • My own Wearable Widgets uses a swipe in the middle of the watch face to move between widgets.

You may notice that all of these examples are about swipe gestures, and therein lies SYSTEM_ALERT_WINDOW’s power on the watch. By drawing an invisible window over the watch screen, we can detect touch gestures (like swipes), and initiate actions in response. It’s not an overstatement to say that this capability is central to the usefulness of many of these apps.

So, it’s useful. What’s the problem?device-2016-01-28-161527

Well, as mentioned earlier, SYSTEM_ALERT_WINDOW is what’s known as a permission, meaning that users have to specifically allow an app to do it. This is because it can be dangerous to let one app draw over others on your screen: the same capability that lets Wear Mini Launcher detect a swipe on your watch face can be turned to evil, letting a malware app detect the touch inputs you think you’re making on some other app: say, the password you’re entering in your banking app. Such an attack is known as tapjacking, and it’s led one Googler to describe SYSTEM_ALERT_WINDOW as “raised to be above DANGEROUS“.

In Android 6 (Marshmallow), Google overhauled the permission model so that users need to explicitly allow apps access to dangerous permissions – generally hailed as a long-overdue improvement. But what about permissions that are “above DANGEROUS”? Well, granting access to those takes an additional step; you need to go to a particular screen in the system Settings and flip a switch for each app that you want to allow.

Well, OK, that seems fair. Again, what’s the problem?

In a nutshell: Android Wear doesn’t have that system Settings screen.

device-2016-01-28-162633_framedWell, perhaps it has it; API level 22 on Wear did. But as of API 23, you can no longer get to it. The system doesn’t link to it (as it did on 22), and if you try to invoke it from a Wear app, you’ll get a crash. The Intent doesn’t resolve.

So what does that mean for those of us whose Wear apps rely on SYSTEM_ALERT_WINDOW? For the time being, I can only see one course of action: keep your apps on targetSdkVersion 22.

This works, because the new permission model is only enforced on apps that target Marshmallow, which is SDK level 23. This “solution” comes with a serious downside, however: your apps will be unable to use any of the cool new features that come with Marshmallow (or later versions). And some of these are seriously handy on Wear (like the ability to use -round resource qualifiers). But at this moment, I don’t see another way forward – though I’ll discuss longer-term options in a moment.

Before I do, however, I just want to note something for the developers reading this: keeping your Wear app on targetSdkVersion 22 means that the enclosing handheld app also needs to be on 22.

I haven’t noticed this restriction before, but I’ve tested it in this case, and it’s true. If your Wear app uses SYSTEM_ALERT_WINDOW and targets API level 22, but it’s packaged in a handheld app that targets 23, installation to the watch will fail. If you’re interested, the error message in logcat is:

W/WearablePkgInstaller: Wearable com.myapp has a permission “android.permission.SYSTEM_ALERT_WINDOW” that is not granted in the host application.

Which isn’t entirely truthful (this happens even if the permission is granted to your host app), but the result is the same: it doesn’t work. Don’t do it, kids.

So, moving on, what are our options for the future?

If we’re lucky, Google will add the Settings screen for users to enable SYSTEM_ALERT_WINDOW on the watch at some point, maybe when Marshmallow is released to the wider Wear ecosystem. You can (possibly) encourage them to do so by starring this issue in the external Android bug tracker. I have my doubts, though, as I get the feeling they are trying hard to discourage use of this permission, and may just cut it off completely on Wear. What if they do – what then?

The obvious (but wrong) answer is to keep our apps on API 22 indefinitely. At some point, however, this will become untenable. There will eventually be some new feature that your app can’t live without, or at the very least, someday you’ll want to move your minSdkVersion beyond 22.

The only other solution that occurs to me is to abandon swipe gestures for some other interaction.

One that I’ve experimented with in Wearable Widgets is tapping on the side of the watch (rather than its screen): by monitoring the device’s accelerometer, such a tap can usually be detected. My current code for doing so is somewhat primitive, and doesn’t work on some older, low-spec watches (with slow accelerometers), but it’s a start – and by the time it becomes necessary, hopefully there’ll be very few of these low-spec watches left in the wild. I intend to open-source my code for doing this soon.

If you have any other ideas, I’d be happy to hear them! Drop a comment below, or join the discussion on the Android Wear dev community.

UPDATE: (2 May 2016) My original testing of SYSTEM_ALERT_WINDOW on Android Wear was done using an API level 23 emulator, and the (recalled) second-edition LG Urbane LTE – the only publicly-released Android Wear hardware running Marshmallow at the time. Since then, the official Android 6.0.1 update has rolled out to all Wear devices, and I’ve confirmed that this issue still exists.

The larger issue also affects the other “super-permission”, WRITE_SETTINGS. It appears to be the same situation: the intent for the user to grant or deny the permission doesn’t resolve on Android Wear.

In addition, I’ve followed up a couple of related leads, which interested developers might find good to know about:

  • It’s emerged that apps installed to Android 6+ from Google Play are being granted SYSTEM_ALERT_WINDOW by default, simply by requesting the permission in their manifests. When I first read about this, I thought it might be a usable workaround for the problem that this post is all about… but no. I’ve tested it, and this grant does not extend to Wear. Apparently, even if the “host” handheld app is installed form Play, the Wear app isn’t considered to be – it still doesn’t get the permission
  • It is possible to grant SYSTEM_ALERT_WINDOW (and, I would expect, WRITE_SETTINGS) to a Wear app by installing with adb -g. I can’t see how this would be useful to end-user deployment, but might be handy for testing.

Bottom line is that we’re no further along in finding a resolution to this issue, so as far as I know, my workaround recommendations above still stand.

UPDATE: (19 July 2016) With the release of the second dev preview for Android Wear 2.0, this issue is now fixed. Firing a Settings.ACTION_MANAGE_OVERLAY_PERMISSION intent device-2016-07-17-213626 now opens a system window where the user can enable this permission. And as you can see, it applies to WRITE_SETTINGS too. Perfect!

Many thanks to the folks at Google who have shepherded the fix through.

Layout-based Watch Faces for Android Wear

Watch faces are basically live wallpapers for your smartwatch – this makes a certain sort of sense, and it is indeed how Google has implemented them on Android Wear. And like live wallpapers, they can be either Canvas or OpenGL-based. But while that works okay for most traditional live wallpapers, there are a lot of watch face designs for which neither of those models works overly well. Examples might include predominantly-digital faces, legacy faces (which were developed as Activities), faces that pack in a lot of data, and anything else with a fairly sophisticated layout.

What you’d like, in fact, is exactly that – to use a standard Android layout for your watch face. It turns out that you can, and in this post, I’m going to show you how. Which of course means that it’s long post, heavy with code. You have been warned.

We’re going to build our layout-based watch face on top of a CanvasWatchFaceService, and the key to it is that you can inflate an arbitrary layout into a View, and then call View.draw(canvas) to render a Canvas from it. The rest of the code is just window dressing, really, but some if it isn’t entirely obvious.

Before we get started, I just want to say that this guide is meant for programmers with some Android experience, and ideally a bit of experience on Android Wear. I’m not going to walk you through every last step of creating a project in the IDE, setting up and running an emulator, what ambient mode means, and so forth. There are lots of great tutorials online for those sorts of things, so I’m going to assume that you have those skills comfortably in hand.

With that said, it’s high time that we…

Get Started

Begin by creating a new Wear watch face project in Android Studio. The current version (1.2 as of this writing) includes watch face templates; we’ll use the Digital template for the example I’ll be explaining here.

[If you’re not using Android Studio yet, now’s a great time to start – and one of these days I’ll write up my hard-won guidelines for converting a mature Eclipse project over to AS. But today, we’ll be starting with a new project, so that’s not an issue.]

Here’s a walk-through of the project creation wizard. The details of these things tend to change from version to version of the IDE, so your screens may not look exactly like this, but hopefully they’ll be close enough.image10

Obviously, the app and package names are up to you.image06

Android Wear isn’t supported below API level 18, so it makes sense to choose that as the minSdkVersion on the phone/tablet side.

For this example, you don’t need an activity on the handheld (mobile) app, because it only serves as a container for installing the watch face. If the previous sentence doesn’t make sense to you, I suggest you go look at Packaging Wearable Apps for clarification.

On the Wear side, however, we do want an activity – or more precisely, a watch face:image04

And on the next screen, choose the Digital watch face template, and give it a name of LayoutFaceService:image00

When Android Studio has created the new project, go ahead and run it, just to make sure that you have a working starting point. It’s probably easiest to do so in an emulator, and when you do, it should look something like this..image03

Now that we have it working, let’s break it! This is an ordinary canvas-based watchface; it’s a reasonable foundation for what we’re going to build, but has some unnecessary bits. So, the next step is to clear those out. Delete the following from your LayoutFaceService source file:

  • The entire createTextPaint method
  • The contents of the onDraw method
  • The two Paint fields (mBackgroundPaint and mTextPaint) and all references to them in the code

And in the interest of brevity, I’m not going to walk you through cleaning up various other loose ends in the template (such as its use of the deprecated Time class). If it works at the end, we’ll call that good. Turning it into production-ready code is left as an exercise for the reader.

But before we move on, let’s create a few new fields that we’ll be needing soon. In the Engine class, insert the following:

private int specW, specH;
private View myLayout;
private TextView day, date, month, hour, minute, second;
private final Point displaySize = new Point(); 

Creating the layout

If all we wanted to render was a simple digital face (like the template), we wouldn’t need a layout – it’s easy enough to render directly. But the whole idea here is to render something more complicated, something that would be a pain to draw out directly onto the canvas.

On the other hand, I still want to keep it simple-ish for this example. image05Here’s a mockup of the watch face I had in mind when I started this post:

It’s just about complicated enough to make this technique worthwhile.

If you have any Android dev experience, you can probably create a layout like this in your sleep. I’m using a simple RelativeLayout, and you can find it in the source code for this example on GitHub. But really, the important thing to take away is that it’s in res/layout/watchface.xml, in my project’s wear module.image01


Now we need to load that layout into our watch face service. The place to do so is in the Engine.onCreate method, and the code is as follows:

LayoutInflater inflater = 
    (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
myLayout = inflater.inflate(R.layout.watchface, null);

If you’ve ever worked with layouts in Android Java code, this will look familiar. It’s pretty standard stuff.

In order to use this layout, we’ll also need some data about the display, so put the following code in onCreate also:

Display display = ((WindowManager) getSystemService(Context.WINDOW_SERVICE))

specW = View.MeasureSpec.makeMeasureSpec(displaySize.x, 
specH = View.MeasureSpec.makeMeasureSpec(displaySize.y,

It looks complicated, but this is just boilerplate; you can copy this stuff verbatim into any layout-based watch face you build.

Finally, we’ll initialize the TextView fields to avoid having to find them every time we need to update the date and time. Again, this is quite basic stuff.

day = (TextView) myLayout.findViewById(R.id.day);
date = (TextView) myLayout.findViewById(R.id.date);
month = (TextView) myLayout.findViewById(R.id.month);
hour = (TextView) myLayout.findViewById(R.id.hour);
minute = (TextView) myLayout.findViewById(R.id.minute);
second = (TextView) myLayout.findViewById(R.id.second);

Making it work

In all Canvas-based watch faces, the onDraw method is where the pixels meet the code. Ours is no different, but one of the advantages to a layout-based face is that onDraw tends to be simpler than if we were drawing everything manually. In essence, we’ve front-loaded the drawing when we set up the layout, so we can offload the actual drawing code to the layout itself.

All of the following code goes in the onDraw handler. The first line is unchanged from the template that Android Studio generated for us:


That sets up the Time variable to the current instant. Next we apply it to all the on-screen date and time TextViews:

day.setText(String.format("%ta", mTime.toMillis(false)));
date.setText(String.format("%02d", mTime.monthDay));
month.setText(String.format("%ta", mTime.toMillis(false)));

hour.setText(String.format("%02d", mTime.hour));
minute.setText(String.format("%02d", mTime.minute));
if (!mAmbient) {
    second.setText(String.format("%02d", mTime.second));

These all follow a similar pattern, extracting a field from mTime and formatting it for display. It’s fiddly, but not actually hard.

So now, all our text fields have been updated, and we need to output it to the screen. But we’re not quite ready to draw it to the Canvas yet; first, we need to finalize the layout.

myLayout.measure(specW, specH);
myLayout.layout(0, 0, myLayout.getMeasuredWidth(), 

This is the crucial step to making a layout-based watch face work. If you’ve been doing ordinary Android development, it’s likely you haven’t seen code like this before; it usually happens behind the scenes in the View classes, and you don’t need to worry about it. But in our case, we’re using a “naked” layout – one not attached to a view hierarchy – so we need to do this ourselves. If we didn’t the layout simply wouldn’t render, and this technique wouldn’t work.

Whatever you do, don’t skip this step.

Now, we’re ready to output it to the Canvas:


The first line clears the Canvas to black, and the second one draws the current contents of our layout.

And that’s it for interactions with the Canvas: usually the biggest part of onDraw, but reduced by the layout approach to a trivial line of code.

Making it work in the real world

At this point, we have a working watch face. It updates the display fields to the current time, and draws them to the screen.

Before moving on, I’d just like to note that much of the job has been done for us by the template itself. It contains quite a few pre-written methods for triggering updates every minute (when in ambient mode) or every second (when not), as well as more esoteric details like tracking time zone changes. Google has put all of this code into the template, and we don’t need to touch any of it.image02

Our watch face works! But, it’s not quite ready for release.

Ambient Mode

One key behavior of Android Wear watches is the two modes they operate in, ambient and normal. The latter is when the user’s actively engaging with their watch, and we’ve got that covered.

But a watch spends most of its time in ambient mode, and a watch face needs to behave differently when it does. The Engine class we’re working from includes a method, onAmbientModeChanged, which is where we’ll put the code to handle the changes.

First, the time-keeping infrastructure built into the template drops its refresh rate from once-per-second to once-per-minute, and as a result, we don’t want to be showing the “seconds” fields when in ambient mode. Because we’re using a standard Android layout, we hide and show the seconds the same way you would in any Activity:

if (inAmbientMode) {
} else {

The second change is a bit less obvious. The visual design I’m working from is based around chunky fonts, and I’ve used boldface type to achieve that effect. But that’s not a good idea when a watch is in ambient mode, for a couple of reasons.

  • AMOLED screens use less power when fewer pixels are lit, so boldface text probably uses twice as much power as normal text.
  • Some screen technologies have an issue with burn-in, and Android Wear addresses this by shifting pixels slightly on-screen. This works much better with thin lines, however, so watch face developers are encouraged to avoid thick strokes in ambient mode.

The upshot is, I only want to use boldface for my text fields when the watch is not in ambient mode. Here’s the code I use to do it:

Typeface font = Typeface.create("sans-serif-condensed",
        inAmbientMode ? Typeface.NORMAL : Typeface.BOLD);
ViewGroup group = (ViewGroup) myLayout;
for (int i = group.getChildCount() - 1; i >= 0; i--) {
    ((TextView) group.getChildAt(i)).setTypeface(font);

You’ll notice that this is kind of a cheat, and only works because every view in my layout is a TextView. image07But it does work – here’s my watch face in ambient mode:

In most cases, more complicated layouts will require more complicated transitions between ambient and normal modes, but the details will need to be determined case-by-case.

Screen shape

In this example, I’m primarily designing for a square watch face. But in the real world, you’ll want to support round watches too – they make up the majority of Android Wear devices in the wild..

To avoid making this long post even longer, all I’m going to do to adjust this watchface for round screens is to shrink it a bit, so that the square text fits in the round hole. I’ll do that in two places; the first is the template’s existing onApplyWindowInsets method. Replace the code in that method (after the call to super.onApplyWindowInsets with the following:

if (insets.isRound()) {
    mXOffset = mYOffset = displaySize.x * 0.1f;
    displaySize.x -= 2 * mXOffset;
    displaySize.y -= 2 * mYOffset;

    specW = View.MeasureSpec.makeMeasureSpec(displaySize.x, 
    specH = View.MeasureSpec.makeMeasureSpec(displaySize.y,
} else {
    mXOffset = mYOffset = 0;

For round screens, we basically compute a margin – 10% of the square layout width – and apply it to the displaySize we got in onCreate. From there, we just recompute the MeasureSpec fields accordingly – this is determines the actual size of the layout.

We also need to use this margin when drawing, and that happens in onDraw, not surprisingly. All that’s needed is one new line of code, highlighted below, in the canvas-drawing section:

canvas.translate(mXOffset, mYOffset);

As its name implies, translate just moves the Canvas before drawing to it, applying the offsets that we calculated above.image09

Here’s what it looks like on a round screen:

Nothing fancy, but it works. However, this is another case where the exact implementation details will depend upon your design. Besides just shrinking the design like this, other solutions might include moving elements of the layout around to fit, or using a different layout completely.

Our layout-based watch face is now complete, and just about ready to deploy. All that’s left are metadata elements like previews and icons, but these are no different than any other watch face, and don’t really merit coverage here.


So far, I’ve mostly talked about the advantages of layout-based watch faces: primarily that you can use all of Android’s UI tools to build your watch face, rather than laboriously drawing it by hand (as it were).

But there are a few downsides as well.

Layout isn’t automatic

This is the biggest pitfall of this approach, for Android devs of all experience levels. Ordinarily, you create your layout, stick it in an activity, and it displays on screen. With a watch face, it’s not quite that simple.

I touched on this back in the onDraw method, but it’s important enough that it bears repeating. Remember these two lines of code?

myLayout.measure(specW, specH);
myLayout.layout(0, 0, myLayout.getMeasuredWidth(), 

These two methods, measure and layout, need to be called after any change to your content that affects the size of any layout element. In my example, I ensure that it will happen by putting them in onDraw, right before drawing to the Canvas. But if you have more complicated logic – perhaps with different parts of your layout being updated in different places – you’ll need to take some care to ensure that measure and layout are always called when they need to be.

If you ever find that your layout is not rendering correctly, this is the first thing to look for.

Battery impact is not out of the question

I’ve developed (and deployed) several watch faces using layouts, and none of them seem to use an excessive amount of battery. However, battery life is always a concern on Android Wear, and it at least seems plausible that using a layout for your watch face will incur some extra overhead – and thus use more power.

As I said, I haven’t seen an issue with it yet, but given this is a new technique, I feel I should mention it.

And while we’re on the subject, you should take care to optimize your code for battery life generally. In the interests of brevity and clarity, I’ve taken a few shortcuts with this example (like updating the date fields every second) that you probably shouldn’t do in the real world. Google has some specific guidelines in this area; read them, follow them, and use your own good sense.

WatchViewStub doesn’t seem to work

A few paragraphs ago, I mentioned the possibility of using different layouts for round versus square screens. If you’ve done much Android Wear development, you’re probably familiar with a standard pattern for addressing this: WatchViewStub, which automagically selects the correct layout based on screen shape.

Unfortunately, WatchViewStub doesn’t work with the technique I’ve outlined here. It’s not open-source, so I can’t delve into the details of why not, but in my testing, inflating a WatchViewStub-based layout just doesn’t work. The magic smoke escapes somewhere, and you always end up with the same layout, regardless of screen shape.

Of course, you can still use different layouts for different shapes; this simply means that you need to select the proper one manually. And the good news is that onApplyWindowInsets does work, so you can easily get the screen shape there – and inflate the proper layout accordingly. Take a look at the Android docs (or the onApplyWindowInsets method in the template) for guidance on how to use this handy method.

Are layout-based watch faces for you?

It’s a fair question – they’re not right for every case.

If you’re creating a face that’s mostly built from graphical assets, it’s probably easier to render them directly to the screen, rather than shunting them through a layout first. Likewise, if your design involves moving many elements around the screen (such as analog clock hands, for example), using a layout may actually be more work.image08

On the other hand, if your watch face design is text-heavy, or has complicated interrelationships between the elements, or perhaps is based off an existing Android app – then using a layout probably is a good choice. And some operations that are a real PITA with direct rendering – like wrapping text – are just effortless with a layout.

It’s also worth noting that layouts aren’t an all-or-nothing proposition. It’s perfectly reasonable to draw some graphical elements directly to the Canvas, then draw your layout. I’ve used this hybrid technique in production watchfaces too.

In any case, I hope you’ve found this guide useful, and it helps you build better watch faces. The sample watch face I’ve built here can be found on both GitHub and Google Play.

Update 11 May 2015:

Fixed a bug with the onApplyWindowOffsets code for round watch face support.

What were they thinking?

urbane_lteWith its new Watch Urbane LTE, LG has gone with a WebOS derivative rather than use Android Wear, as all their other smartwatches do. What’s that about?

It seems clear that LG wanted a watch to compete with its arch-rival Samsung’s Gear S, which packs an LTE radio for voice and data access directly from your wrist. This is the headline feature of the Urbane LTE – it’s right there in the name. And since Android Wear doesn’t support cellular connectivity, LG needed an alternative. [The Gear S gets around this limitation by running Tizen, Samsung’s own mobile OS, on which it’s based most of its smartwatches to date.]

But even given that requirement, WebOS seems an odd choice. It’s hard to imagine that many developers will create new apps – or port existing ones – for an ecosystem that contains exactly one device. And without apps, any smart device faces an uphill battle for consumer acceptance.

Why didn’t LG just use Android? Not Android Wear, but a parallel fork of the AOSP. I can’t imagine that it would have been significantly harder than adapting WebOS, and it would have gone a long way toward addressing the app problem. There are currently thousands of developers building for Android Wear, which is 95% pure Android. We’ve already made our apps work on the smartwatch form factor; it would be a much shorter path for us to rewrite the Wear-dependent bits than to start over from scratch.

As an aside, though, there is one interesting aspect to the WebOS choice. As its name implies, WebOS is based on web technologies: “native” WebOS apps are actually little web pages, with functionality written in JavaScript. You know what other smartwatch OS uses the same architecture? Tizen. That’s right, the easiest watch apps to port to LG’s new shiny will be those written for its mortal enemy, Samsung’s Gear line.

All this is an issue because Google is maintaining much tighter control over Wear than it historically has over Android generally. This means that all platform-level innovation needs to come from Mountain View, rather than being driven by partners – and clearly, this is holding the ecosystem back. Major OEMS, like Samsung and LG, have already chosen to use other platforms rather than live within Android Wear’s limitations. There are two likely results of this situation.

First, Wear is unlikely to achieve the same kind of market-share dominance in wearables  that Android enjoys in mobile. Whenever a vendor does want to push the envelope, it’ll need to do as Samsung and LG have: use another OS. That fragments the wearable space.

And second, Wear is likely to be far less rich and diverse than Android has been on phones and tablets. We won’t get the experimentation, we won’t find any interesting new use cases that Google doesn’t see coming.

But in the wider world of wearables, innovation will happen. And when a bold new idea does resonate with consumers and take off – there’s a good chance it won’t be Android Wear doing it.

A solution to app store sustainability?

The rise of the app store model for software distribution has been an incredible boon for many independent developers, including the author of this post. It’s provided the exposure that solo devs were unable to get previously, and that – combined with easy payments – has enabled us to sell software in a way that just wasn’t practical before. It’s not only been a game-changer, it’s been a life-changer for many of us.

And yet, there are serious downsides. One that I’ve seen discussed a lot is the “race to the bottom” in pricing: that the default price for most paid apps is $0.99, the minimum that most app stores allow. This is a real issue, in that it devalues the software in the mind of the customer. But on a practical level, the size of the userbases involved has meant that it’s possible to make that up with volume, at least in theory. And the laws of supply and demand teach us that it may well be more profitable to price your product low – and sell a lot of them – than to price it high and only sell a few. So this isn’t a clear loss for devs.

A deeper issue, but one that I’ve seen less discussion of outside the developer community, is that of sustainability. As one well-respected dev said in a recent Google+ post, “Users expect the app they paid $2 for to be updated forever with every new OS release and with additional features, without any additional cost, forever.”

I hope I don’t need to explain the problem with this.

It can be OK as long as the market is expanding: a constant stream of new customers buying the app translates to an income stream for the dev. But the incremental cost of each new user is not zero: it costs the dev more time and effort to support 10,000 users than to support 100, in a number of ways. And if the number of users levels off, then the number of new purchases (and hence income for the dev) goes away, and the dev is left supporting the existing user base for free. Unless the app was extremely easy to develop in the first place (so there’s profit “left over”), was outrageously successful (which most of them aren’t), or has an extraordinarily low maintenance burden (hah!), it will inevitably turn into a losing proposition for the dev.

And although users may like the deal they’re getting now, if it’s unsustainable for developers, it will eventually be unsustainable for the whole app store.

So is there an answer to this, a way for modern apps to have a sustainable business model?

The conventional answer in the pre-app-store software world was to charge for updates. When you bought Windows 7, you had no expectation that you’d get updated to Windows 8 for free. That’s not how old-school software works, and everybody knows it. New versions come with a price tag, and while there might be a price break for existing users (or not), it’s still not free.

The first problem with applying this to mobile or web apps is that none of the major app stores support this pricing model. You can put a price on your app for the initial installation, but there’s no way to attach a price to an update. This is probably why that same G+ post mentioned above went on to say, “This is a fundamental problem that needs to be fixed by the platform providers.”

But if you dig a little deeper, I think you’ll find that it’s not that simple; such a “solution” wouldn’t actually solve the problem for indy devs. The reason is bug fixes.

Although I’d like to charge for updates, as an ethical developer I realize that it’s not OK to charge for bug fixes. These are essentially flaws in my product, and it’s my duty to fix them, to the best of my ability. If Google Play let me charge for updates to my apps, there’d inevitably be some users who would elect not to do it – users who are happy to remain on the older version. But additional bugs will inevitably turn up in these older versions, and since it’s my responsibility to fix them, this means that I end up maintaining two different versions of each app… then three versions, then four, another one each time I release a paid update.

Sure, eventually I can end-of-life old versions, but the time scale for that is measured in years – it limits the problem, but by no means eliminates it. I can also mitigate things somewhat by good use of source code management (so ideally bugs fixes happen once in common code, rather than being duplicated), but this is also an imperfect solution. The reality is, paid updates would actually multiply my software maintenance load. This really isn’t much of an improvement.

An alternative approach to the pay-for-each-update model is to create a new app on the store for each major version. So I’d release MyApp 1.0 for $0.99, then later create a new “app” on the store for MyApp 2.0, also $0.99. This has the advantage that it doesn’t require changes by the platform provider, but has a host of disadvantages:

  • It doesn’t help the bug-fix/multiple-version maintenance headache outlined above.
  • Every time you create a new app, you’re essentially starting from scratch on the app store. You lose your user base, your ratings & reviews, you have to fight your way up the listings again, and so on.
  • Your existing users need to be notified manually of the new version.
  • Migrating users from the old version to the new one is a headache. Settings need to be transferred, the user can easily end up with multiple versions on their device, etc.
  • There’s no way to give a discount to existing users.
  • Many users would scream bloody murder if you tried this (see the “pay once, get updates forever” expectation above)

In other words, this is pretty bad “solution”.

Another approach which is sometimes proposed is a subscription model. There are several variations to this, but they boil down to the same basic idea: charge your users an annual subscription fee for updates. While this is another model that isn’t explicitly supported by the app stores, they do support subscriptions, so it can be accomplished by the developer in their own code; essentially, by only making certain features available to users who have paid their subscription fee. This neatly avoids the version-multiplication problem we’ve had up until now: there’s only one version of the app out at any one time.

So I believe that this approach has some merit, but it also has some hurdles. One of the largest is the simple use of the word subscription: in the mind of the customer, a subscription is usually something that gets delivered either continuously, or quite frequently. Think of a music service (your tunes are delivered on-demand), or a magazine (which is delivered monthly). More generally, a subscription fee is something you pay for a service, not for a product.

And delivering frequent software updates as a service is a big ask for a solo developer, especially one who’s supporting multiple apps. Quite simply, I don’t have the capability to deliver frequent, major updates to all of my apps. Releasing a new version of every app, every month is fine if you’re Google, not so much if you’re one person working on your own.

“OK, so don’t support multiple apps”, I hear you say. That’s fine in theory, but it assumes that the single app I choose to support brings in enough income to support me. This is a big reason why I have multiple apps in the first place: because no single one would support me on its own. And once I put an app out there – especially with an update subscription – I’m making a commitment to support that app. I can’t just say, “This one’s not profitable enough, I’m pulling the plug on it.” I can’t afford that, and it’s not fair to the subscibers.

So subscriptions come with a lot of baggage – they’re an imperfect solution at best. Any other possibilities?

The last “standard” solution is in-app purchases (IAPs). Again, there are variations, but the basic proposal is to charge users piecemeal for significant new features. I develop something new for an existing app, it goes in as an IAP, and existing users need to pony up in order to use it. Sounds feasible, and again, it is an approach that is supported today by the app stores.

And it’s a reasonable model when one thinks in terms of the long-standing user: paid $2 for v1.0 of the app last year, pays another $1 for this year’s 2.0 features, and next year may pay another $1 for more new stuff in what I label as v3.0.

The problem comes after several years of this: new users (who are coming to the app for the first time) will find that the app they’ve just paid $2 for comes with many of its best features disabled, and they have to pay another $1 for each of them. They’ll rightly feel like they’re getting nickel-and-dimed here, and will likely voice this unhappiness in an app review. Bad news all around.

But maybe we’re getting close to a good solution here. I think we might be, and I have a proposal to make this work. It’s based on the IAP-for-upgrade model, but with a twist: when the next major update comes, the features from the last update get rolled into the “base” version of the app, for free.

Perhaps the best way to explain this is with a concrete example.
2014: I release the first version of my app, and set a price on it, say $2.
2015: I have a major update for the app, and release it as “Upgrade Pack 2015” for $1 as an IAP.
2016: I’ve created some more new features, and bundle them into “Upgrade Pack 2016”, for another $1. But when I release this, Upgrade Pack 2015 goes away, and its features get rolled into the main ($2) app.
2017+: Lather, rinse, repeat.

A better labeling system might be to not tie it to specific years, but to use semi-traditional version numbers instead. So the above release history would look like this (the years are just to tie it to the previous example):
2014: version 1.0 is released for $2
2015: new features go into “Version 1 Upgrade Pack” (v1UP), for an extra $1
2016: version 2.0 (containing the features from both version 1.0 and v1UP) is released to all users, no extra charge. Simultaneously, new features go out as v2UP for another $1.
2017: version 3.0 released (v2.0 + v2UP), as well as a new, $1, v3UP
 . . .

Here are the important points to this approach:

  • At each release, existing users can choose whether the new features are worth another buck to them.
  • If not, they’re free to stay on “the old version”, and will get bug fixes all the same.
  • There’s never more than one code base to maintain; a single binary contains all features, and just has some of them paywalled behind an IAP.
  • At no point is there more than one Upgrade Pack available. So new users never get the nickel-and-dime feeling: there’s just the main app, plus one optional Upgrade Pack.

Looking at it another way, users are paying for “early access” to the features in each Upgrade Pack: if they want to wait, they will get them eventually, when the next UP is released.

About the only downside I see is that you’d probably need to explain this to the users as simply as possible, because it is a bit unorthodox. But that’s probably doable. [And with luck, it could even catch on and become orthodox. Call it the vnUP approach.]

Oh, and IAPs themselves are kind of a PITA, and need to be re-implemented for each app store you’re selling on (Google, Amazon, Apple, Samsung, etc.). But that’s one-time pain, and this work can possibly be re-used between projects.

One nice upside is that this can be layered onto a mature app, one that’s already in the wild with an existing user base. As long as you roll out your first UP along with some other, free bug fixes and minor enhancements, PR shouldn’t be too problematic. Then your pump is primed to keep the ball rolling with later versions.

But the big upside is that the app store business actually becomes sustainable. If a dev keeps adding new features, she has a legitimate opportunity to monetize her existing users on an ongoing basis. Everyone’s happy: the developer’s making a living, and the users get continuing updates, for a price that’s still very reasonable – or even for free, if they’re willing to wait. It’s a win for everyone.

Users: what do you think? A fair compromise?

Developers: are you with me?

Testing In-App Billing on Android

I’ve spent the last few weeks extending Wearable Widgets with in-app purchasing (variously known as IAP, in-app billing, or IAB). Honestly, there’s no good reason why this should have taken weeks. I can immediately think of a couple of reasons why it has, though.

The first is security. Because IAB is a commercial transaction, and because some lowlife will always be looking to scam you out of two bucks, you need to apply various layers of security to it – and these add time and effort.

A paradoxical aspect of this is that you’re specifically advised not to use any code examples you might find online, especially those in the documentation, because the scum who crack these apps will have seen all those code structures before – and will probably have scripts ready to break it.

But on the other hand, it seems to me that there’s a real downside to asking myriad developers like me to roll their own IAB solutions. Most of us are developers with no significant security experience – meaning that our homebrewed solutions are probably riddled with security holes and rookie mistakes, making them much less secure than code that’s been developed by security professionals. It’s a bit of a programming paradox, really.

Further, Google also includes something they call an IabHelper, a pre-written wrapper around all of the IAB routines, and many of their examples are based around this helper class. But it seems to me that this flies in the face of the roll-yer-own security recommendation; I have to believe that any two-bit script-kiddie app-cracker knows right where IabHelper lives, exactly how to recognize it (even in obfuscated code), and how to exploit it. Seriously, why would Google even provide this?

But that’s not really what I want to write about here.

The topic I want to cover, the other area which has cost me a lot of time in my IAB implementation, is testing. Part of that is simply because it’s a complicated beast – OK, fair enough. But a big part of it is because the documentation for testing this stuff is about as clear as mud, if not actually misleading in some places. So I thought I’d share my experience in testing Google’s IAB as of mid-2014. Be warned, from here on in this entry’s going to be pitched at Android devs who are elbow-deep in IAB; I’m not going to explain every term along the way. If you’re not a developer, you may or may not find it worth your while to read on. But if you are in the target demographic, hopefully what follows will save you some anguish.

Google provides a couple of doc pages about IAB testing, and you should start by reading those. They lay the groundwork, and nothing they tell you is really wrong – it’s just not quite the whole story. But nonetheless, you should start there, and get some understanding of the lay of the land.

Now, I’m going to tell you the real story. Here’s the first gotcha: that first link above says that there are two ways to test your IAB app, test purchases and real purchases. And the page no sooner describes those two before it goes on to discuss a third way, static responses. So the main thing I’d like to do here is to lay out the three ways to test IAB, with the things you need to know about each. I’ll present them in the order you should do them; complete your testing with one before you move on to the next.

Stage 1: Static Responses

This is where you should start: write your first pass at your IAB implementation, unit-test all the routines involved, and send the transactions off to Google Play with an SKU of android.test.purchased. [You can also use .canceled, .refunded, and .item_unavailable to test unsuccessful responses. But let’s go for success right now.] These are the easiest tests, because you don’t need to upload or sign your APK in any way (other than the normal debug signature that the IDE automatically applies). These tests can also be run by any user – although apparently you’ll get incomplete information returned if you don’t test using your developer account, so I recommend sticking with a device registered to the same Google ID as your Play developer console. When you issue an IAB request with one of the static-response SKUs, the process will look something like this:

  1. The purchase dialog Google Play shows will be completely dummied-up (see above).
  2. Assuming you’re using android.test.purchased, the transaction always succeeds.
  3. It returns to the calling activity’s onActivityResult() handler with a resultCode of -1, and a blank INAPP_DATA_SIGNATURE, but otherwise real values matching what you sent in the purchase request.

One important point I didn’t see anywhere in the docs: after you use a static-response SKU once, that SKU is now “owned” by the user that the device is registered to. And it will show as such in any subsequent IAB calls, which makes retesting a hassle. Apparently, it will reset by itself in a day or so, though I didn’t test this. I didn’t have the patience to wait a day between each debugging run of my app. But it turns out that you can also consume it in your app, with code like this:

    3, context.getPackageName(), purchaseToken);

where purchaseToken is returned from the purchase request you sent. In my experience with static responses, the purchaseToken was a simple construct like “inapp:my.package.name:android.test.purchased”, but YMMV.

And that’s about it for static responses. When you’ve done all the testing you can with them, you’re ready to move on to…

Stage 2: Real SKU, test user

Update 10 May 2015:

Since I wrote this post 11 months ago, Google has completely overhauled their  “test purchase” procedure. At the least:

    • Apps can no longer be in draft on Google Play for non-static purchases; they must be published to some channel (alpha, beta, or production).
    • IAB transactions for apps published to alpha channels do not cost whitelisted users real money. This was how I expected things to work last year (see below); now, they actually do.
    • With the advent of Android Studio, it’s now possible to debug an app signed with a production cert. So handy!

I may do a new writeup on it at some point, but until I do, be aware that much of whatI did write in this section is no longer correct – and that Google’s docs are actually pretty reasonable now.

This is the case that Google calls test purchases, and it involves sending your real item SKUs but in a test mode. Everything is like a real purchase, except that no money actually changes hands. It sounds so simple in the documentation… but there are a couple of serious pitfalls.

First, you’ll need to get things set up on your Google Play developer console. You’ll also need to wait several hours after doing these changes for them to roll out through Google’s server network.

  • You’ll need to have created your IAB items (on the In-app Products tab of your app in the console)
  • The user ID(s) you’re going to test with must be whitelisted for IAB testing: Settings > Account Details > License Testing. Note that real SKUs can’t be purchased by the user who owns the Google Play account, even in test mode.
  • You need to upload a signed APK, with a higher versionCode (in the manifest) than anything you have published on Play.

When you actually do your testing, it will also need to be with a signed APK, and one that has the same versionCode as the uploaded-but-unpublished APK in the last step above.

The bad news here is that there’s no using the debugger at this stage: logcat is your friend. But the good news is that it doesn’t actually have to be the same APK as you’ve uploaded to the dev console; it just needs to have the same versionCode. This requirement – for an uploaded but unpublished version of your APK – is never really, explicitly covered in the docs. It’s mentioned obliquely, but nowhere near as directly as it needs to be.

If your test version hasn’t been uploaded to the APK tab on the console, the IAB call will fail. OTOH, if it is published at all – even in the alpha or beta channel – your test users will really get billed for the IAP.

This one took me days to work out: silly me, I thought the alpha channel was specifically for this kind of testing, and as long as I had the user’s Gmail address on the whitelist, the transaction wouldn’t post. Wrong. The whitelist is ignored for published APK versionCodes.

In fact, it’s even a bit worse than that – the whitelist is ignored for all versionCodes less than or equal to anything published. Let me illustrate that with a concrete example:

  1. The production versionCode of my app is 9 – that’s my baseline, before I started implementing IAB.
  2. After I had a first cut of IAB done – with versionCode 10 – I published it to my alpha-test group and had a whitelisted user try it. He got charged, because 10 wasn’t unpublished.
  3. Learning from these mistakes, I uploaded a later version (13) to Google Play, but did not publish it. I then emailed the APK to some whitelisted testers, who successfully used the IAB feature without being charged.
  4. Moving closer to release, I built versionCode 14 and published it to beta. I fully expect users of this version to be charged, and they are.
  5. However: the next day, one of my whitelisted test group from step 3 – still on versionCode 13 – tried out the IAB and got charged for it. My best explanation for this is that, even though 13 is still unpublished, the whitelist is ignored, because 14 is published.

The bottom line is, upload to Google Play but don’t publish anything at this stage. But once you have all those pieces in place, and have given them time to take effect, here’s how it’ll go:

  1. The purchase dialog will be real, but with the extra “test order” line shown above.
  2. The purchase always succeeds, AFAICT
  3. The return values are all real (token, payload, etc)
  4. The transaction appears in your Google Wallet Merchant console with a “Test:” prefix

As with static responses, this SKU is now owned by the user, causing a similar headache for any retesting you need to do. You’ll need to cancel it from your Merchant console (or alternatively, it will apparently expire in a week or two).

Be aware that, in addition to cancelling the purchase, you’ll also need to clear the cache for Google Play Store and Play Services on the device – and probably reboot, and maybe wait an hour or so – before the SKU will stop showing up as owned.

Stage 3: Real Purchases

This isn’t really “testing” IAB any more; everything is live, from the APK down to the financial transaction. But Google includes it on their testing page, so I’ll discuss it briefly here as well. Basically, this is the scenario your user will be in whenever the versionCode of the APK they’re running matches one that’s published on Google Play, in any channel (Alpha, Beta, or Production). It’s also the way the purchase will play out if the user isn’t on your IAB, or the whitelist entry hasn’t percolated through the Googlenet.

As confirmation of any of these situations, any time Google Play shows a purchase dialog without the “test order” verbage (compare the above and below screenshots), the user will get charged for the purchase.


I’m not going to go through the whole process here, because it’s a live transaction, and everything happens accordingly. If you do need to retest in this case, its like Stage 2: clear the cache for Google Play Store and Services, reboot the phone, wait an hour.

Time Is Money

One recurring theme you might notice from the above is all of the waiting that goes on. From hours to weeks, there are many, many aspects of IAB testing which require you to just twiddle your thumbs (or go read Engadget) for extended periods. Which is why testing this has taken so damn long. As of today, I’m really not sure that IAB was worth doing, especially for (what should have been) a dead-simple implementation like mine: I have exactly one product, essentially an unlock key to turn the “trial” version of my app into the “full” version. There are several other tried-and-true ways to implement this sort of freemium model, and I’m not at all convinced that IAB was the right one to choose. Sure, it may be slightly lower-friction for the users – but enough so to justify weeks of extra developer time? Will it actually gain that many more conversions? It’s impossible to know.