Wednesday, 30 September 2015

Guide to implementing App Linking on Android 6.0 Marshmallow

Knives and forks
Android Marshmallow has a feature that can make life better for developers who feel that their app experience is better than their web experience. It's called App Linking and it ensures that your app always handles links for your domain without the disambiguation dialog you would normally see. 
This is the disambiguation dialog I see when I click on a link to Stack Overflow. The feature is called App Linking but the connection between the app and the web site is called an App Link. And, in case you're wondering, it's unrelated to Facebook's initiative.

This is a short guide to implementing and testing the feature. Let's start.
  1. Go through your manifest and identify the domains (and subdomains) your app claims to be able to support.
  2. Add an assetlinks.json file pointing to your app (or apps) to each of these domains or subdomains. If there's a domain or subdomain that you don't control then the verification process will fail. You can either remove that host from your manifest or you can remove the CATEGORY_BROWSABLE category from the manifest as this will have the same effect: your app won't intercept request for other people's domains or subdomains.
  3. Make sure you serve the assetlinks.json file over HTTPS on every domain or subdomain that you support. Your entire site doesn't have to support HTTPS. Serving just the assetlinks.json file over HTTPS will suffice.
  4. Make sure the assetlinks.json file is served with content-type “application/json” since it won’t work with any other content type.
  5. As documented here you should use our debugging tool to verify that each domain or subdomain has a valid assetlinks.json file. Here's an example for one of my sites.
If everything works you should see a message like this:
Add an autoVerify attribute to the intents in your manifest for each of these domains.
Be aware that the verifier doesn't follow redirects so it won't work if you try to shortcut this by having one canonical file that all the other URLs redirect towards. You can find more details about the install-time verification process by reading this excellent but now outdated guide from Christopher Orr.

Don't forget that all of these files must match exactly so if you update one of them you must update all of them. Fortunately the SHA256 in the assetlinks.json is based on your app's private keys so once you've added your release and debug keys you should never need to change it.

Between this guide and the official documentation you now know everything you need to make App Linking work on Android Marshmallow. If you still have any questions then ask on Stack Overflow using the tag: android-app-linking.

Friday, 19 June 2015

Omnivorous inclusiveness and the closing of the browser parenthesis

In the past I've thought of the web as a convoy of browsers. That turns out to be wrong.

Nowadays (thanks to a long lunch with Paul Downey, Jeni Tennison,  et al) I've begun thinking of the web as a ship of Theseus where, despite replacing every single part of the stack, what's left is still recognisably the web.

This made me realise that we are surrounded by unexamined and ossified metaphors that are in danger of becoming thought-terminating cliches. For example:
- open web versus (presumably) closed web
- the web browser is the web platform is the web
- the web as a platform
- web apps
- web versus native

One of the reasons I present at conferences like OpenTech is because I want to have my mind changed and my complacent metaphors jolted. This year my presentation came out of asking myself "what do I most like about the web?" My initial list was:
- its universality (view source meant everybody everywhere could cut and paste their way to something that sort of worked).
- its omnivorous inclusiveness (it tended to absorb neighbouring or competing technologies like WAIS, Gopher, NNTP and FTP).
- its hypertextuality, intertwingularity and document orientation because they open the door to new forms of argumentation as well as letting us create living documents.
- its peculiar notion of addressability without guarantees about the nature of the resources at the end of the links.

This presentation started out as my oft-repeated but never documented "HTML 3.2 was the last good version of HTML" rant. It channeled some of my distress with the ideas behind HTML 5 and the notion that there is a "web platform" which arbitrarily excludes certain technologies (like Flash and native apps) but includes others (like JavaScript). In its final form it asked if today's open web platform is still the web. Now I have my answer.

That answer is driven by two realisations. Firstly it turns out that browsers are not the only user agent. They're not even the only kind of user agent. Secondly now that deeplinking is becoming mere linking it is clearer than ever that apps are just domain-specific user-agents. As a consequence it becomes clear that native versus web is merely a debate about whether we should use 1 universal user-agent or N domain-specific user-agents.

Since browsers and native apps are merely different kinds of user-agents I think it's a mistake to conflate browsers and the web. I think we run the risk of mistaking the capabilities and roadmap of today's most popular kind of user agent for the capabilities and roadmap of the web. For example user-agents that don't support Javascript or CSS are equally legitimate but less popular constituents of the web. However there's a strong temptation to consider them to be obsolete or lagging members of our convoy and thus leave them behind.


