Poking a Hole in the Sandbox: Using Urls on Ios
Total Page:16
File Type:pdf, Size:1020Kb
Poking a Hole in the Sandbox: Using URLs on iOS Greg Pierce @agiletortoise agiletortoise.com Tuesday, September 11, 12 Who am I? Greg Pierce President, Agile Tortoise @agiletortoise http://agiletortoise.com Indie app development, web consulting agiletortoise.com Tuesday, September 11, 12 What do I do? Drafts Terminology Phraseology agiletortoise.com Tuesday, September 11, 12 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. agiletortoise.com Tuesday, September 11, 12 Inter-app whaaa? Integrating with other apps can make your app... - More useful. - Offers great opportunities for cross-promotion. agiletortoise.com Tuesday, September 11, 12 Overview Part 1 - What? - Local and Lightweight Part 2 - Why? - Use Cases Part 3 - How? - Implementation Part 4 - X-Callback-URL Q & A agiletortoise.com Tuesday, September 11, 12 Part 1 - What? Local and Lightweight agiletortoise.com Tuesday, September 11, 12 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” agiletortoise.com Tuesday, September 11, 12 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. agiletortoise.com Tuesday, September 11, 12 URLs - Lightweight Messaging between apps. - No OAuth, Web Services, complex setup. - Local - No network require for locally installed apps. - Few options! agiletortoise.com Tuesday, September 11, 12 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. agiletortoise.com Tuesday, September 11, 12 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]; agiletortoise.com Tuesday, September 11, 12 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 agiletortoise.com Tuesday, September 11, 12 Part 2 - Why? Use cases agiletortoise.com Tuesday, September 11, 12 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 cross- promoting apps, without annoying people who have already downloaded. agiletortoise.com Tuesday, September 11, 12 Launching Without any additional work, registering a URL scheme gives apps a way to launch your app. See Launch Center Pro from App Cubby... agiletortoise.com Tuesday, September 11, 12 Launching with Context Have the user arrive at a specific place in your app... Facebook: fb://profile fb://events Tweetbot: tweetbot://post agiletortoise.com Tuesday, September 11, 12 Launching with Content Send some bit of string data to the target app. Drafts drafts://x-callback-url/create?text=%@ OmniFocus omnifocus:///add?name=%@ agiletortoise.com Tuesday, September 11, 12 Executing an Action Dial a phone number tel:8175551234 Open this URL, Phone.app will launch and dial the number. agiletortoise.com Tuesday, September 11, 12 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 agiletortoise.com Tuesday, September 11, 12 Instapaper > Terminology > Instapaper terminology://x-callback-url/lookup? text=ceremony &x-source=Instapaper &x-success=instapaper:// agiletortoise.com Tuesday, September 11, 12 Instapaper > Terminology > Instapaper Terminology does the “lookup” x-source param provides friendly name for source Tap and Terminology will trigger the url in the x-success param agiletortoise.com Tuesday, September 11, 12 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:// agiletortoise.com Tuesday, September 11, 12 Other Two-Way - iZettle - Credit Card Transactions - Scanner Go - Bar Code Scanning - Authorization - Dropbox SDK, Facebook SDK agiletortoise.com Tuesday, September 11, 12 What not to do with URLs - Destructive actions myapp://deleteEverything - If destructive, require user confirmation. - Think about HTTP GET RESTful actions. agiletortoise.com Tuesday, September 11, 12 Part 3 - How? Implementation agiletortoise.com Tuesday, September 11, 12 URLScheme Demo App Example app on Github https://github.com/agiletortoise/URLSchemes agiletortoise.com Tuesday, September 11, 12 Consuming URLs agiletortoise.com Tuesday, September 11, 12 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 agiletortoise.com Tuesday, September 11, 12 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://” agiletortoise.com Tuesday, September 11, 12 Providing URLs agiletortoise.com Tuesday, September 11, 12 Register scheme agiletortoise.com Tuesday, September 11, 12 Register in Info.plist agiletortoise.com Tuesday, September 11, 12 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. agiletortoise.com Tuesday, September 11, 12 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:// agiletortoise.com Tuesday, September 11, 12 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. agiletortoise.com Tuesday, September 11, 12 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) agiletortoise.com Tuesday, September 11, 12 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. agiletortoise.com Tuesday, September 11, 12 Parsing Parameters myapp://actionName?test=param%20value&test2=paramValue URLParser *parser = [[URLParser alloc] initWithURLString:[url absoluteString]]; NSString *testParamValue = [parser valueForVariable:@"test"]; // testParamValue == @”param value” agiletortoise.com Tuesday, September 11, 12 Parsing Parameters If you parse using some other method, USE THIS METHOD TO DECODE!!! [str stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding] agiletortoise.com Tuesday, September 11, 12 DEMO (unreheased, apologies in advance) agiletortoise.com Tuesday, September 11, 12 Part 4 X-Callback-URL agiletortoise.com Tuesday, September 11, 12 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 agiletortoise.com Tuesday, September 11, 12 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 agiletortoise.com Tuesday, September 11, 12 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 agiletortoise.com Tuesday, September 11, 12 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. agiletortoise.com Tuesday, September 11, 12 Resources Find URL schemes: - http://handleopenurl.com - http://wiki.akosma.com/IPhone_URL_Schemes Tutorial: - http://mobile.tutsplus.com/tutorials/iphone/ios-sdk-working- with-url-schemes/ X-Callback-URL: - http://x-callback-url.com (sample apps/examples) URLSchemes Demo App: - https://github.com/agiletortoise/URLSchemes agiletortoise.com Tuesday, September 11, 12 Q & A @agiletortoise Slides and Links: http://agiletortoise.com/blog agiletortoise.com Tuesday, September 11, 12.