The Space For App Developers

Beyond Plain Old HTML Objects

Defining custom URL schemes for your AIR mobile applications

with 21 comments

If you’ve ever wondered if you can register your own URL schemes for your AIR mobile applications running on iOS or Android platforms the answer is yes! Actually it is very simple and you can do it by adding few extra lines in the *-app.xml document. Once you do your application can be invoked directly from other applications or browser with a simple <a href="my-scheme:">open app</a> link click.

(Custom URL schemes are especially useful if you are doing OAuth authentication in your app and you want to redirect the user back to your application after the authorization in the browser. You can find out more about OAuth in AS3/Flex applications in my ADC tutorials.)

To register a custom URL scheme like my-scheme: you simply add the following code in your *-app.xml.

Android settings:

<android>
    <manifestAdditions>
    <![CDATA[
        <manifest android:installLocation="auto">
            <application> 
                <activity> 
                    <intent-filter> 
                        <action android:name="android.intent.action.VIEW"/> 
                        <category android:name="android.intent.category.BROWSABLE"/> 
                        <category android:name="android.intent.category.DEFAULT"/> 
                        <data android:scheme="my-scheme"/> 
                    </intent-filter> 
                </activity> 
            </application> 
 
            <uses-permission android:name="android.permission.INTERNET"/>
 
        </manifest>
    ]]>
    </manifestAdditions>
</android>

iOS settings:

<iPhone>
	<InfoAdditions>
	<![CDATA[
		<key>UIDeviceFamily</key>
		<array>
			<string>1</string>
			<string>2</string>
		</array>
 
		<key>CFBundleURLTypes</key>
		<array>
			<dict>
				<key>CFBundleURLSchemes</key>
				<array>
					<string>my-scheme</string>
				</array>
				<key>CFBundleURLName</key>
				<string>com.myapp</string>
			</dict>
		</array>
 
	]]>
	</InfoAdditions>
        <requestedDisplayResolution>high</requestedDisplayResolution>
</iPhone>

Also you can pass additional arguments to your app from the invoking source. Arguments can be passed in the URL scheme after the colon; for example: my-scheme:myparam. Then in your application you can listen for InvokeEvent.INVOKE event on the NativeApplication.nativeApplication instance. The received event object contains an arguments property that returns an Array with the invoking scheme and parameters in the first item, so it would be my-scheme:myparam value. Next you can parse the value of your argument, and take some action in the application based on its value.

In a Flex Mobile app you can register an InvokeEvent.INVOKE event listener in the preinitialize phase as in following snippet:

 
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
			   xmlns:s="library://ns.adobe.com/flex/spark"
			   preinitialize="application_preinitializeHandler(event)">
 
	<fx:Script>
		<![CDATA[
			import mx.events.FlexEvent;
 
			protected function application_preinitializeHandler(event:FlexEvent):void
			{
				NativeApplication.nativeApplication.addEventListener(
					InvokeEvent.INVOKE, onInvoke);
			}
 
			private function onInvoke(event:InvokeEvent):void
			{
				// You can parse argument value from event.arguments property
				lblArguments.text = "Arguments: " + event.arguments;
			}
 
		]]>
	</fx:Script>
 
	<fx:Declarations>
		<!-- Place non-visual elements (e.g., services, value objects) here -->
	</fx:Declarations>
 
	<s:Label id="lblArguments" horizontalCenter="0" verticalCenter="0" />
 
</s:Application>

One caveat is that invoking other apps with the custom URL schemes from AIR apps is not possible. The AIR security model is more restrictive and it limits schemes to: http:, https:, sms:, tel:, mailto:, file:, app:, app-storage:, vipaccess: and connectpro:. You can find more about it here and here.

Written by Piotr Walczyszyn

August 2nd, 2011 at 5:15 pm

Posted in Articles,Examples

Tagged with , ,

21 Responses to 'Defining custom URL schemes for your AIR mobile applications'

