Let down by Android 5.0's half-baked screen pinning API

androidlollipop5dot0cnet.jpg
androidlollipop5dot0cnet.jpg

 Image: Nicole Cozma/CNET

I came to smartphone development by way of embedded systems, meaning I spent the first decade of my career working on dedicated hardware computing platforms: automatic teller machines, industrial controllers, and point of sale terminals. I love a lot of things about Android as a consumer-facing general purpose computing platform, but it has always fallen short when dropped into a fixed-purpose device.

Want an example? Stick a pre-Lollipop build of Android on a kiosk in a library and see how long it takes before some kid manages to get out of your book catalog and download Angry Birds. Even with third-party add-ons, in my experience Android has been poorly suited for specialized hardware solutions. You could always root the device or install a custom ROM, but in most cases that means voiding the warranty on your shiny new hardware.

Since this type of application is near and dear to my heart, I was quite excited to read about a new feature in Android 5.0 called screen pinning. According to Google's description:

"Android 5.0 introduces a new screen pinning API that lets you temporarily restrict users from leaving your task or being interrupted by notifications."

And more specifically:

"This could be used, for example, if you are developing an education app to support high stakes assessment requirements on Android, or a single-purpose or kiosk application."

Perfect! A way to lock down the standard Android distribution on a store-bought tablet -- this is exactly what I was looking for. I couldn't wait to fire up Android Studio and give it a try. Based on a read-thru of the documentation, it appeared that there were only two API calls involved: startLockTask and stopLockTask.

In a few minutes I threw together a sample that looked something like this:

public class MainActivity extends Activity implements OnClickListener { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findViewById(R.id.pin).setOnClickListener(this); findViewById(R.id.unpin).setOnClickListener(this); } @Override public void onClick(View v) { if (v.getId()==R.id.pin) { startLockTask(); } else { stopLockTask(); } } }

It wasn't until I began playing with the app that the inherent problems with the API became apparent. First, there is no call to tell if an attempt to pin an app actually succeeded -- this includes if the user uses the dialog to cancel. Second, you can subsequently call startLockTask as many times as you want, but calling stopLockTask on an app that is not locked (and, remember, you can't ask for the state) causes a crash. The only solution I found was wrapping the entire mess in a try-catch.

To further complicate things, apps can be pinned or unpinned both programmatically as well as manually via the Settings menu. Neither seems to talk to the other. So if I pin an app through my program, then the user unpins it through the menu, my program is completely unaware.

The final nail in the coffin was when I began investigating how to pin an app without user confirmation, as in the case of the example suggested in Google's documentation: a single-purpose kiosk. You would need to make sure the app started in locked mode and stayed that way. I found the documentation fuzzy in this regard. One technique required rooting the device, and the other required writing a custom NFC trigger?

I agree that programmatic app pinning should not be easy or something that can be done accidentally -- after all, you don't want that same kid who broke out of your kiosk to play Angry Birds when you were running KitKat to turn around and lock you out of that device now that you upgraded to Lollipop. Still, how about a boot loader menu option or something tied to a factory reset?

At the end of the day I just felt disappointed -- it seemed like the feature was a much-needed update that turned out to be only half-baked. There are consumer facing uses for the API as it exists now, but it's just not the robust sort of API that is really called for in this specific application. Too bad.

I hope Android 5.0's pinning feature is paving the way for what is ahead.

Automatically subscribe to TechRepublic's The Android Expert newsletter.