Slide 1

Slide 1 text

App & Service Benjamin Ragheb CocoaHeads, New York City 9 May 2013

Slide 2

Slide 2 text

In cloud computing the people are served by two separate, yet equally important parts. The applications which interact with the users and the services which process their data. These are their stories.

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

Make Setup Easier • User snaps photo of blank log sheet • A sophisticated neural network (a.k.a. “Mike”) interprets photo • Send email to user when we’re done

Slide 5

Slide 5 text

Constraints • Will anybody use it? • I hate writing web services

Slide 6

Slide 6 text

To the Cloud! Amazon S3 (obviously)

Slide 7

Slide 7 text

No content

Slide 8

Slide 8 text

Amazon SNS • You create a topic • Use HTTP to publish something to the topic • Amazon forwards the something to the topic’s subscribers

Slide 9

Slide 9 text

Amazon SNS • Message is up to 64KB of whatever you like • Can forward to email, text message, HTTP, or SQS

Slide 10

Slide 10 text

Separation of Concerns • App doesn’t need to know where message is going • Amazon keeps track of subscriptions • Official Objective-C SDK available • I can procrastinate! • I hate writing web services

Slide 11

Slide 11 text

Workflow • Read instructions • Take photo • Answer questions • Submit to service • Photo to S3 • Metadata to SNS

Slide 12

Slide 12 text

Lingering Worry • AWS credentials baked into app • What if a malicious user extracts them? • New credentials requires App Store review • A token-vending machine is server-side code • I hate writing web services

Slide 13

Slide 13 text

Let’s work on the app • Let’s use a web view to present instructions • Why not load content from the network? • Feature requires network access anyway • Now we can revise any time • “Out of Order”

Slide 14

Slide 14 text

Buttons in HTML • Links that look like buttons • URL like “action:///takePhoto” • To disable feature, remove buttons

Slide 15

Slide 15 text

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { NSURL *URL = [request URL]; if ([[URL scheme] isEqualToString:@"action"]) { if ([[URL path] isEqualToString:@"/takePhoto"]) { [self takePhoto:nil]; return NO; } else if ([[URL path] isEqualToString:@"/choosePhoto"]) { [self choosePhoto:nil]; return NO; } } if (navigationType == UIWebViewNavigationTypeLinkClicked) { [[UIApplication sharedApplication] openURL:URL]; return NO; } return YES; }

Slide 16

Slide 16 text

Serendipity • If I can transmit information to the user… • …surely I can transmit to my code • Use Javascript to embed metadata

Slide 17

Slide 17 text

var access = { key: 'AKIAJV3BLV6Z3Y7FKURQ', secret: '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', bucket: 'logbook-capture', topic: 'arn:aws:sns:us-east-1:693923277227:logbooks-topic' } var jpegQuality = 0.5; var facilityTypes = ["", "Commercial", "Healthcare", "Hotel", "Industrial/Manufacturing", "Maritime", "Multifamily Residential", "Power Plant/Generation", "University/School", "Warehouse", "Other"];

Slide 18

Slide 18 text

• “document.body.id” to see if this is the page you want • “javascriptVariableName” to read a scalar value • “javascriptArrayName.join(‘\0’)” to read an array stringByEvaluatingJavaScriptFromString:

Slide 19

Slide 19 text

- (void)webViewDidFinishLoad:(UIWebView *)webView { NSString *bodyID = [webView stringByEvaluatingJavaScriptFromString:@"document.body.id"]; if ([bodyID isEqualToString:@"start"]) { SGLogbookCaptureSession *session = [[SGLogbookCaptureSession alloc] init]; session.amazonAccessKey = [webView stringByEvaluatingJavaScriptFromString:@"access.key session.amazonSecretKey = [webView stringByEvaluatingJavaScriptFromString:@"access.sec session.amazonBucketName = [webView stringByEvaluatingJavaScriptFromString:@"access.bu session.amazonTopicARN = [webView stringByEvaluatingJavaScriptFromString:@"access.topi session.logbookImageQuality = [[webView stringByEvaluatingJavaScriptFromString:@"jpegQ NSString *facilityTypes = [webView stringByEvaluatingJavaScriptFromString:@"facilityTy session.facilityTypes = [facilityTypes componentsSeparatedByString:@"\0"]; SGAccountController *accountController = [SGAccountController sharedController]; if (![accountController isGuest]) { session.emailAddress = accountController.emailAddress; } self.session = session; } }

Slide 20

Slide 20 text

Success • Lines of server code written: 0 • Token vending machine? Do it later! • Submission handler? Do it later! • I hate writing web services

Slide 21

Slide 21 text

Executive Producer Dick Wolf

Slide 22

Slide 22 text

Benjamin Ragheb Keep in touch! @benzado http://www.benzado.com [email protected]