diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj index 4997bc1..87c1dbc 100644 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 46; + objectVersion = 50; objects = { /* Begin PBXBuildFile section */ @@ -76,7 +76,6 @@ EE2828077045705EB4BA404D /* Pods-Runner.release.xcconfig */, C9F844878FCCBEAFD77B42DD /* Pods-Runner.profile.xcconfig */, ); - name = Pods; path = Pods; sourceTree = ""; }; @@ -253,27 +252,12 @@ buildActionMask = 2147483647; files = ( ); - inputPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh", - "${PODS_ROOT}/../Flutter/Flutter.framework", - "${BUILT_PRODUCTS_DIR}/SAMKeychain/SAMKeychain.framework", - "${BUILT_PRODUCTS_DIR}/SwiftyJSON/SwiftyJSON.framework", - "${BUILT_PRODUCTS_DIR}/Toast/Toast.framework", - "${BUILT_PRODUCTS_DIR}/device_info/device_info.framework", - "${BUILT_PRODUCTS_DIR}/flutter_nearby_connections/flutter_nearby_connections.framework", - "${BUILT_PRODUCTS_DIR}/flutter_udid/flutter_udid.framework", - "${BUILT_PRODUCTS_DIR}/fluttertoast/fluttertoast.framework", + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", ); name = "[CP] Embed Pods Frameworks"; - outputPaths = ( - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SAMKeychain.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SwiftyJSON.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Toast.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/device_info.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_nearby_connections.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_udid.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/fluttertoast.framework", + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; @@ -370,20 +354,26 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; + CODE_SIGN_STYLE = Manual; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = ""; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Flutter", ); INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Flutter", ); PRODUCT_BUNDLE_IDENTIFIER = com.nankai.flutterNearbyConnectionsExample; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; VERSIONING_SYSTEM = "apple-generic"; @@ -490,7 +480,8 @@ MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; - SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; @@ -502,20 +493,26 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; + CODE_SIGN_STYLE = Manual; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = ""; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Flutter", ); INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Flutter", ); PRODUCT_BUNDLE_IDENTIFIER = com.nankai.flutterNearbyConnectionsExample; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; @@ -529,20 +526,26 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; + CODE_SIGN_STYLE = Manual; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = ""; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Flutter", ); INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Flutter", ); PRODUCT_BUNDLE_IDENTIFIER = com.nankai.flutterNearbyConnectionsExample; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; VERSIONING_SYSTEM = "apple-generic"; diff --git a/example/ios/Runner/AppDelegate.swift b/example/ios/Runner/AppDelegate.swift index 70693e4..a02a2f8 100644 --- a/example/ios/Runner/AppDelegate.swift +++ b/example/ios/Runner/AppDelegate.swift @@ -3,11 +3,12 @@ import Flutter @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate { - override func application( - _ application: UIApplication, - didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? - ) -> Bool { - GeneratedPluginRegistrant.register(with: self) - return super.application(application, didFinishLaunchingWithOptions: launchOptions) - } + + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + GeneratedPluginRegistrant.register(with: self) + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } } diff --git a/ios/Classes/Device.swift b/ios/Classes/Device.swift index ed4f590..24b5115 100644 --- a/ios/Classes/Device.swift +++ b/ios/Classes/Device.swift @@ -17,11 +17,10 @@ class Device: NSObject { 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 @@ -29,16 +28,22 @@ class Device: NSObject { } func invite(with browser: MCNearbyServiceBrowser) { - self.createSession() - browser.invitePeer(self.peerID, to: self.session!, withContext: nil, timeout: 10) + 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: self) + if(self.state != state) { + self.state = state + NotificationCenter.default.post(name: MPCManager.Notifications.deviceDidChangeState, object: self) + } } public func session(_ session: MCSession, didReceive data: Data, fromPeer peerID: MCPeerID) { @@ -48,7 +53,7 @@ extension Device: MCSessionDelegate { 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?) { } - + } diff --git a/ios/Classes/MPCManager.swift b/ios/Classes/MPCManager.swift index 9207c54..f14c2c8 100644 --- a/ios/Classes/MPCManager.swift +++ b/ios/Classes/MPCManager.swift @@ -29,17 +29,17 @@ class MPCManager: NSObject { var deviceDidChange: (() -> Void)? - override init() { - if let data = UserDefaults.standard.data(forKey: "peerID"), let id = NSKeyedUnarchiver.unarchiveObject(with: data) as? MCPeerID { +// override init() { +// if let data = UserDefaults.standard.data(forKey: "peerID"), let id = NSKeyedUnarchiver.unarchiveObject(with: data) as? MCPeerID { // self.localPeerID = id - } else { +// } 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() - } +// } +// super.init() +// } deinit{ if(enterbackgroundNotification != nil){ @@ -97,24 +97,32 @@ class MPCManager: NSObject { } func invitePeer(deviceID: String) { - self.devices.forEach { (element) in - element.disconnect() + do { + let device = MPCManager.instance.findDevice(for: deviceID) + if(device?.state == MCSessionState.notConnected){ + device?.invite(with: self.browser) + } + } catch let error { + print(error.localizedDescription) } - - - let device = MPCManager.instance.device(for: deviceID) - device?.invite(with: self.browser) } func disconnectPeer(deviceID: String){ - self.devices.forEach { (element) in - if(element.peerID.displayName == deviceID){ - element.disconnect() - } + let device = MPCManager.instance.findDevice(for: deviceID) + device?.disconnect() + } + + func device(for id: MCPeerID) -> Device { + if let device = devices.first(where: {$0.peerID == id}) { + return device + } else { + let device = Device(peerID: id) + self.devices.append(device) + return device } } - func device(for deviceId: String) -> Device? { + func findDevice(for deviceId: String) -> Device? { for device in self.devices { if device.peerID.displayName == deviceId { return device } } @@ -122,14 +130,11 @@ class MPCManager: NSObject { return nil } - func device(for id: MCPeerID) -> Device { + func findDevice(for id: MCPeerID) -> Device? { if let device = devices.first(where: {$0.peerID == id}) { return device - } else { - let device = Device(peerID: id) - self.devices.append(device) - return device } + return nil } @objc func enteredBackground() { @@ -141,7 +146,6 @@ class MPCManager: NSObject { extension MPCManager: MCNearbyServiceAdvertiserDelegate { func advertiser(_ advertiser: MCNearbyServiceAdvertiser, didReceiveInvitationFromPeer peerID: MCPeerID, withContext context: Data?, invitationHandler: @escaping (Bool, MCSession?) -> Void) { - let device = self.device(for: peerID) device.createSession() invitationHandler(true, device.session) @@ -151,15 +155,21 @@ extension MPCManager: MCNearbyServiceAdvertiserDelegate { extension MPCManager: MCNearbyServiceBrowserDelegate { func browser(_ browser: MCNearbyServiceBrowser, foundPeer peerID: MCPeerID, withDiscoveryInfo info: [String : String]?) { + // found peer, create a device with this peerID self.device(for: peerID) - } func browser(_ browser: MCNearbyServiceBrowser, lostPeer peerID: MCPeerID) { - let device = self.device(for: peerID) - device.disconnect() - devices.removeAll { (device) -> Bool in - device.peerID == peerID + // lost peer, disconnect and remove the device with this peerID + let device = self.findDevice(for: peerID) + device?.disconnect() + do { + try devices.removeAll { (device) -> Bool in + device.peerID == peerID + } + } catch let error { + print(error.localizedDescription) } } + } diff --git a/ios/Classes/SwiftFlutterNearbyConnectionsPlugin.swift b/ios/Classes/SwiftFlutterNearbyConnectionsPlugin.swift index 4ed8fc0..864826f 100644 --- a/ios/Classes/SwiftFlutterNearbyConnectionsPlugin.swift +++ b/ios/Classes/SwiftFlutterNearbyConnectionsPlugin.swift @@ -101,7 +101,11 @@ public class SwiftFlutterNearbyConnectionsPlugin: NSObject, FlutterPlugin { public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { switch MethodCall(rawValue: call.method) { case .initNearbyService: - let data = call.arguments as! Dictionary + guard let data = call.arguments as? Dictionary else { + result(false) + return + + } let serviceType:String = data["serviceType"] as? String ?? SERVICE_TYPE var deviceName:String = data["deviceName"] as? String ?? "" if (deviceName.isEmpty){ @@ -124,16 +128,24 @@ public class SwiftFlutterNearbyConnectionsPlugin: NSObject, FlutterPlugin { MPCManager.instance.stopBrowsingForPeers() result(true) case .invitePeer: - let data = call.arguments as! Dictionary - let deviceId:String? = data["deviceId"] as? String ?? nil - if (deviceId != nil) { - MPCManager.instance.invitePeer(deviceID: deviceId!) - result(true) - } else { + guard let data = call.arguments as? Dictionary 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: - let data = call.arguments as! Dictionary + guard let data = call.arguments as? Dictionary else { + result(false) + return + + } let deviceId:String? = data["deviceId"] as? String ?? nil if (deviceId != nil) { MPCManager.instance.disconnectPeer(deviceID: deviceId!) @@ -142,10 +154,13 @@ public class SwiftFlutterNearbyConnectionsPlugin: NSObject, FlutterPlugin { result(false) } case .sendMessage: - let dict = call.arguments as! Dictionary + guard let dict = call.arguments as? Dictionary else { + result(false) + return + } do { let jsonData = try JSONSerialization.data(withJSONObject: dict, options: .prettyPrinted) - if let device = MPCManager.instance.device(for: dict["deviceId"] as! String) { + if let device = MPCManager.instance.findDevice(for: dict["deviceId"] as! String) { currentReceivedDevice = device try device.send(data: jsonData) result(true)