2021-02-28 09:22:53 +00:00
|
|
|
//
|
|
|
|
// MPCManager.swift
|
|
|
|
// multipeer_connections
|
|
|
|
//
|
|
|
|
// Created by NamIT on 9/3/20.
|
|
|
|
//
|
|
|
|
|
|
|
|
import Foundation
|
|
|
|
import MultipeerConnectivity
|
|
|
|
|
|
|
|
class MPCManager: NSObject {
|
|
|
|
|
|
|
|
var advertiser: MCNearbyServiceAdvertiser!
|
|
|
|
var browser: MCNearbyServiceBrowser!
|
|
|
|
|
|
|
|
struct Notifications {
|
|
|
|
static let deviceDidChangeState = Notification.Name("deviceDidChangeState")
|
2021-02-28 11:56:55 +00:00
|
|
|
|
|
|
|
static let adOnConnectionInitiated = Notification.Name("adOnConnectionInitiated")
|
|
|
|
static let adOnConnectionResult = Notification.Name("adOnConnectionResult")
|
|
|
|
static let adOnDisconnected = Notification.Name("adOnDisconnected")
|
|
|
|
|
|
|
|
static let disOnConnectionInitiated = Notification.Name("disOnConnectionInitiated")
|
|
|
|
static let disOnConnectionResult = Notification.Name("disOnConnectionResult")
|
|
|
|
static let disOnDisconnected = Notification.Name("disOnDisconnected")
|
|
|
|
static let disOnEndpointFound = Notification.Name("disOnEndpointFound")
|
|
|
|
static let disOnEndpointLost = Notification.Name("disOnEndpointLost")
|
2021-02-28 09:22:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static let instance = MPCManager()
|
|
|
|
|
|
|
|
var localPeerID: MCPeerID!
|
|
|
|
var enterbackgroundNotification: NSObjectProtocol!
|
|
|
|
private var backgroundTaskID: UIBackgroundTaskIdentifier = .invalid
|
2021-02-28 16:02:51 +00:00
|
|
|
var devices: [Device] = []
|
2021-02-28 09:22:53 +00:00
|
|
|
|
|
|
|
var deviceDidChange: (() -> Void)?
|
|
|
|
|
|
|
|
deinit{
|
|
|
|
if let taskEnterBackground = enterbackgroundNotification {
|
|
|
|
NotificationCenter.default.removeObserver(taskEnterBackground)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-28 11:56:55 +00:00
|
|
|
func setup(serviceType: String, deviceName: String, isAdvert: Bool) {
|
2021-02-28 09:22:53 +00:00
|
|
|
if let data = UserDefaults.standard.data(forKey: deviceName), let id = NSKeyedUnarchiver.unarchiveObject(with: data) as? MCPeerID {
|
|
|
|
self.localPeerID = id
|
|
|
|
} else {
|
|
|
|
let peerID = MCPeerID(displayName: deviceName)
|
|
|
|
let data = NSKeyedArchiver.archivedData(withRootObject: peerID)
|
|
|
|
UserDefaults.standard.set(data, forKey: deviceName)
|
|
|
|
self.localPeerID = peerID
|
|
|
|
}
|
2021-02-28 11:56:55 +00:00
|
|
|
if(isAdvert){
|
|
|
|
self.advertiser = MCNearbyServiceAdvertiser(peer: localPeerID, discoveryInfo: nil, serviceType: serviceType)
|
|
|
|
self.advertiser.delegate = self
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
self.browser = MCNearbyServiceBrowser(peer: localPeerID, serviceType: serviceType)
|
|
|
|
self.browser.delegate = self
|
|
|
|
}
|
2021-02-28 09:22:53 +00:00
|
|
|
enterbackgroundNotification = NotificationCenter.default.addObserver(
|
|
|
|
forName: UIApplication.didEnterBackgroundNotification,
|
|
|
|
object: nil,
|
|
|
|
queue: nil,
|
|
|
|
using: {
|
|
|
|
[weak self](notification) in
|
|
|
|
self?.enteredBackground()
|
|
|
|
}
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
func startAdvertisingPeer() {
|
|
|
|
self.advertiser.startAdvertisingPeer()
|
|
|
|
}
|
|
|
|
|
|
|
|
func startBrowsingForPeers() {
|
|
|
|
self.browser.startBrowsingForPeers()
|
|
|
|
}
|
|
|
|
|
|
|
|
func stopAdvertisingPeer() {
|
|
|
|
self.advertiser.stopAdvertisingPeer()
|
|
|
|
}
|
|
|
|
|
|
|
|
func stopBrowsingForPeers() {
|
|
|
|
self.browser.stopBrowsingForPeers()
|
|
|
|
}
|
|
|
|
|
2021-02-28 16:02:51 +00:00
|
|
|
func invitePeer(endpointId: String) {
|
2021-02-28 09:22:53 +00:00
|
|
|
do {
|
2021-02-28 16:02:51 +00:00
|
|
|
let device = MPCManager.instance.findDevice(for: endpointId)
|
2021-02-28 09:22:53 +00:00
|
|
|
if(device?.state == MCSessionState.notConnected){
|
|
|
|
device?.invite(with: self.browser)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func disconnectPeer(deviceID: String){
|
|
|
|
let device = MPCManager.instance.findDevice(for: deviceID)
|
|
|
|
device?.disconnect()
|
|
|
|
}
|
|
|
|
|
2021-02-28 11:56:55 +00:00
|
|
|
func disconnectAllPeers(){
|
|
|
|
for device in self.devices {
|
|
|
|
device.disconnect()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-28 09:22:53 +00:00
|
|
|
func addNewDevice(for id: MCPeerID) -> Device {
|
2021-02-28 11:56:55 +00:00
|
|
|
// devices = devices.filter{$0.peerID.displayName != id.displayName}
|
2021-02-28 09:22:53 +00:00
|
|
|
let device = Device(peerID: id)
|
|
|
|
self.devices.append(device)
|
|
|
|
return device
|
|
|
|
}
|
|
|
|
|
2021-02-28 16:02:51 +00:00
|
|
|
func findDevice(for endpointId: String) -> Device? {
|
2021-02-28 09:22:53 +00:00
|
|
|
for device in self.devices {
|
2021-02-28 16:02:51 +00:00
|
|
|
if device.endpointId == endpointId { return device }
|
2021-02-28 09:22:53 +00:00
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func findDevice(for id: MCPeerID) -> Device? {
|
|
|
|
if let device = devices.first(where: {$0.peerID == id}) {
|
|
|
|
return device
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
@objc func enteredBackground() {
|
|
|
|
for device in self.devices {
|
|
|
|
device.disconnect()
|
|
|
|
}
|
|
|
|
DispatchQueue.global().async {[weak self] in
|
|
|
|
guard let `self` = self else {return}
|
|
|
|
// Request the task assertion and save the ID.
|
|
|
|
self.backgroundTaskID = UIApplication.shared.beginBackgroundTask (withName: "Finish Network Tasks") {
|
|
|
|
// End the task if time expires.
|
|
|
|
UIApplication.shared.endBackgroundTask(self.backgroundTaskID)
|
|
|
|
self.backgroundTaskID = .invalid
|
|
|
|
}
|
|
|
|
|
|
|
|
// Send the data synchronously.
|
|
|
|
self.devices = []
|
|
|
|
|
|
|
|
// End the task assertion.
|
|
|
|
UIApplication.shared.endBackgroundTask(self.backgroundTaskID)
|
|
|
|
self.backgroundTaskID = .invalid
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
extension MPCManager: MCNearbyServiceAdvertiserDelegate {
|
|
|
|
func advertiser(_ advertiser: MCNearbyServiceAdvertiser, didReceiveInvitationFromPeer peerID: MCPeerID, withContext context: Data?, invitationHandler: @escaping (Bool, MCSession?) -> Void) {
|
|
|
|
let device = self.addNewDevice(for: peerID)
|
|
|
|
device.createSession()
|
|
|
|
invitationHandler(true, device.session)
|
|
|
|
// Handle our incoming peer
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
extension MPCManager: MCNearbyServiceBrowserDelegate {
|
|
|
|
func browser(_ browser: MCNearbyServiceBrowser, foundPeer peerID: MCPeerID, withDiscoveryInfo info: [String : String]?) {
|
|
|
|
// found peer, create a device with this peerID
|
|
|
|
addNewDevice(for: peerID)
|
2021-02-28 16:02:51 +00:00
|
|
|
|
2021-02-28 09:22:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func browser(_ browser: MCNearbyServiceBrowser, lostPeer peerID: MCPeerID) {
|
|
|
|
// lost peer, disconnect and remove the device with this peerID
|
|
|
|
let device = self.findDevice(for: peerID)
|
|
|
|
devices = devices.filter{$0.peerID.displayName != peerID.displayName}
|
|
|
|
device?.disconnect()
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|