The web has changed, is changing and will keep on changing. The convoy is bigger than I originally thought because there are lots of overlooked user-agents out there. These apps aren't part of the web any more than browsers are but their addressable/linkable content most definitely is part of the web. Just because that content has a preferred user-agent doesn't change this.

Perhaps, like the Gutenberg Parenthesis, there is a 'Browser Parenthesis' that is also closing?

Update: The audio from my OpenTech 2015 talk is now available.

Friday, 2 January 2015

Awkward questions for those boarding the microservices bandwagon

Why isn't this a library?
What heuristics do you use to decide when to build (or extract) a service versus building (or extracting) a library?

How do you plan to deploy your microservices?
What is your deployable unit?
Will you be deploying each microservice in isolation or deploying the set of microservices needed to implement some business functionality?
Are you capable of deploying different instances (where an instance may represent multiple processes on multiple machines) of the same microservice with different configurations?

Is it acceptable for another team to take your code and spin up another instance of your microservice?
Can team A use team B's microservice or are they only used within rather than between teams?
Do you have consumer contacts for your microservices or is it the consumer's responsibility to keep up with the changes to your API?

Is each microservice a snowflake or are there common conventions?
How are these conventions enforced?
How are these conventions documented?
What's involved in supporting these conventions?
Are there common libraries that help with supporting these conventions?

How do you plan to monitor your microservices?
How do you plan to trace the interactions between different microservices in a production environment?

What constitutes a production-ready microservice in your environment?
What does the smallest possible deployable microservice look like in your environment?

2015 technology wishlist

The start of the year is a good time to be thinking about the end of the year and the kind of world I would like to see. Usually this leads to resolutions and predictions. Unfortunately I find most predictions worthless since the pundits seldom go back to check on their previous predictions. The other problem is that people start out making predictions and then the articles turn into wishlists. That's why this year I'm just going to write a wishlist.

I'd like to see:
  • more viable identity providers.
  • more social environments that understand the benefits of Reed's Law and ridiculously easy group-forming.
  • Wikipedia starting to use identity technology to improve the user experience. For example if I donate or become a member then I'd like to stop seeing obnoxious adverts (and they really are adverts) asking for money. The Guardian's membership programme is a good model that Wikipedia should adopt.
  • a viable successor to the Leica M9. The Leica M Type 240 just isn't a big enough improvement.
  • a viable replacement for Aperture. I have zero faith in the upcoming Apple Photos app and there isn't enough official  support for migrating from Aperture to Lightroom.
  • a viable replacement for the old Mac Pro. The new Mac Pro abandons all of the strengths of the old Mac Pro.
  • more mujicomp and less ryanaircomp.
  • fewer people bemoaning the web we lost and more people asking new questions about the world we actually live in where everything gets touched by the network.
  • more device-native apps. I'd like to see more apps that are designed to really exploit the capabilities of our current generation of interconnected mobile devices.
  • more apps that provide multi-device workflows
  • more experience reports about the issues involved in building backend services that support multiple native mobile and web apps.
  • the Software Craftsmanship community changing its focus from converting new people to helping each other learn and grow.
  • less hype/advocacy for microservices and more documentation/descriptions of techniques that work with collections of small services. You'll be able to tell if you're seeing hype by the number of awkward questions that they raise.

Wednesday, 24 December 2014

What makes native mobile apps special?

That tweet was inspired by a conversation with Scott Jenson in which he asked: "what is mobile good at?" My response was: "anything that gets better if you can do it everywhere and add new sensors or transmitters."

I think I now have a better answer to a slightly different but more evocative question: what makes native mobile apps special?

Firstly these apps are special because they can use every sensor and transmitter on your mobile phone. That means they will also be the first to get access to new sensors and transmitters as they are added to these devices. This gives them more power than any other apps that have ever existed.

Secondly these apps are special because they're installed in a device that the user will carry around all day every day. That means that they will see more usage per user since there will be so many more opportunities to use them. It may even be time to start measuring average usage per user (AUPU) as a more quantitative version of Larry Page's 'toothbrush test.'

Finally these apps are special because they're on devices that will eventually end up in the hands of every post-pubescent person on the planet. That means they will eventually end up with more users than anything we've seen so far.

In short...ubiquity.

Saturday, 21 December 2013

What is the state of the art in Android sharing?

I meet a lot of people in my job. Consequently I get to see lots of different companies trying to create the best possible Android sharing experience. Just about all of them start off with the standard sharing system based on intents and the standard chooser dialog.

