mirror of
				https://github.com/hackku21/nearby_connections.git
				synced 2025-06-13 12:53:50 +00:00 
			
		
		
		
	Copy swift code
This commit is contained in:
		
							parent
							
								
									8b29fdc01f
								
							
						
					
					
						commit
						aae94e8e9b
					
				
							
								
								
									
										56
									
								
								ios/Classes/Device.swift
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								ios/Classes/Device.swift
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,56 @@ | ||||
| import Foundation | ||||
| import MultipeerConnectivity | ||||
| import SwiftyJSON | ||||
| 
 | ||||
| class Device: NSObject { | ||||
|     let peerID: MCPeerID | ||||
|     var session: MCSession? | ||||
|     var state = MCSessionState.notConnected | ||||
|     var lastMessageReceived: Message? | ||||
| 
 | ||||
|     static let messageReceivedNotification = Notification.Name("DeviceDidReceiveMessage") | ||||
| 
 | ||||
|     init(peerID: MCPeerID) { | ||||
|         self.peerID = peerID | ||||
|         super.init() | ||||
|     } | ||||
| 
 | ||||
|     func createSession() { | ||||
|         if self.session != nil { return } | ||||
|         self.session = MCSession(peer: MPCManager.instance.localPeerID, securityIdentity: nil, encryptionPreference: .required) | ||||
|         self.session?.delegate = self | ||||
|     } | ||||
| 
 | ||||
|     func disconnect() { | ||||
|         self.session?.disconnect() | ||||
|         self.session = nil | ||||
|         NotificationCenter.default.post(name: MPCManager.Notifications.deviceDidChangeState, object: self) | ||||
|     } | ||||
| 
 | ||||
|     func invite(with browser: MCNearbyServiceBrowser) { | ||||
|         if (self.state == MCSessionState.notConnected) { | ||||
|             self.createSession() | ||||
|             if let session = session { | ||||
|                 browser.invitePeer(self.peerID, to: session, withContext: nil, timeout: 10) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| extension Device: MCSessionDelegate { | ||||
|     public func session(_ session: MCSession, peer peerID: MCPeerID, didChange state: MCSessionState) { | ||||
|         self.state = state | ||||
|         NotificationCenter.default.post(name: MPCManager.Notifications.deviceDidChangeState, object: nil) | ||||
|     } | ||||
| 
 | ||||
|     public func session(_ session: MCSession, didReceive data: Data, fromPeer peerID: MCPeerID) { | ||||
|         NotificationCenter.default.post(name: Device.messageReceivedNotification, object: nil, userInfo: ["from": peerID, "data": data]) | ||||
|     } | ||||
| 
 | ||||
|     public func session(_ session: MCSession, didReceive stream: InputStream, withName streamName: String, fromPeer peerID: MCPeerID) { } | ||||
| 
 | ||||
|     public func session(_ session: MCSession, didStartReceivingResourceWithName resourceName: String, fromPeer peerID: MCPeerID, with progress: Progress) { } | ||||
| 
 | ||||
|     public func session(_ session: MCSession, didFinishReceivingResourceWithName resourceName: String, fromPeer peerID: MCPeerID, at localURL: URL?, withError error: Error?) { } | ||||
| 
 | ||||
| } | ||||
							
								
								
									
										180
									
								
								ios/Classes/MPCManager.swift
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										180
									
								
								ios/Classes/MPCManager.swift
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,180 @@ | ||||
| // | ||||
| //  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 instance = MPCManager() | ||||
| 
 | ||||
|     var localPeerID: MCPeerID! | ||||
|     var enterbackgroundNotification: NSObjectProtocol! | ||||
|     private var backgroundTaskID: UIBackgroundTaskIdentifier = .invalid | ||||
|     var devices: [Device] = [] { | ||||
|         didSet { | ||||
|             deviceDidChange?() | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     var deviceDidChange: (() -> Void)? | ||||
| 
 | ||||
|     //    override init() { | ||||
|     //        if let data = UserDefaults.standard.data(forKey: "peerID"), let id = NSKeyedUnarchiver.unarchiveObject(with: data) as? MCPeerID { | ||||
|     //            self.localPeerID = id | ||||
|     //        } else { | ||||
|     //            let peerID = MCPeerID(displayName: UIDevice.current.name) | ||||
|     //            let data = NSKeyedArchiver.archivedData(withRootObject: peerID) | ||||
|     //            UserDefaults.standard.set(data, forKey: "peerID") | ||||
|     //            self.localPeerID = peerID | ||||
|     //        } | ||||
|     //        super.init() | ||||
|     //    } | ||||
| 
 | ||||
|     deinit{ | ||||
|         if let taskEnterBackground = enterbackgroundNotification { | ||||
|             NotificationCenter.default.removeObserver(taskEnterBackground) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     func setup(serviceType: String, deviceName: String) { | ||||
|         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 | ||||
|         } | ||||
| 
 | ||||
|         self.advertiser = MCNearbyServiceAdvertiser(peer: localPeerID, discoveryInfo: nil, serviceType: serviceType) | ||||
|         self.advertiser.delegate = self | ||||
| 
 | ||||
|         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() { | ||||
|         for device in self.devices { | ||||
|             device.disconnect() | ||||
|         } | ||||
|         self.browser.stopBrowsingForPeers() | ||||
|     } | ||||
| 
 | ||||
|     func invitePeer(deviceID: String) { | ||||
|         do { | ||||
|             let device = MPCManager.instance.findDevice(for: deviceID) | ||||
|             if(device?.state == MCSessionState.notConnected){ | ||||
|                 device?.invite(with: self.browser) | ||||
|             } | ||||
|         } catch let error { | ||||
|             print(error.localizedDescription) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     func disconnectPeer(deviceID: String){ | ||||
|         let device = MPCManager.instance.findDevice(for: deviceID) | ||||
|         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 deviceId: String) -> Device? { | ||||
|         for device in self.devices { | ||||
|             if device.peerID.displayName == deviceId { 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() | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
							
								
								
									
										80
									
								
								ios/Classes/Message.swift
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								ios/Classes/Message.swift
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,80 @@ | ||||
| // | ||||
| //  Message.swift | ||||
| //  multipeer_connections | ||||
| // | ||||
| //  Created by NamIT on 9/3/20. | ||||
| // | ||||
| 
 | ||||
| import Foundation | ||||
| import SwiftyJSON | ||||
| 
 | ||||
| struct Message: Codable { | ||||
|     let body: String | ||||
| } | ||||
| 
 | ||||
| extension Device { | ||||
|     func send(text: String) throws { | ||||
|         try self.session?.send(text.data(using: .utf8) ?? Data(), toPeers: [self.peerID], with: .reliable) | ||||
|     } | ||||
| 
 | ||||
|     func send(json: JSON) throws { | ||||
|         try self.session?.send(json.rawData(), toPeers: [self.peerID], with: .reliable) | ||||
|     } | ||||
| 
 | ||||
|     func send(data: Data) throws { | ||||
|         try self.session?.send(data, toPeers: [self.peerID], with: .reliable) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| struct ReceivedResponse { | ||||
|     var deviceID: String? | ||||
|     var message: MessageReponse | ||||
| 
 | ||||
|     init(json: JSON) { | ||||
|         deviceID = json["deviceID"].string | ||||
|         message = MessageReponse(json: json["message"]) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| struct MessageReponse { | ||||
|     var items: [MessageResponseItem] = [] | ||||
|     var subTotal: NSNumber? | ||||
|     var rounding: NSNumber? | ||||
|     var total: NSNumber? | ||||
| 
 | ||||
|     init(json: JSON) { | ||||
|         items = json["items"].array?.compactMap({return MessageResponseItem(json: $0)}) ?? [] | ||||
|         subTotal = json["subTotal"].number | ||||
|         rounding = json["rounding"].number | ||||
|         total = json["total"].number | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| struct MessageResponseItem { | ||||
|     var quantity: NSNumber? | ||||
|     var itemCollection: MessageItemCollection? | ||||
| 
 | ||||
|     init(json: JSON) { | ||||
|         quantity = json["quantity"].number | ||||
|         itemCollection = MessageItemCollection(json: json["itemCollection"]) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| struct MessageItemCollection { | ||||
|     var name: String? | ||||
|     var status: MessageItemCollectionStatus? | ||||
|     var imageUrl: String? | ||||
|     var price: NSNumber? | ||||
| 
 | ||||
|     init(json: JSON) { | ||||
|         name = json["name"].string | ||||
|         status = MessageItemCollectionStatus(rawValue: json["status"].stringValue) | ||||
|         imageUrl = json["imageUrl"].string | ||||
|         price = json["price"].number | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| enum MessageItemCollectionStatus: String { | ||||
|     case active = "ACTIVE" | ||||
| } | ||||
| 
 | ||||
| @ -1,14 +1,178 @@ | ||||
| import Flutter | ||||
| import UIKit | ||||
| import MultipeerConnectivity | ||||
| import SwiftyJSON | ||||
| 
 | ||||
| let SERVICE_TYPE = "nearby_connections" | ||||
| let INVOKE_CHANGE_STATE_METHOD = "invoke_change_state_method" | ||||
| let INVOKE_MESSAGE_RECEIVE_METHOD = "invoke_message_receive_method" | ||||
| 
 | ||||
| enum MethodCall: String { | ||||
|   case initNearbyService = "init_nearby_service" | ||||
|   case startAdvertisingPeer = "start_advertising_peer" | ||||
|   case startBrowsingForPeers = "start_browsing_for_peers" | ||||
| 
 | ||||
|   case stopAdvertisingPeer = "stop_advertising_peer" | ||||
|   case stopBrowsingForPeers = "stop_browsing_for_peers" | ||||
| 
 | ||||
|   case invitePeer = "invite_peer" | ||||
|   case disconnectPeer = "disconnect_peer" | ||||
| 
 | ||||
|   case sendMessage = "send_message" | ||||
| } | ||||
| 
 | ||||
| public class SwiftNearbyConnectionsPlugin: NSObject, FlutterPlugin { | ||||
|   public static func register(with registrar: FlutterPluginRegistrar) { | ||||
|     let channel = FlutterMethodChannel(name: "nearby_connections", binaryMessenger: registrar.messenger()) | ||||
|     let instance = SwiftNearbyConnectionsPlugin() | ||||
|     registrar.addMethodCallDelegate(instance, channel: channel) | ||||
|   let channel = FlutterMethodChannel(name: "nearby_connections", binaryMessenger: registrar.messenger()) | ||||
|   let instance = SwiftNearbyConnectionsPlugin() | ||||
|   registrar.addMethodCallDelegate(instance, channel: channel) | ||||
|   } | ||||
| 
 | ||||
|   var currentReceivedDevice: Device? | ||||
| 
 | ||||
|   let channel: FlutterMethodChannel | ||||
| 
 | ||||
|   struct DeviceJson { | ||||
|     var deviceId:String | ||||
|     var deviceName:String | ||||
|     var state:Int | ||||
| 
 | ||||
|     func toStringAnyObject() -> [String: Any] { | ||||
|       return [ | ||||
|         "deviceId": deviceId, | ||||
|         "deviceName": deviceName, | ||||
|         "state": state | ||||
|       ] | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   struct MessageJson { | ||||
|     var deviceId:String | ||||
|     var message:String | ||||
| 
 | ||||
|     func toStringAnyObject() -> [String: Any] { | ||||
|       return [ | ||||
|         "deviceId": deviceId, | ||||
|         "message": message | ||||
|       ] | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   @objc func stateChanged(){ | ||||
|     let devices = MPCManager.instance.devices.compactMap({return DeviceJson(deviceId: $0.peerID.displayName, deviceName: $0.peerID.displayName, state: $0.state.rawValue)}) | ||||
|     channel.invokeMethod(INVOKE_CHANGE_STATE_METHOD, arguments: JSON(devices.compactMap({return $0.toStringAnyObject()})).rawString()) | ||||
|   } | ||||
| 
 | ||||
|   @objc func messageReceived(notification: Notification) { | ||||
|     do { | ||||
|       if let data = notification.userInfo?["data"] as? Data, let stringData = JSON(data).rawString() { | ||||
|         let dict = convertToDictionary(text: stringData) | ||||
|         self.channel.invokeMethod(INVOKE_MESSAGE_RECEIVE_METHOD, arguments: dict) | ||||
|       } | ||||
|     } catch let e { | ||||
|       print(e.localizedDescription) | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   func convertToDictionary(text: String) -> [String: Any]? { | ||||
|     if let data = text.data(using: .utf8) { | ||||
|       do { | ||||
|         return try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] | ||||
|       } catch { | ||||
|         print(error.localizedDescription) | ||||
|       } | ||||
|     } | ||||
|     return nil | ||||
|   } | ||||
| 
 | ||||
|   public init(channel:FlutterMethodChannel) { | ||||
|     self.channel = channel | ||||
|     super.init() | ||||
| 
 | ||||
|     NotificationCenter.default.addObserver(self, selector: #selector(stateChanged), name: MPCManager.Notifications.deviceDidChangeState, object: nil) | ||||
| 
 | ||||
|     NotificationCenter.default.addObserver(self, selector: #selector(messageReceived), name: Device.messageReceivedNotification, object: nil) | ||||
| 
 | ||||
|     MPCManager.instance.deviceDidChange = {[weak self] in | ||||
|       self?.stateChanged() | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { | ||||
|     result("iOS " + UIDevice.current.systemVersion) | ||||
|     switch MethodCall(rawValue: call.method) { | ||||
|     case .initNearbyService: | ||||
|       guard let data = call.arguments as? Dictionary<String, AnyObject> else { | ||||
|         result(false) | ||||
|         return | ||||
|       } | ||||
|       let serviceType:String = data["serviceType"] as? String ?? SERVICE_TYPE | ||||
|       var deviceName:String = data["deviceName"] as? String ?? "" | ||||
|       if (deviceName.isEmpty){ | ||||
|         deviceName =  UIDevice.current.name | ||||
|       } | ||||
| 
 | ||||
|       MPCManager.instance.setup(serviceType: serviceType, deviceName: deviceName) | ||||
|       currentReceivedDevice = Device(peerID: MPCManager.instance.localPeerID) | ||||
|       result(true) | ||||
|     case .startAdvertisingPeer: | ||||
|       MPCManager.instance.startAdvertisingPeer() | ||||
|       result(true) | ||||
|     case .startBrowsingForPeers: | ||||
|       MPCManager.instance.startBrowsingForPeers() | ||||
|       result(true) | ||||
|     case .stopAdvertisingPeer: | ||||
|       MPCManager.instance.stopAdvertisingPeer() | ||||
|       result(true) | ||||
|     case .stopBrowsingForPeers: | ||||
|       MPCManager.instance.stopBrowsingForPeers() | ||||
|       result(true) | ||||
|     case .invitePeer: | ||||
|       guard let data = call.arguments as? Dictionary<String, AnyObject> else { | ||||
|         result(false) | ||||
|         return | ||||
| 
 | ||||
|       } | ||||
|       guard let deviceId: String = data["deviceId"] as? String else { | ||||
|         result(false) | ||||
|         return | ||||
|       } | ||||
|       MPCManager.instance.invitePeer(deviceID: deviceId) | ||||
|       result(true) | ||||
| 
 | ||||
|     case .disconnectPeer: | ||||
|       guard let data = call.arguments as? Dictionary<String, AnyObject> else { | ||||
|         result(false) | ||||
|         return | ||||
| 
 | ||||
|       } | ||||
|       let deviceId:String? = data["deviceId"] as? String ?? nil | ||||
|       if (deviceId != nil) { | ||||
|         MPCManager.instance.disconnectPeer(deviceID: deviceId!) | ||||
|         result(true) | ||||
|       } else { | ||||
|         result(false) | ||||
|       } | ||||
|     case .sendMessage: | ||||
|       guard let dict = call.arguments as? Dictionary<String, AnyObject> else { | ||||
|         result(false) | ||||
|         return | ||||
|       } | ||||
|       do { | ||||
|         let jsonData = try JSONSerialization.data(withJSONObject: dict, options: .prettyPrinted) | ||||
|         if let device = MPCManager.instance.findDevice(for: dict["deviceId"] as! String) { | ||||
|           currentReceivedDevice = device | ||||
|           try device.send(data: jsonData) | ||||
|           result(true) | ||||
|           return | ||||
|         } | ||||
|       } catch let error as NSError { | ||||
|         print(error) | ||||
|       } | ||||
|       result(false) | ||||
|     default: | ||||
|       result(FlutterMethodNotImplemented) | ||||
|       return | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
| } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user