Synchronizing without internet - Multipeer Connectivity (iOS)

64
Synchronizing without internet Codemotion 2014, Madrid

description

Slides of my presentation in Codemotion 2014, Madrid talking about Multipeer connectivity and how to sync data between devices without need an internet connection or without to create an infraestructure network. See materials in https://github.com/patoroco/Codemotion-2014-Multipeer-Connectivity

Transcript of Synchronizing without internet - Multipeer Connectivity (iOS)

Page 1: Synchronizing without internet - Multipeer Connectivity (iOS)

Synchronizingwithout internetCodemotion 2014, Madrid

Page 2: Synchronizing without internet - Multipeer Connectivity (iOS)

Who am I?Jorge Maroto (@patoroco)

http://maroto.me

· iOS Developer @ticketeaeng

· Playing with iOS since 2010

· Fanboy

Page 3: Synchronizing without internet - Multipeer Connectivity (iOS)

Synchronize

Page 4: Synchronizing without internet - Multipeer Connectivity (iOS)
Page 5: Synchronizing without internet - Multipeer Connectivity (iOS)
Page 6: Synchronizing without internet - Multipeer Connectivity (iOS)
Page 7: Synchronizing without internet - Multipeer Connectivity (iOS)

¿Internet?

Page 8: Synchronizing without internet - Multipeer Connectivity (iOS)

LAN (wired / wi-fi)

Page 9: Synchronizing without internet - Multipeer Connectivity (iOS)

What about iOS?

Page 10: Synchronizing without internet - Multipeer Connectivity (iOS)

Changelog· iOS 3: Game Kit

· iOS 4: Game Center· iOS 5: Core Bluetooth

· iOS 6: Core Bluetooth advertising· iOS 7: Multipeer Connectivity &

iBeacons· iOS 8: Handoff

Page 11: Synchronizing without internet - Multipeer Connectivity (iOS)

Changelog· iOS 3: Game Kit

· iOS 4: Game Center· iOS 5: Core Bluetooth

· iOS 6: Core Bluetooth advertising· iOS 7: Multipeer Connectivity &

iBeacons· iOS 8: Handoff

Page 12: Synchronizing without internet - Multipeer Connectivity (iOS)

MultipeerConnectivity

Page 13: Synchronizing without internet - Multipeer Connectivity (iOS)

Multipeer connectivity· Appears in iOS7.

· Ability to connect to a mesh of peers.· Able to connect to peers over WiFi, ad-

hoc wireless, and Bluetooth.· Doesn't require server infraestructure.

· Peers must be 'nearby'.

Page 14: Synchronizing without internet - Multipeer Connectivity (iOS)
Page 15: Synchronizing without internet - Multipeer Connectivity (iOS)
Page 16: Synchronizing without internet - Multipeer Connectivity (iOS)

MultipeerConnectivity.frameworkBonjour | CFNetwork

Page 17: Synchronizing without internet - Multipeer Connectivity (iOS)

Two phases· Discovery· Session

Page 18: Synchronizing without internet - Multipeer Connectivity (iOS)

Classes#import <MultipeerConnectivity/MultipeerConnectivity.h>

Session infoDiscovery

Advertisement

Page 19: Synchronizing without internet - Multipeer Connectivity (iOS)

Session info· MCPeerId· MCSession

Page 20: Synchronizing without internet - Multipeer Connectivity (iOS)

MCPeerIdMCPeerID *peerId = [[MCPeerID alloc] initWithDisplayName:self.deviceName];

Page 21: Synchronizing without internet - Multipeer Connectivity (iOS)

MCSessionMCSession *session = [[MCSession alloc] initWithPeer:self.peerId];

session.delegate = self;

Page 22: Synchronizing without internet - Multipeer Connectivity (iOS)

<MCSessionDelegate>- (void)session:(MCSession *)session peer:(MCPeerID *)peerID didChangeState:(MCSessionState)state{ switch (state): { case MCSessionStateConnected: ... case MCSessionStateConnecting: ... case MCSessionStateNotConnected: ... }}

Page 23: Synchronizing without internet - Multipeer Connectivity (iOS)