It's compatible with just about all devices but it gives users an alphabetical list of applications even though many of these may not make sense in the given context. For example the list below shows the stock Email app even though I'm a Gmail user who has never configured the other email app on my tablet. This dialog also has issues for users who install lots of apps and its alphabetical ordering means we're starting to see developers gaming the system in order to be at the top of the list.
There's also the problem that the intents system doesn't let you customise the recipient other than by passing in a set of key-value pairs so developers (like The Guardian and Soundwave) offer an explicit Google+ share button in the action bar for users who are signed-in with Google+. This gives their users direct access to interactive posts. They also offer the standard chooser dialog as well.

The Gallery and Keep apps try to remember the last N apps the user has shared and present them to the user by using the ShareActionProvider added in Ice Cream Sandwich. Shazam's implementation is built on the same idea but does something slightly more sophisticated with it. It shows a list of the apps I've recently shared content to but adds various social services to the top of the list. It also knows which social service I signed-in with and adds it to the action bar as a separate button. The assumption is that I'm more likely to want to share newly discovered music to that social network than with the random assortment of apps on my device.

Snapette and Fancy implement simpler variants on the same idea. They hardcode a small set of social services (including Google+, Twitter and Facebook) even if they're not installed on the user's device. Clicking on those options takes users to a sign-in dialog before they can share. In their defence Fancy does offer a 'More' button that goes to the standard chooser dialog. This offers an escape hatch for users who want to share to contexts other than social networks.

Another alternative can be seen in the Spotify app. They make their own version of the standard chooser dialog but add a Spotify button to the top. That's because the standard chooser dialog doesn't give you much control over the order or the membership of the list it uses.

Unfortunately if you make your own chooser dialog you're going to have to expend a lot of effort to make it resemble the real thing. Or you can just show a simple list.

So what do I recommend? Ideally you should use the ShareActionProvider but nowadays a lot of apps are finding that deep integration with social services drives significant traffic and engagement. In that case...

If the screen is large enough then you should have your preferred share option in the action bar next to a button that launches a custom share list that shows your preferred apps with a More button that sends the user to the standard share dialog. This pushes users towards the developer's preferred networks (these could be the app's network or the services that the user has used to sign-in) but still gives users a way to get to all of apps they've installed.

On smaller screens you should have a share button that sends the user to a custom list containing the developer's preferred networks with a More button that sends users to the standard chooser dialog.

This approach balances simplicity of implementation, predictability (users shouldn't have to wonder why options are appearing and disappearing from their chooser dialog), extensibility, value to the developer and responsiveness to device size. This may seem complicated but fortunately a large amount of this can be implemented using the ShareActionProvider and its support for fine-grained tracking of history.

This is a complex and subtle topic with many different approaches being explored by lots of very smart people. I'm not going to pretend that this blog post is the final answer. After all, there's always the option of building something completely specific to your needs.

Wednesday, 11 December 2013

Migrating to Google+ Sign-in in 5 minutes

Are you looking to understand the available strategies for migrating your existing Google login solution to Google+ Sign-in? Well… You’ve certainly come to the right place
Who are you. You are you
If you're using OpenID1, OpenID2, OAuth1 or OAuth2Login then we have a detailed migration guide:

I strongly recommend reading it. Or at least skimming it since the social login market is bigger and more complicated than it seems. The following is merely a high-level restatement of the migration guide for people who aren't really sure which of the aforementioned technologies they're using.

If your existing system captures the user's email address using a Google identity solution then you can just:
  • migrate to Google+ sign-in
  • ask for the email OAuth scope
  • fetch the user's email address using one of our recommended approaches
  • look up the user in your database by email
  • associate them with the existing record that matches that email address since Google guarantees that the email addresses are valid
If your existing system doesn't capture the user's email address then life gets interesting.

If you're sure you're using OAuth1+OpenID2 then you can follow the instructions here: which tell you how to fetch your old identifier and find out the equivalent identifier with Google+ Sign. Once that's done you can just associate the new identifier with the existing record and the user can sign-in in future with Google+ Sign-in.

If you're using something else then you can ask the user to sign-in twice: firstly with your existing Google identity solution then with Google+ Sign-in. Now that you have both identities you can associate them in your database. Once a critical mass of your users have gone through this process then you can stop using the legacy identity solution. If you have to use this option then I would also recommend reading Michael Mahemoff's experience report from's migration: since I got the idea from him.