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:
[cc lang="Java"]OpenIdManager manager = new OpenIdManager();
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](http://developer.android.com/guide/topics/manifest/intent-filter-element.html) of the `AndroidManifest.xml`. The [Intents](http://developer.android.com/guide/topics/intents/intents-filters.html) 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](http://developer.android.com/reference/android/content/Intent.html) 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](http://developer.android.com/guide/topics/manifest/intent-filter-element.html). 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](http://developer.android.com/guide/topics/manifest/data-element.html):
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.
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:
To test it, it is sufficient to create a simple html file:
and click on the Click here link!
Remember to have INTERNET permission enabled for app.