Blog

The latest goings on at Kotikan.

Passing data between iOS apps

30/03/11 by Marius Ciocanel

Apps on the iPhone all run in a sandbox. Great for security but not so great for developers. We recently had the requirement to communicate between two of our applications and so set out to find an elegant solution. The best way to manage communication between apps appears to be through registered URL handlers, here is an outline of how to set that up.

The process

Assuming you have two apps (appA and appB) and appA wishes to get data from appB the process works as follows:

  1. Register a protocol handler for each app with the device
    AppA registers the appA:// protocol handler with the iOS device
    AppB registers the appB:// protocol handler with the iOS device
  2. AppA requests information from appB.
    AppA opens a URL that starts with appB:// that closes appA and opens appB e.g appB://localhost/exportData
  3. AppB handles the request and sends the data to appA.
    AppB constructs the data that appA asked for, it creates a JSON string and encodes the string using base64.
    AppB sends the data by asking appA to open a URL that starts with appA:// and that contains the base64 encoded JSON string.

    e.g appA://localhost/exportedData/data?SlNPTiBTdHJpbmcgZW5jb2RlZCB3aXRoIGJhc2U2NA==
  4. AppA receives the data and uses it for its own purposes.

 

Setting up the project

iPhone applications store runtime configuration information, including the URL schemes the application handles, in the Info.plist file. Add a CFBundleURLTypes element to the application’s Info.plist to register it as a URL handler for a particular protocol. Xcode makes this easy:

  1. Open the Info.plist file (typically found under the "Resources Folder") in Xcode.
  2. Select the top-level "Information Property List" element and add a new child-key to by clicking the "insert line" button.
  3. Scroll to the bottom of the drop-down list and select "URL types."
  4. Enter a unique identifier (e.g., com.mydomain.myprotocol) for the value of the "URL identifier" key.
  5. With "URL identifier" still selected, click the "+" button and select "URL Schemes" from the resulting list
  6. Enter the protocol name — e.g. myprotocol — as the value for the "Item 1″ key.

 

That’s all there is to registering a protocol handler. The iPhone will automatically wire up the association when the app in installed.
Please note that the URL identifier and URL scheme must be unique for your application.

Handling An Open URL Request

To ensure that the URL is handled in the same way in iOS < 4.2 and in iOS 4.2 the way to do it is by implementing the

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions method.

(applicationDidFinishLaunching: should NOT be used as it is deprecated).

The launchOptions dictionary contains data indicating the reason the application was launched. This is useful because we can check to see if another application opened a URL that was owned by our application. To get the URL we get the value for the UIApplicationLaunchOptionsURLKey key.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 
	NSURL *urlToParse = [launchOptions objectForKey:UIApplicationLaunchOptionsURLKey];
    	if (urlToParse) {
        	[self application:application handleOpenURL:urlToParse];
    	} 
    	return YES;
}

The method above is being called when the app is being launched and it's not already running.

If the app is already running in the background(e.g in iOS 4 or more) then only handleOpenURL: is called when the app is opened via a URL.

To make things simple that is why we call the application:handleOpenURL in the method above.

We'll need to implement the method that actually deals with the URL that was passed on to our application :

- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
	if ([[url scheme] isEqualToString:@"appB"] && [[url path] isEqualToString:@"/exportData"]) {
		//in here you do whatever you need the app to do
		// e.g decode JSON string from base64 to plain text & parse JSON string
	}
 return YES; //if everything went well
}

Opening a URL From An Application

The UIApplication class’ openURL method handles opening URLs from an application. Use the [UIApplication sharedApplication] singleton to access the UIApplication.

NSURL *url = [NSURL URLWithString:@"myprotocol://localhost/exportData"];
[[UIApplication sharedApplication] openURL:url];

If you want to support a "round trip" from one application to another and then back to the originating application then you'll have to ask appA to open a URL that is registered by appB and appB then opens a URL registered to appA.

AppA calls this URL to open appB:

NSURL *url = [NSURL URLWithString:@"appB://localhost/exportData"];
[[UIApplication sharedApplication] openURL:url];

AppB calls this URL to open appA:

NSURL *url = [NSURL URLWithString: @"appA://localhost/exportedData/data?SlNPTiBTdHJpbmcgZW5jb2RlZCB3aXRoIGJhc2U2NA=="];
[[UIApplication sharedApplication] openURL:url];

Summary

That's all you need to get data to and from other applications you have written. The added benefit is that 3rd party applications could publish their URL scheme and allow other apps to integrate with them.

blog comments powered by Disqus