<MCSessionDelegate>// DATA- (void)session:(MCSession *)session didReceiveData:(NSData *)data fromPeer:(MCPeerID *)peerID {}

// RESOURCES- (void)session:(MCSession *)session didStartReceivingResourceWithName:(NSString *)resourceName fromPeer:(MCPeerID *)peerID withProgress:(NSProgress *)progress {}- (void)session:(MCSession *)session didFinishReceivingResourceWithName:(NSString *)resourceName fromPeer:(MCPeerID *)peerID atURL:(NSURL *)localURL withError:(NSError *)error{}

// STREAMS- (void)session:(MCSession *)session didReceiveStream:(NSInputStream *)stream withName:(NSString *)streamName fromPeer:(MCPeerID *)peerID{}

Page 24: Synchronizing without internet - Multipeer Connectivity (iOS)

Discovery· MCBrowserViewController· MCNearbyServiceBrowser

Page 25: Synchronizing without internet - Multipeer Connectivity (iOS)

MCBrowserViewControllerNSString * const serviceIdentifier = @"codemotion-demo";

MCBrowserViewController *browser = [[MCBrowserViewController alloc] initWithServiceType:serviceIdentifier session:self.appdelegate.session];

browser.delegate = self;

[self presentViewController:browser animated:YES completion:nil];

Page 26: Synchronizing without internet - Multipeer Connectivity (iOS)
Page 27: Synchronizing without internet - Multipeer Connectivity (iOS)

<MCBrowserViewControllerDelegate>- (void)browserViewControllerDidFinish:(MCBrowserViewController *)b {}

- (void)browserViewControllerWasCancelled:(MCBrowserViewController *)b {}

Page 28: Synchronizing without internet - Multipeer Connectivity (iOS)

Advertisement· MCAdvertiserAssistant

· MCNearbyServicesAdvertiser

Page 29: Synchronizing without internet - Multipeer Connectivity (iOS)

MCAdvertiserAssistantNSString * const serviceIdentifier = @"codemotion-demo";

MCAdvertiserAssistant *advertiser = [[MCAdvertiserAssistant alloc] initWithServiceType:self.serviceIdentifier discoveryInfo:nil session:session];

[advertiser start];

Page 30: Synchronizing without internet - Multipeer Connectivity (iOS)

Session phase

Page 31: Synchronizing without internet - Multipeer Connectivity (iOS)

Sending data· NSData to an array of peers.

· NSURL resource to a peer.· NSStream to a peer.

Page 32: Synchronizing without internet - Multipeer Connectivity (iOS)

Send NSData to an array of peers- (BOOL)sendData:(NSData *)data toPeers:(NSArray *)peerIDs withMode:(MCSessionSendDataMode)mode error:(NSError **)error;

Modes· MCSessionSendDataReliable· MCSessionSendDataUnreliable

Page 33: Synchronizing without internet - Multipeer Connectivity (iOS)

DEMOHello world in MC

Page 34: Synchronizing without internet - Multipeer Connectivity (iOS)

Video

Page 35: Synchronizing without internet - Multipeer Connectivity (iOS)
Page 36: Synchronizing without internet - Multipeer Connectivity (iOS)

Send resource to a peer

- (NSProgress *)sendResourceAtURL:(NSURL *)resourceURL withName:(NSString *)resourceName toPeer:(MCPeerID *)peerID withCompletionHandler:(void(^)(NSError *error))completionHandler;

Page 37: Synchronizing without internet - Multipeer Connectivity (iOS)

ExampleShare images from photo

library

Page 38: Synchronizing without internet - Multipeer Connectivity (iOS)

@property (weak, nonatomic) IBOutlet UIImageView *picture;

Page 39: Synchronizing without internet - Multipeer Connectivity (iOS)

- (IBAction)choosePhoto:(UIButton *)sender{ UIImagePickerController *picker = [[UIImagePickerController alloc] init]; picker.delegate = self; picker.allowsEditing = NO; picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary; picker.mediaTypes = @[(NSString *)kUTTypeImage];

[self presentViewController:picker animated:YES completion:nil];}

