Files
nearby_service/ios/Classes/NearbyManager.swift
T

190 lines
7.0 KiB
Swift

import Foundation
import Flutter
import MultipeerConnectivity
class NearbyManager: NSObject {
var device: NearbyDevice!
var advertiser: MCNearbyServiceAdvertiser!
var browser: MCNearbyServiceBrowser!
var invitationHandlers: [String: ((Bool, MCSession?) -> Void)] = [:]
func initialize(for deviceName: String? = nil, result: @escaping FlutterResult) {
self.device = MyDeviceDataGenerator.generate(name: deviceName)
self.advertiser = MCNearbyServiceAdvertiser(
peer: self.device.peerID,
discoveryInfo: self.device.toDictionary(),
serviceType: SERVICE_TYPE
)
self.advertiser.delegate = self
self.browser = MCNearbyServiceBrowser(peer: self.device.peerID, serviceType: SERVICE_TYPE)
self.browser.delegate = self
result(true)
}
func getSavedDeviceName(result: @escaping FlutterResult) {
result(Archiver.getName())
}
func getCurrentDevice(result: @escaping FlutterResult) {
result(device.toDartFormat())
}
func openServicesSettings(result: @escaping FlutterResult) {
if let url = URL(string:UIApplication.openSettingsURLString) {
if UIApplication.shared.canOpenURL(url) {
UIApplication.shared.open(url, options: [:], completionHandler: nil)
}
}
result(true)
}
func startAdvertising(result: @escaping FlutterResult) {
self.advertiser.startAdvertisingPeer()
result(true)
}
func startBrowsing(result: @escaping FlutterResult) {
self.browser.startBrowsingForPeers()
result(true)
}
func stopAdvertising(result: @escaping FlutterResult) {
self.advertiser.stopAdvertisingPeer()
NearbyDevicesStore.instance.clear()
result(true)
}
func stopBrowsing(result: @escaping FlutterResult) {
self.browser.stopBrowsingForPeers()
NearbyDevicesStore.instance.clear()
result(true)
}
func getPeers(result: @escaping FlutterResult) {
result(NearbyDevicesStore.instance.toDartFormat())
}
func invite(for deviceId: String, result: @escaping FlutterResult) {
do {
let device = NearbyDevicesStore.instance.find(for: deviceId)
if let requireDevice = device {
let nearbySession = requireDevice.createSession(for: self.device.peerID)
self.browser.invitePeer(
requireDevice.peerID,
to: nearbySession.session,
withContext: try JSONSerialization.data(withJSONObject:["displayName": self.device.name]),
timeout: 0
)
result(true)
}
} catch let error {
Logger.error(message: error.localizedDescription)
result(false)
}
}
func acceptInvite(for deviceId: String, result: @escaping FlutterResult) {
let device = NearbyDevicesStore.instance.find(for: deviceId)
if let requireDevice = device {
let nearbySession = requireDevice.createSession(for: self.device.peerID)
self.invitationHandlers[deviceId]?(true, nearbySession.session)
result(true)
}
}
func disconnect(for deviceId: String, result: @escaping FlutterResult) {
let device = NearbyDevicesStore.instance.find(for: deviceId)
device?.deleteSession()
result(true)
}
func send(for content: NearbyMessageContent, with receiverId: String, result: @escaping FlutterResult) {
let device = NearbyDevicesStore.instance.find(for: receiverId)
do {
if let requireDevice = device {
let message = NearbyMessage(content: content, senderName: self.device.name, senderPeerID: self.device.peerID)
if (content is NearbyMessageFilesRequest) {
NearbyRequestsStore.instance.add(request: message.content as! NearbyMessageFilesRequest)
}
try requireDevice.session?.session?.send(
try JSONSerialization.data(withJSONObject: message.toDictionary()),
toPeers: [requireDevice.peerID],
with: MCSessionSendDataMode.reliable
)
}
} catch let error {
Logger.error(message: error.localizedDescription)
}
result(true)
}
func sendFiles(id: String, paths: [String], with receiverId: String) {
do {
let device = NearbyDevicesStore.instance.find(for: receiverId)
if let requireDevice = device {
let command = NearbyStartCommand(
id: id,
senderName: self.device.name,
filesCount: paths.count
).toDictionary()
try requireDevice.session?.session?.send(
try JSONSerialization.data(withJSONObject: command),
toPeers: [requireDevice.peerID],
with: MCSessionSendDataMode.reliable
)
for path in paths {
let url = URL(fileURLWithPath: path)
if FileManager.default.fileExists(atPath: url.path) {
requireDevice.session?.session?.sendResource(
at: url,
withName: url.lastPathComponent,
toPeer: requireDevice.peerID
)
} else {
Logger.error(message: "File does not exist: " + path)
}
}
}
} catch let error {
Logger.error(message: error.localizedDescription)
}
}
}
extension NearbyManager: MCNearbyServiceAdvertiserDelegate {
func advertiser(_ advertiser: MCNearbyServiceAdvertiser, didReceiveInvitationFromPeer peerID: MCPeerID, withContext context: Data?, invitationHandler: @escaping (Bool, MCSession?) -> Void
) {
var dict: Dictionary<String, String>?
do {
dict = try JSONSerialization.jsonObject(with: context ?? Data()) as? Dictionary<String, String>
} catch let error {
Logger.error(message: error.localizedDescription)
}
_ = NearbyDevicesStore.instance.add(for: peerID, discoveryInfo: dict)
self.invitationHandlers[peerID.displayName] = invitationHandler
}
}
extension NearbyManager: MCNearbyServiceBrowserDelegate {
func browser(_ browser: MCNearbyServiceBrowser, foundPeer peerID: MCPeerID, withDiscoveryInfo info: [String : String]?) {
_ = NearbyDevicesStore.instance.add(for: peerID, discoveryInfo: info)
}
func browser(_ browser: MCNearbyServiceBrowser, lostPeer peerID: MCPeerID) {
let device = NearbyDevicesStore.instance.find(for: peerID.displayName)
device?.deleteSession()
NearbyDevicesStore.instance.remove(for: peerID)
}
}