art-collector: learning about android app links

Posted by



This is an old draft. There’s more detail and a better structure here:

View at Medium.com


art-collector is a small app I wrote which displays a selection of paintings from the Harvard Art Museum API.


It has three main screens:

  • the gallery showing a selection of paintings
  • an artist gallery, showing the paintings created by a single artist
  • a painting screen, showing a single painting

art collector gallery, clicking through to the Worthington Whittredge, clicking through to A Sheep Cote on Lake Albano

I want these screens to be accessible from these web-links:

The screens are organised into different modules, with the Gallery part of the base feature module, app, and artist and painting feature modules for the other two, depending on app:


Deep-linking was a bit disappointing. I wanted to use intent-filters on each Activity but in my understanding, the regex used for android:pathPattern is too limited to distinguish between the links I listed above.

I ended up adding a DeepLinkActivity in the base module:

<activity android:name=".DeepLinkActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />

<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />

<data android:scheme="http" />
<data android:scheme="https" />
<data android:host="art-collector.ataulm.com" />
</intent-filter>
</activity>

This Activity has no UI — it just consumes all the links (for art-collector.ataulm.com), parses the URI, and redirects to the correct Activity.

private fun artistGallery(): Intent {
return Intent(Intent.ACTION_VIEW)
.setClassName(
BuildConfig.APPLICATION_ID,
"${BuildConfig.APPLICATION_ID}.artist.ui.ArtistActivity"
)
...

The problem with this is that there’s an implicit dependency from the base module to feature modules (so that it can redirect to them) — why does the base know about Activity classes in features?

It’s implicit because it uses the qualified component name as a String (which is pretty fragile — will rely on integration tests). For now, it’s a code smell I can live with — I’d rather the base module not depend on the feature ones.

But hang on! Is that enough? Are we done? No. These are just deep links. Both art collector and any app that handles HTTP links (like Google Chrome) will be presented to the user when this link is clicked:

Disambiguation dialog showing art collector and Google Chrome for Android as options

App Links are a little different. Android checks that you own a given domain, and then will just open your app without showing the disambiguation dialog to the user.

View at Medium.com

I created a sub-domain for my website (art-collector.ataulm.com) to try for myself.

First, we need to generate the file that we’ll put on our website. I used the statement list generator:

View at Medium.com

When I tested it though (using the same tool), it said it couldn’t find it. I learned that it’s because my website didn’t have a valid SSL certificate, which is necessary, so I got one from SSLForFree.com. And then it worked!

Successful test for Statement List Generator

There was one more thing that we need to do to enable App Links for Android. Add android:autoVerify="true" to any of the web URL intent filters that include action.VIEW and category.BROWSABLE :

<activity android:name=".DeepLinkActivity">
<intent-filter android:autoVerify="true">
...

and it’s done!

Here are the PRs related to this feature:

Please comment below, reach out on Twitter or comment directly on the pull requests!