Subscribe to comments with RSS or TrackBack to 'Defining custom URL schemes for your AIR mobile applications'.

  1. Cool! What about PlayBook?

    Jon

    2 Aug 11 at 7:45 pm

  2. Nice post!

    Those docs are wrong though, all other URI’s are not restricted on the Playbook, appworld://, help://, maps:// all work…

    SHawn

    2 Aug 11 at 10:13 pm

  3. thanks for the tip. On android, I successfully used it to do an oauth with soundcloud.com. However, I’m briefly seeing a page blip that says “you do not have permission to open this page.” I’m using stageWebView so I think it’s trying to navigate to my scheme first. Any ideas on how to avoid that message? thnx Seth

    Seth

    4 Aug 11 at 4:18 am

  4. In the Android settings, doesn’t an activity require an android:name attribute to be a valid manifest.xml file?

    Scott

    4 Aug 11 at 6:31 pm

  5. @Scott well could be but this works though ;)

    Piotr Walczyszyn

    5 Aug 11 at 5:07 pm

  6. Huh, when I copy and paste the entry you’ve provided into an *-app.xml of mine and try to install the apk (using either adb over USB or a local device install) I get a manifest parsing error (error manifest malformed). I don’t see any syntactic issues in what you’ve provided and my apk installs fine without the activity.

    I investigated by decoding the apk using android-apktool:

    http://code.google.com/p/android-apktool/

    and inspecting the manifest.xml file against the Android manifest documentation. The only issue I could find was that the documentation for the activity says:

    “There is no default. The name must be specified.”

    http://developer.android.com/guide/topics/manifest/activity-element.html#nm

    The activity generated by the AIR compiler for launching the application specifies:

    android:name=”.AppEntry”

    If I add this attribute to the activity tag the apk installs successfully. However, I’m not sure this is an appropriate solution. “.AppEntry” is an activity class generated by the AIR compiler for the MAIN activity and I’ve been unable to find any resource to support its use or suggest an alternative.

    Any thoughts?

    Scott

    5 Aug 11 at 8:41 pm

  7. After a bit brute force and ignorance I’ve found:

    1. If you use the android:name=”.AppEntry” attribute in the custom URL activity it works if the app isn’t loaded but not if the app is already loaded, which isn’t surprising since the .AppEntry class was designed to load from scratch.

    2. You can’t supply the name of a non-existent class and sneak by. My apk installs in that case but crashes any time I try to open a custom URL.

    3. I tried supplying the base class as the name, i.e. android.app.Activity, which also did not work.

    All of this makes me curious about the differences between our conditions that makes your apk work while mine does not. I’m trying to deploy to a DroidX running Android 2.3.3 using AIR 2.7 with an adt.bat version of 2.7.0.20000, packaged on a command line, not using an IDE.

    Scott

    5 Aug 11 at 9:13 pm

  8. Is there any way to invoke another app and pass a few arguments (native or air) from a air-based iphone application?

    Per your caveat above, it sounds like the custom url scheme can only be used from native apps to contact air apps and not the other way around, right?

    If so, is this going to be fixed by some other process in the future(ie. native extensions)?

    Brad

    23 Aug 11 at 9:29 pm

  9. Calling custom URIs will be possible from Air 3 according to an Adobe employee who responded to my post on their forum here: http://forums.adobe.com/thread/894668

    hope this helps someone else

    Brad

    24 Aug 11 at 11:46 pm

  10. anyone else seeing a bug with implementing this?

    using causes the application’s icon to disappear. the app is running in the system but there’s no icon in the application drawer…

    seth

    17 Sep 11 at 6:36 pm

  11. Nice post. It works partially for me – when I use parameters (e.g my-scheme://prm1=val1&prm2=val2) the app is indeed invoked but the parameters are not passed into event.arguments – that array is empty.

    Am I miscalling the URL params?

    Yuval

    18 Sep 11 at 1:21 pm

  12. Okay problem solved. Apparently you can’t use “my-schame://my-params…” but rather only “my-scheme:my-params…”

    Yuval

    18 Sep 11 at 1:49 pm

  13. I am using stageWebView for showing webpage in my mobile app but don’t know how to move back to my app once it gets loaded. In application descriptor file, I had already registered custom uri scheme (myapp://) for IOS devices and from the loaded page inside stageWebView, I was trying to call following URL myapp://webcam. But nothing had happened. It neither called LOCATION_CHANGE event of StageWebView not called INVOKE_EVENT of nativeapplication.

    How can I fix this issue?

    Thanks in advance,
    Mamta

    Mamta

    19 Sep 11 at 11:36 am

  14. @Mamta I think you misunderstood something, if you want to use custom url schemes you don’t need StageWebView.

    Piotr Walczyszyn

    20 Sep 11 at 3:07 pm

  15. Do you know if the same can be done for desktop apps?

    Nikita

    6 Oct 11 at 2:28 am

  16. Thank you a lot for sharing this with all folks you actually understand what you are speaking about! Bookmarked. Please additionally seek advice from my site =). We could have a hyperlink change agreement among us

    url shortener

    28 Oct 11 at 6:39 pm

  17. I added in *-app.xml what you said above and I am getting this error. I am testing on emulator.

    11-02 01:40:31.776: ERROR/Tab(317): onReceivedError -10 my-scheme: The protocol is not supported.

    Thanks

    Marin

    2 Nov 11 at 1:44 am

  18. Hi Piotr,

    Thnaks for your post. Just one thing missing, I think, for Android :

    You have to put this first intent filter, else the .apk doesn’t install from Flash Builder :

    Nils

    Nils

    26 Nov 11 at 2:07 pm

  19. intent-filter
    action android:name=”android.intent.action.MAIN”
    category android:name=”android.intent.category.LAUNCHER”
    intent-filter

    Nils

    26 Nov 11 at 2:08 pm

  20. This is great stuff dude!

    Dennis

    5 Dec 11 at 2:36 pm

  21. Yuval above says “Okay problem solved. Apparently you can’t use “my-schame://my-params…” but rather only “my-scheme:my-params…””

    The param part of this is not working for me on the iPad. Was this not implemented in AIR for IOS?

    As he indicates, app does indeed launch if invoked from browser via URL like “my-scheme:my-param” but onInvoke handler inside app is never called so the code to retrieve the arguments never executes. Pretty desperate to figure this out. If anyone knows anything please respond. Thanks

    Robert

    15 Feb 12 at 6:18 pm

Leave a Reply