Poking a Hole in the Sandbox: Using URLs on ios Greg Pierce @agiletortoise
Who am I? Greg Pierce President, Agile Tortoise @agiletortoise http:// Indie app development, web consulting
What do I do? Drafts Terminology Phraseology
What am I talking about? Custom URLs schemes as tool for inter-app communication on ios. - Limited options in the sandbox. - Consume URLs in other apps. - Provide services with URLs.
Inter-app whaaa? Integrating with other apps can make your app... - More useful. - Offers great opportunities for cross-promotion.
Overview Part 1 - What? - Local and Lightweight Part 2 - Why? - Use Cases Part 3 - How? - Implementation Part 4 - X-Callback-URL Q & A
Part 1 - What? Local and Lightweight
Anatomy of a URL - URL = Uniform Resource Locator scheme://domain:port/path? query_string#fragment_id - scheme or protocol is registered with OS. - Safari registers http - Phone.app registers tel - Mail.app registers mailto
Custom URLs - ios provides means to register Custom URL schemes for apps. - Registering says you know what to do with scheme: URLs. - Simple entries in app s Info.plist. - One app can register many custom URL schemes.
URLs - Lightweight Messaging between apps. - No OAuth, Web Services, complex setup. - Local - No network require for locally installed apps. - Few options!
Custom URL structure - Beyond the scheme and the colon, custom URL can look like anything. scheme:* - Not tied to HTTP (host:port/path) structure, but... - reuse tools/code that already exist to parse. - easier to document/consume. - Must follow escaping/encoding guidelines - Can support 80k characters at least.
Using URLs - URLs can be triggered like any links - Link embedded on a webpage - Programmatically two important methods: [[UIApplication sharedapplication] canopenurl:(nsurl *)url]; [[UIApplication sharedapplication] openurl:(nsurl *)url];
What happens? When a custom URL is opened... - Source app is backgrounded. - Target app is launched (or foregrounded) - Target AppDelegate is notified with a URL, using... - (BOOL)application:(UIApplication *)application openurl:(nsurl *)url sourceapplication:(nsstring *)sourceapplication annotation:(id)annotation
Part 2 - Why? Use cases
Testing if app is installed If you register a unique URL scheme, you give other apps a way to test if your app is installed. This includes your own apps...great for crosspromoting apps, without annoying people who have already downloaded.
Launching Without any additional work, registering a URL scheme gives apps a way to launch your app. See Launch Center Pro from App Cubby...
Launching with Context Have the user arrive at a specific place in your app... Facebook: fb://profile fb://events Tweetbot: tweetbot://post
Launching with Content Send some bit of string data to the target app. Drafts drafts://x-callback-url/create?text=%@ OmniFocus omnifocus:///add?name=%@
Executing an Action Dial a phone number tel:8175551234 Open this URL, Phone.app will launch and dial the number.
Two-Way Interaction - All these examples are one-way. Source App > Target App - What about 2-way? Source App > Target App > Source App - Callback URLs
Instapaper > Terminology > Instapaper terminology://x-callback-url/lookup? text=ceremony &x-source=instapaper &x-success=instapaper://
Instapaper > Terminology > Instapaper Terminology does the lookup Tap and Terminology will trigger the url in the x-success param x-source param provides friendly name for source
Two-Way with Data - Terminology Replace terminology://x-callback-url/replace? text=select &x-success=drafts://x-callback-url/replaceselection &x-source=drafts &x-cancel=drafts:// drafts://x-callback-url/replaceselection &replacewith=choose drafts://
Other Two-Way - izettle - Credit Card Transactions - Scanner Go - Bar Code Scanning - Authorization - Dropbox SDK, Facebook SDK
What not to do with URLs - Destructive actions myapp://deleteeverything - If destructive, require user confirmation. - Think about HTTP GET RESTful actions.
Part 3 - How? Implementation
URLScheme Demo App Example app on Github https://github.com/agiletortoise/urlschemes
Consuming URLs
Building URLs #import "Scratchpad.h" #import "NSString+URLEncoding.h" // Category for encoding @implementation Scratchpad - (void)examples { NSString *urlstring = @"test://action?param1=%@¶m2=%@"; NSString *p1 = @"Hello World"; NSString *p2 = @"You re Awesome"; NSString *fullurlstring = [NSString stringwithformat:urlstring, [p1 urlencodeusingencoding:nsutf8stringencoding], [p2 urlencodeusingencoding:nsutf8stringencoding]]; NSURL *url = [NSURL URLWithString:fullURLString]; } @end test://action? param1=hello%20world ¶m2=you%e2%80%99re%20awesome
Opening URLs if ([[UIApplication sharedapplication] canopenurl:url]) { [[UIApplication sharedapplication] openurl:url]; } - Use canopenurl to build UI, don t show things that can t be used. - canopenurl doesn t need full URLs, test with just scheme://
Providing URLs
Register scheme
Register in Info.plist
Valid URL Scheme Names - Sequence of characters beginning with a letter and followed by any combination of letters, digits, plus ("+"), period ("."), or hyphen ("-"). - NOT case sensitive.
Recommended URL Scheme Names - Your app name as it appears on the device, with hyphens in place of spaces. My App Name my-app-name://
Versioning If you provide actions that you need to version over time, register additional URLs x-app-api10:// x-app-api20:// Now you have a way to test for compatibility.
Reacting to URL On AppDelegate, define: - (BOOL)application:(UIApplication *)application openurl:(nsurl *)url sourceapplication:(nsstring *)sourceapplication annotation:(id)annotation; c - called after applicationwillenterforeground - called before applicationdidbecomeactive - return NO if you don t recognize the URL - (Nothing happens, just best practice)
ios 3 note... Prior to ios 4, you handled URLs in... - (BOOL)application:(UIApplication *)application handleopenurl:(nsurl *)url; If you need to support ios 3, implement this method and forward to your application: openurl: sourceapplication: annotation method.
Parsing Parameters myapp://actionname?test=param%20value&test2=paramvalue URLParser *parser = [[URLParser alloc] initwithurlstring:[url absolutestring]]; NSString *testparamvalue = [parser valueforvariable:@"test"]; // testparamvalue == @ param value
Parsing Parameters If you parse using some other method, USE THIS METHOD TO DECODE!!! [str stringbyreplacingpercentescapesusingencoding:nsutf8stringencoding]
DEMO (unreheased, apologies in advance)
Part 4 X-Callback-URL
X-Callback-URL - Specification to standardize URL formats - Drafts, Terminology, Instapaper, Agenda, Due, icab Mobile, Poster, Phraseology, Notesy. - Collaboration of myself, Marco Arment with input from a few others. http://x-callback-url.com
X-Callback-URL format scheme://x-callback-url/[action]?[x-callback parameters]&[action parameters] - [action] is specific to your app/implementation and should typically be a verb. - [action parameters] are also specific to your app and show be in a URL query string...i.e.: subject=the%20subject&body=the%20body
X-Callback-URL Parameters x-source: Friendly name of source app. x-success: Base URL to fire if successful x-error: Base URL to fire if error occurs x-cancel: Base URL to fire if user cancels
Finally... - Why use URL schemes? Why not? - Why format them with X-Callback-URL? Why not? - Document what you implement!!!!!! - Use affiliate links to promote apps you integrate with!!!!! - UTF8 escape and decode parameters! - Test with Unicode chars and cold starts.
Resources Find URL schemes: - http://handleopenurl.com - http://wiki.akosma.com/iphone_url_schemes Tutorial: - http://mobile.tutsplus.com/tutorials/iphone/ios-sdk-workingwith-url-schemes/ X-Callback-URL: - http://x-callback-url.com (sample apps/examples) URLSchemes Demo App: - https://github.com/agiletortoise/urlschemes
Q & A @agiletortoise Slides and Links: http:///blog