You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
nearby_connections/ios/Classes/MPCManager.swift

178 lines
5.9 KiB

//
// 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")
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")
}
static let instance = MPCManager()
var localPeerID: MCPeerID!
var enterbackgroundNotification: NSObjectProtocol!
private var backgroundTaskID: UIBackgroundTaskIdentifier = .invalid
var devices: [Device] = []
var deviceDidChange: (() -> Void)?
deinit{
if let taskEnterBackground = enterbackgroundNotification {
NotificationCenter.default.removeObserver(taskEnterBackground)
}
}
func setup(serviceType: String, deviceName: String, isAdvert: Bool) {
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
}
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
}
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()
}
func invitePeer(endpointId: String) {
do {
let device = MPCManager.instance.findDevice(for: endpointId)
if(device?.state == MCSessionState.notConnected){
device?.invite(with: self.browser)
}
}
}
func disconnectPeer(deviceID: String){
let device = MPCManager.instance.findDevice(for: deviceID)
device?.disconnect()
}
func disconnectAllPeers(){
for device in self.devices {
device.disconnect()
}
}
func addNewDevice(for id: MCPeerID) -> Device {
// devices = devices.filter{$0.peerID.displayName != id.displayName}
let device = Device(peerID: id)
self.devices.append(device)
return device
}
func findDevice(for endpointId: String) -> Device? {
for device in self.devices {
if device.endpointId == endpointId { return device }
}
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)
}
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()
}
}