Android/iOS - Custom Uri/Protocol Handling

Android / iOS - Custom URI / Protocol Handling

Update: This is a very old question, and things have changed a lot on both iOS and Android. I'll leave the original answer below, but anyone working on a new project or updating an old one should instead consider using deep links, which are supported on both platforms.

On iOS, deep links are called universal links. You'll need to create a JSON file on your web site that associates your app with URLs that point to parts of your web site. Next, update your app to accept a NSUserActivity object and set up the app to display the content that corresponds to the given URL. You also need to add an entitlement to the app listing the URLs that the app can handle. In use, the operating system takes care of downloading the association file from your site and starting your app when someone tries to open one of the URLs your app handles.

Setting up app links on Android works similarly. First, you'll set up an association between your web site(s) and your app, and then you'll add intent filters that let your app intercept attempts to open the URLs that your app can handle.

Although the details are obviously different, the approach is pretty much the same on both platforms. It gives you the ability to insert your app into the display of your web site's content no matter what app tries to access that content.


Original answer:

For iOS, yes, you can do two things:

  1. Have your app advertise that it can handle URL's with a given scheme.

  2. Install a protocol handler to handle whatever scheme you like.

The first option is pretty straightforward, and described in Implementing Custom URL Schemes. To let the system know that your app can handle a given scheme:

  • update your app's Info.plist with a CFBundleURLTypes entry

  • implement -application:didFinishLaunchingWithOptions: in your app delegate.

The second possibility is to write your own protocol handler. This works only within your app, but you can use it in conjunction with the technique described above. Use the method above to get the system to launch your app for a given URL, and then use a custom URL protocol handler within your app to leverage the power of iOS's URL loading system:

  • Create a your own subclass of NSURLProtocol.

  • Override +canInitWithRequest: -- usually you'll just look at the URL scheme and accept it if it matches the scheme you want to handle, but you can look at other aspects of the request as well.

  • Register your subclass: [MyURLProtocol registerClass];

  • Override -startLoading and -stopLoading to start and stop loading the request, respectively.

Read the NSURLProtocol docs linked above for more information. The level of difficulty here depends largely on what you're trying to implement. It's common for iOS apps to implement a custom URL handler so that other apps can make simple requests. Implementing your own HTTP or FTP handler is a bit more involved.

For what it's worth, this is exactly how PhoneGap works on iOS. PhoneGap includes an NSURLProtocol subclass called PGURLProtocol that looks at the scheme of any URL the app tries to load and takes over if it's one of the schemes that it recognizes. PhoneGap's open-source cousin is Cordova -- you may find it helpful to take a look.

Android how to create Custom URL scheme with the given format myapp://http://

As CommonsWare said the given URI upon I needed to create a Scheme is not a valid URI thus the scheme didn't not work and the application didn't launch. After this explanation the server side guys were convinced to change the URI to myapp://... and it worked like magic :).

The Activity looks like this now :

 <activity
android:name="com.myapp.test.SplashScreen"
android:exported="true"
android:label="@string/app_name"
android:screenOrientation="portrait"
android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

<!-- Test for URL scheme -->
<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="myapp" />
</intent-filter>
<!-- End Test for URL scheme -->
</activity>

How to implement my very own URI scheme on Android

This is very possible; you define the URI scheme in your AndroidManifest.xml, using the <data> element. You setup an intent filter with the <data> element filled out, and you'll be able to create your own scheme. (More on intent filters and intent resolution here.)

Here's a short example:

<activity android:name=".MyUriActivity">
<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="myapp" android:host="path" />
</intent-filter>
</activity>

As per how implicit intents work, you need to define at least one action and one category as well; here I picked VIEW as the action (though it could be anything), and made sure to add the DEFAULT category (as this is required for all implicit intents). Also notice how I added the category BROWSABLE - this is not necessary, but it will allow your URIs to be openable from the browser (a nifty feature).

Is there a custom URL scheme for the built-in Contacts app?

If there were a public URL scheme, Apple would have documented it in the URL Scheme Reference.

Your options are:

  1. ABNewPersonViewController or ABUnknownPersonViewController
  2. Direct modification of the address book. (archived link)

How to fall back to marketplace when Android custom URL scheme not handled?

Below is a working code snippet for most of the android browsers:

<script type="text/javascript">
var custom = "myapp://custom_url";
var alt = "http://mywebsite.com/alternate/content";
var g_intent = "intent://scan/#Intent;scheme=zxing;package=com.google.zxing.client.android;end";
var timer;
var heartbeat;
var iframe_timer;

function clearTimers() {
clearTimeout(timer);
clearTimeout(heartbeat);
clearTimeout(iframe_timer);
}

function intervalHeartbeat() {
if (document.webkitHidden || document.hidden) {
clearTimers();
}
}

function tryIframeApproach() {
var iframe = document.createElement("iframe");
iframe.style.border = "none";
iframe.style.width = "1px";
iframe.style.height = "1px";
iframe.onload = function () {
document.location = alt;
};
iframe.src = custom;
document.body.appendChild(iframe);
}

function tryWebkitApproach() {
document.location = custom;
timer = setTimeout(function () {
document.location = alt;
}, 2500);
}

function useIntent() {
document.location = g_intent;
}

function launch_app_or_alt_url(el) {
heartbeat = setInterval(intervalHeartbeat, 200);
if (navigator.userAgent.match(/Chrome/)) {
useIntent();
} else if (navigator.userAgent.match(/Firefox/)) {
tryWebkitApproach();
iframe_timer = setTimeout(function () {
tryIframeApproach();
}, 1500);
} else {
tryIframeApproach();
}
}

$(".source_url").click(function (event) {
launch_app_or_alt_url($(this));
event.preventDefault();
});
</script>

You need to add source_url class to the anchor tag.

I have blogged more about it here:

http://aawaara.com/post/88310470252/smallest-piece-of-code-thats-going-to-change-the



Related Topics



Leave a reply



Submit