When Grass Was Greener

Rants on programming, photography, life, universe and everything

Starting Android application from browser URI

| 2 Comments

Recently, when playing with adding OpenID support to one of Android programs – namely Tracks – I have faced a simple problem.

When using OpenID, one has to delegate authentication to some 3rd party website. This is OpenID Provider. Thanks to this our application (the Relaying Party) does not have to know identifier/password and user authenticates himself on a page he knows. Nor do we have to maintain the security of these in application.

So I’ve started looking at JOpenID.

The very first lines in JOpenID QuickStart say:

1
2
OpenIdManager manager = new OpenIdManager();
manager.setReturnTo("http://www.openid-example.com/openId");

After successful login OpenProvider service will redirect browser to this return address together with OpenID Identifier, encrypted association handler.

Question is: how can we provide return address so we can start our application and with resulting URL from browser?

The answer lies in intent filters of the AndroidManifest.xml. The Intents are the glue that cement the Android system, the juice that runs it. Intent system is responsible for starting Activities, interacting between applications and system services.

For each Activity one can declare which intents it shall interact with – that is, say which intents will activate it. This information is stored during application install and browsed by system when an intent is sent.

To declare what intents an activity will interact with, one needs to specify an intent filter. Such intent filter contains action and possibly category and data fields.

For example the main activity of application has a filter with action android.intent.action.MAIN and category android.intent.category.LAUNCHER. Thanks to this, Android system knows that application should appear in the menu (category = launcher) and is an entry point into application (action = main).

So I want to start my application from the browser using a URI. A URI looks like (in short) scheme://host/path/?query#fragment. Let’s have a closer look at data field of intent filter:

1
2
3
4
5
6
7
<data android:host="string"
         android:mimeType="string"
         android:path="string"
         android:pathPattern="string"
         android:pathPrefix="string"
         android:port="string"
         android:scheme="string" />

Looks similar.. And for starting app from browser it is sufficient to define only scheme part. Of course an action is needed for the filter: android.intent.action.VIEW is ok. But these two elements are not enough, categories are needed.

First of them is CATEGORY_BROWSABLE:

Activities that can be safely invoked from a browser must support this category. For example, if the user is viewing a web page or an e-mail and clicks on a link in the text, the Intent generated execute that link will require the BROWSABLE category, so that only activities supporting this category will be considered as possible actions. By supporting this category, you are promising that there is nothing damaging (without user intervention) that can happen by invoking any matching Intent.

and CATEGORY_DEFAULT:

Set if the activity should be an option for the default action (center press) to perform on a piece of data. Setting this will hide from the user any activities without it set when performing an action on some data. Note that this is normal -not- set in the Intent when initiating an action — it is for use in intent filters specified in packages.

Bringing all this info together the StartOnUri activity is declared and intent-filter defined in the manifest:

1
2
3
4
5
6
7
8
9
        <activity android:name=".StartOnUri"
                 android:label="@string/app_name">
            <intent-filter>
                <data android:scheme="startonuri" />
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT"></category>
                <category android:name="android.intent.category.BROWSABLE"></category>
            </intent-filter>
        </activity>

To test it, it is sufficient to create a simple html file:

1
2
3
4
5
<html>
<body>
  <a href="startonuri://dummy">Click here</a>
</body>
</html>

and click on the Click here link!

2 Comments

  1. Hello,

    I tried it, but Google does not seem to accept non-http scheme. Any idea what I might do ?

  2. The exact example has startonuri:// scheme.. So this is non-http. Eg. look also that any link with market:// scheme, launches Android Market when opened in Android’s browser.

Leave a Reply

Required fields are marked *.

*