Page 40: Synchronizing without internet - Multipeer Connectivity (iOS)

<UIImagePickerDelegate>#pragma mark - UIImagePickerDelegate

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{ UIImage *selectedImage = info[UIImagePickerControllerOriginalImage]; NSData *jpegImg = UIImageJPEGRepresentation(selectedImage, 0.5);

NSString *tmpPath = [NSTemporaryDirectory() stringByAppendingString:@"pic.jpg"]; self.imageURL = [NSURL fileURLWithPath:tmpPath];

[jpegImg writeToURL:self.imageURL atomically:NO];

self.picture.image = selectedImage; [picker dismissViewControllerAnimated:YES completion:nil];}

- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker { [picker dismissViewControllerAnimated:YES completion:NULL];}

Page 41: Synchronizing without internet - Multipeer Connectivity (iOS)

<MCSessionDelegate>#pragma mark - - (void)session:(MCSession *)session didStartReceivingResourceWithName:(NSString *)resourceName fromPeer:(MCPeerID *)peerID withProgress:(NSProgress *)progress{ dispatch_async(dispatch_get_main_queue(), ^{ self.picture.image = nil; self.picture.backgroundColor = [UIColor yellowColor]; });}

- (void)session:(MCSession *)session didFinishReceivingResourceWithName:(NSString *)resourceName fromPeer:(MCPeerID *)peerID atURL:(NSURL *)localURL withError:(NSError *)error{ NSData *data = [NSData dataWithContentsOfURL:localURL]; UIImage *image = [[UIImage alloc] initWithData:data];

dispatch_async(dispatch_get_main_queue(), ^{ self.picture.image = image; });}

Page 42: Synchronizing without internet - Multipeer Connectivity (iOS)

VideoShare images from photo

library

Page 43: Synchronizing without internet - Multipeer Connectivity (iOS)
Page 44: Synchronizing without internet - Multipeer Connectivity (iOS)

Streaming- (NSOutputStream *)startStreamWithName:(NSString *)streamName toPeer:(MCPeerID *)peerID error:(NSError **)error;

Page 45: Synchronizing without internet - Multipeer Connectivity (iOS)

NSOutputStream: open

- (void)session:(MCSession *)session peer:(MCPeerID *)peerID didChangeState:(MCSessionState)state{ ... if (state == MCSessionStateConnected) { NSError *error; NSOutputStream *output = [session startStreamWithName:@"streamName" toPeer:peer error:&error];

if (error) { return; }

[output scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; [output open]; } ...}

Page 46: Synchronizing without internet - Multipeer Connectivity (iOS)

NSOutputStream: write

NSData *data = [NSData data]; [self.output write:data.bytes maxLength:data.length];

Page 47: Synchronizing without internet - Multipeer Connectivity (iOS)

NSInputStream- (void)session:(MCSession *)session didReceiveStream:(NSInputStream *)stream withName:(NSString *)streamName fromPeer:(MCPeerID *)peerID{ stream.delegate = self; [stream scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; [stream open];}

Page 48: Synchronizing without internet - Multipeer Connectivity (iOS)

<NSStreamDelegate>- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode{ switch (eventCode) { case NSStreamEventOpenCompleted: ... case NSStreamEventEndEncountered: ... case NSStreamEventHasBytesAvailable: { NSInputStream *inputStream = (NSInputStream *)aStream;

uint8_t buffer[1024]; NSInteger size = [inputStream read:(uint8_t *)buffer maxLength:1024];

NSData *data = [NSData dataWithBytes:buffer length:size]; ... // Manage data received ... break; } default: break; }}

Page 49: Synchronizing without internet - Multipeer Connectivity (iOS)

ExampleShared whiteboard

Page 50: Synchronizing without internet - Multipeer Connectivity (iOS)
Page 51: Synchronizing without internet - Multipeer Connectivity (iOS)

UIPanGestureRecognizer- (IBAction)panReceived:(UIPanGestureRecognizer *)sender{ CGPoint point = [sender locationInView:sender.view];

[self.drawable drawPoint:point state:sender.state];

NSData *data = [NSData drawDataWithGestureState:sender.state point:[sender locationInView:sender.view]]; [self.output write:data.bytes maxLength:data.length];}

Page 52: Synchronizing without internet - Multipeer Connectivity (iOS)

- (void)drawPoint:(CGPoint)point state:(UIGestureRecognizerState)state{ switch (state) { case UIGestureRecognizerStateBegan: { lastPoint = point; break; } case UIGestureRecognizerStateChanged: { CGPoint currentPoint = point;

UIGraphicsBeginImageContext(self.layout.frame.size); [self.tmpLayout.image drawInRect:CGRectMake(0, 0, self.layout.frame.size.width, self.layout.frame.size.height)]; CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y); CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint.x, currentPoint.y); CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound); CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 10); CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 0, 0, 0, 1.0); CGContextSetBlendMode(UIGraphicsGetCurrentContext(),kCGBlendModeNormal);

CGContextStrokePath(UIGraphicsGetCurrentContext()); self.tmpLayout.image = UIGraphicsGetImageFromCurrentImageContext(); [self.tmpLayout setAlpha:1]; UIGraphicsEndImageContext();

lastPoint = currentPoint; break; } case UIGestureRecognizerStateEnded: { UIGraphicsBeginImageContext(self.layout.frame.size); [self.layout.image drawInRect:CGRectMake(0, 0, self.layout.frame.size.width, self.layout.frame.size.height) blendMode:kCGBlendModeNormal alpha:1.0]; [self.tmpLayout.image drawInRect:CGRectMake(0, 0, self.layout.frame.size.width, self.layout.frame.size.height) blendMode:kCGBlendModeNormal alpha:1.0]; self.layout.image = UIGraphicsGetImageFromCurrentImageContext(); self.tmpLayout.image = nil; UIGraphicsEndImageContext(); break; }

default: break; }}

