Another Flatiron student and I were interested in the Multipeer Connectivity Framework in iOS, so we made a chat app called Lattice that uses multipeer in the event of a natural disaster as a demonstration of the technology.
I’m going to talk about how the basics of multipeer connectivity work.
The Multipeer Connectivity (MC) Framework
What does it do?
Multipeer allows devices to connect with others nearby without the internet.
How does it work?
Multipeer Connectivity is an implementation of mesh networking, creating a local network between devices within Wifi or Bluetooth range. Not only are new devices connected with devices within range but also with all devices that those devices are connected to, even if the destination device is not within range of the sender.
That’s the real power of mesh networks. If permitted, devices can send messages relayed through other devices.
How might this be useful?
- Mesh networks allow communication when internet infrastructure is damaged (such as natural disasters).
- Mesh networks allow communication when internet access is restricted by governments, seen in the protests of Hong Kong.
- Mesh networks allow communication in internet-less situation (camping trips, road trips, subway commutes, and foreign vacations).
Lattice – Demo Project
Before we dive into the nitty gritty, I’ve placed Lattice on Github, so you can see exactly how the snippets below are used.
Setting up the MCManager
We have a MCManager class, similar to an API manager or data store for Core Data. Four properties need to be set up.
_peerID = [[MCPeerID alloc] initWithDisplayName:displayName];
This is the name of your device.
_session = [[MCSession alloc] initWithPeer:self.peerID securityIdentity:nil encryptionPreference:MCEncryptionNone];
_session.delegate = self;
This is the session that your device will start. Think of a session like a chatroom.
_advertiser = [[MCNearbyServiceAdvertiser alloc] initWithPeer:self.peerID discoveryInfo:elements serviceType:LatticeServiceType];
self.advertiser.delegate = self;
This adverser tells nearby browsers that it is looking to connect with a particular serviceType. DiscoveryInfo is a dictionary that the browser will receive when it finds this advertiser.
_browser = [[MCNearbyServiceBrowser alloc] initWithPeer:self.peerID serviceType:LatticeServiceType];
self.browser.delegate = self;
This browser looks for advertisers of a particular service type to connect to.
Connecting to Other Devices
Lattice, the demo app, will have an advertiser and browser running at the same time on each device.
Browser Finds Peer, Invites Peer
- (void)browser:(MCNearbyServiceBrowser *)browser foundPeer:(MCPeerID *)peerID withDiscoveryInfo:(NSDictionary *)info
[self.browser invitePeer:peerID toSession:self.session withContext:nil timeout:10]
When a browser finds an advertiser, it can parse the discoveryInfo that the advertiser set when it was created. In this case, we want the devices to connect automatically, so the browser sends an invitation to connect to the browser’s session.
Advertiser Accepts Invitation
- (void)advertiser:(MCNearbyServiceAdvertiser *)advertiser didReceiveInvitationFromPeer:(MCPeerID *)peerID withContext:(NSData *)context invitationHandler:(void (^)(BOOL, MCSession *))invitationHandler
Since we want the advertiser to connect automatically, the advertiser will reply YES to the invitation.
Session Confirms Connection
- (void)session:(MCSession *)session peer:(MCPeerID *)peerID didChangeState:(MCSessionState)state
We can indeed confirm that the two devices are connected with this delegate method from the session. The session will tells us that the peer is now in the connected state.
Sending and Receiving Messages
Sending From the View Controller
[self.multipeerManager.session sendData:messageData toPeers:self.multipeerManager.session.connectedPeers withMode:MCSessionSendDataUnreliable error:&error];
Messages are sent from the session to the peers in the session.
Receiving In the MCManager
- (void)session:(MCSession *)session didReceiveData:(NSData *)data fromPeer:(MCPeerID *)peerID
//Kicks off a notification to the View Controller
Messages are received by the session on the other devices. In Lattice, we triggered a notification with each message received.
Catching the Notification In the View Controller
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(peerDidReceiveDataWithNotification:) name:@"MCDidReceiveDataNotification" object:nil];
- (void)peerDidReceiveDataWithNotification:(NSNotification *)notification
NSData *messageData = notification.userInfo[@"data"];
NSArray *messages = [NSKeyedUnarchiver unarchiveObjectWithData:messageData];
The notification was handled by the view controller to display the new message.
Multipeer Connectivity is a iOS framework.
Range can be limited on Bluetooth
We found it to be about 60 – 100 feet.
Downloading the app requires the internet?!
There should be a way for the app to spread virally with no internet.
Limited usefulness in zombie apocalypse
This would be great for finding survivors nearby without having to go room by room through scary dark buildings. During night when the zombies are outside, the bluetooth signal may not be long enough to communicate between buildings.
Peter Fennema for showing how to connect via multipeer automatically
Jesse Squires for the messaging user interface: JSQMessagesViewController