Page 53: Synchronizing without internet - Multipeer Connectivity (iOS)

- (void)clearScreen{ UIGraphicsBeginImageContext(self.layout.frame.size); CGContextRef ctx = UIGraphicsGetCurrentContext();

CGContextSetRGBFillColor(ctx, 255.0, 255.0, 255.0, 1.0); CGContextFillRect(ctx, CGRectMake(0, 0, self.tmpLayout.frame.size.width, self.tmpLayout.frame.size.height)); self.layout.image = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext();}

Page 54: Synchronizing without internet - Multipeer Connectivity (iOS)

VideoShared whiteboard

Page 55: Synchronizing without internet - Multipeer Connectivity (iOS)
Page 56: Synchronizing without internet - Multipeer Connectivity (iOS)

All together

Page 57: Synchronizing without internet - Multipeer Connectivity (iOS)

'simple sync' example· n-devices.

· Create a hash by each register based in time.

· First sync in batch using a file.· NSOutputstream to send 'ligth data'.

· Off and on send counters & timers using MCSessionSendDataReliable.

Page 58: Synchronizing without internet - Multipeer Connectivity (iOS)

'simple sync' example· n-devices.

· Create a hash by each register based in time.

· First sync in batch using a file.· NSOutputstream to send 'ligth data'.

· Off and on send counters & timers using MCSessionSendDataReliable.

Page 59: Synchronizing without internet - Multipeer Connectivity (iOS)
Page 60: Synchronizing without internet - Multipeer Connectivity (iOS)

Ensembles1

"Sync for Core Data Apps"1 http://www.ensembles.io

Page 61: Synchronizing without internet - Multipeer Connectivity (iOS)

How far can I ...

Page 62: Synchronizing without internet - Multipeer Connectivity (iOS)

How far can I ...

- RADIOUS2.

- DevRocket3

...

3 DeckRocket: https://github.com/jpsim/DeckRocket.

2 RADIOUS: https://itunes.apple.com/nz/app/radious-walkie-talkie/id738480541?mt=8.

Page 63: Synchronizing without internet - Multipeer Connectivity (iOS)

Questions?

Page 64: Synchronizing without internet - Multipeer Connectivity (iOS)

Thanks@patoroco