2021-02-28 08:36:16 +00:00
|
|
|
import Flutter
|
|
|
|
import UIKit
|
2021-02-28 09:22:53 +00:00
|
|
|
import MultipeerConnectivity
|
|
|
|
import SwiftyJSON
|
|
|
|
|
|
|
|
let SERVICE_TYPE = "nearby_connections"
|
2021-02-28 11:56:55 +00:00
|
|
|
let INVOKE_CHANGE_STATE_METHOD = "ios.stateChanged"
|
|
|
|
let INVOKE_MESSAGE_RECEIVE_METHOD = "ios.messageReceived"
|
2021-02-28 09:22:53 +00:00
|
|
|
|
|
|
|
enum MethodCall: String {
|
2021-02-28 11:56:55 +00:00
|
|
|
case startAdvertisingPeer = "startAdvertising"
|
|
|
|
case startBrowsingForPeers = "startDiscovery"
|
2021-02-28 09:22:53 +00:00
|
|
|
|
2021-02-28 11:56:55 +00:00
|
|
|
case adOnConnectionInitiated = "ad.onConnectionInitiated"
|
|
|
|
case adOnConnectionResult = "ad.onConnectionResult"
|
2021-02-28 12:37:42 +00:00
|
|
|
case adOnDisconnected = "ad.onDisconnected"
|
2021-02-28 09:22:53 +00:00
|
|
|
|
2021-02-28 11:56:55 +00:00
|
|
|
case disOnConnectionInitiated = "dis.onConnectionInitiated"
|
|
|
|
case disOnConnectionResult = "dis.onConnectionResult"
|
2021-02-28 12:37:42 +00:00
|
|
|
case disOnDisconnected = "dis.onDisconnected"
|
2021-02-28 11:56:55 +00:00
|
|
|
case disOnEndpointFound = "dis.onEndpointFound"
|
|
|
|
case disOnEndpointLost = "dis.onEndpointLost"
|
2021-02-28 09:22:53 +00:00
|
|
|
|
2021-02-28 11:56:55 +00:00
|
|
|
case stopAdvertisingPeer = "stopAdvertising"
|
|
|
|
case stopBrowsingForPeers = "stopDiscovery"
|
|
|
|
|
|
|
|
case invitePeer = "requestConnection"
|
|
|
|
case disconnectPeer = "disconnectFromEndpoint"
|
|
|
|
|
|
|
|
case sendMessage = "sendPayload"
|
2021-02-28 09:22:53 +00:00
|
|
|
}
|
2021-02-28 08:36:16 +00:00
|
|
|
|
|
|
|
public class SwiftNearbyConnectionsPlugin: NSObject, FlutterPlugin {
|
|
|
|
public static func register(with registrar: FlutterPluginRegistrar) {
|
2021-02-28 09:22:53 +00:00
|
|
|
let channel = FlutterMethodChannel(name: "nearby_connections", binaryMessenger: registrar.messenger())
|
2021-02-28 12:37:42 +00:00
|
|
|
let instance = SwiftNearbyConnectionsPlugin(channel: channel)
|
2021-02-28 09:22:53 +00:00
|
|
|
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 [
|
2021-02-28 11:56:55 +00:00
|
|
|
"endpointId": deviceId,
|
|
|
|
"userNickName": deviceName,
|
2021-02-28 09:22:53 +00:00
|
|
|
"state": state
|
|
|
|
]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@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())
|
|
|
|
}
|
|
|
|
|
2021-02-28 11:56:55 +00:00
|
|
|
@objc func adOnConnectionInitiated(){
|
|
|
|
}
|
|
|
|
@objc func adOnConnectionResult(){
|
|
|
|
}
|
|
|
|
@objc func adOnDisconnected(){
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@objc func disOnConnectionInitiated(){
|
|
|
|
}
|
|
|
|
@objc func disOnConnectionResult(){
|
|
|
|
}
|
|
|
|
@objc func disOnDisconnected(){
|
|
|
|
}
|
|
|
|
@objc func disOnEndpointFound(){
|
|
|
|
}
|
|
|
|
@objc func disOnEndpointLost(){
|
|
|
|
}
|
|
|
|
|
2021-02-28 09:22:53 +00:00
|
|
|
@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)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
2021-02-28 11:56:55 +00:00
|
|
|
NotificationCenter.default.addObserver(self, selector: #selector(adOnConnectionInitiated), name: MPCManager.Notifications.adOnConnectionInitiated, object: nil)
|
|
|
|
NotificationCenter.default.addObserver(self, selector: #selector(adOnConnectionResult), name: MPCManager.Notifications.adOnConnectionResult, object: nil)
|
|
|
|
NotificationCenter.default.addObserver(self, selector: #selector(adOnDisconnected), name: MPCManager.Notifications.adOnDisconnected, object: nil)
|
|
|
|
|
|
|
|
NotificationCenter.default.addObserver(self, selector: #selector(disOnConnectionInitiated), name: MPCManager.Notifications.disOnConnectionInitiated, object: nil)
|
|
|
|
NotificationCenter.default.addObserver(self, selector: #selector(disOnConnectionResult), name: MPCManager.Notifications.disOnConnectionResult, object: nil)
|
|
|
|
NotificationCenter.default.addObserver(self, selector: #selector(disOnDisconnected), name: MPCManager.Notifications.disOnDisconnected, object: nil)
|
|
|
|
NotificationCenter.default.addObserver(self, selector: #selector(disOnEndpointFound), name: MPCManager.Notifications.disOnEndpointFound, object: nil)
|
|
|
|
NotificationCenter.default.addObserver(self, selector: #selector(disOnEndpointLost), name: MPCManager.Notifications.disOnEndpointLost, object: nil)
|
|
|
|
|
2021-02-28 09:22:53 +00:00
|
|
|
NotificationCenter.default.addObserver(self, selector: #selector(messageReceived), name: Device.messageReceivedNotification, object: nil)
|
|
|
|
|
|
|
|
MPCManager.instance.deviceDidChange = {[weak self] in
|
|
|
|
self?.stateChanged()
|
|
|
|
}
|
2021-02-28 08:36:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
|
2021-02-28 09:22:53 +00:00
|
|
|
switch MethodCall(rawValue: call.method) {
|
2021-02-28 11:56:55 +00:00
|
|
|
case .startAdvertisingPeer:
|
2021-02-28 09:22:53 +00:00
|
|
|
guard let data = call.arguments as? Dictionary<String, AnyObject> else {
|
|
|
|
result(false)
|
|
|
|
return
|
|
|
|
}
|
2021-02-28 11:56:55 +00:00
|
|
|
let serviceType:String = data["serviceId"] as? String ?? SERVICE_TYPE
|
|
|
|
var deviceName:String = data["userNickName"] as? String ?? ""
|
2021-02-28 09:22:53 +00:00
|
|
|
if (deviceName.isEmpty){
|
|
|
|
deviceName = UIDevice.current.name
|
|
|
|
}
|
|
|
|
|
2021-02-28 11:56:55 +00:00
|
|
|
MPCManager.instance.setup(serviceType: serviceType, deviceName: deviceName, isAdvert: true)
|
2021-02-28 09:22:53 +00:00
|
|
|
currentReceivedDevice = Device(peerID: MPCManager.instance.localPeerID)
|
|
|
|
MPCManager.instance.startAdvertisingPeer()
|
|
|
|
result(true)
|
|
|
|
case .startBrowsingForPeers:
|
2021-02-28 11:56:55 +00:00
|
|
|
guard let data = call.arguments as? Dictionary<String, AnyObject> else {
|
|
|
|
result(false)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
let serviceType:String = data["serviceId"] as? String ?? SERVICE_TYPE
|
|
|
|
var deviceName:String = data["userNickName"] as? String ?? ""
|
|
|
|
if (deviceName.isEmpty){
|
|
|
|
deviceName = UIDevice.current.name
|
|
|
|
}
|
|
|
|
|
|
|
|
MPCManager.instance.setup(serviceType: serviceType, deviceName: deviceName, isAdvert: false)
|
|
|
|
currentReceivedDevice = Device(peerID: MPCManager.instance.localPeerID)
|
2021-02-28 09:22:53 +00:00
|
|
|
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
|
|
|
|
}
|
2021-02-28 11:56:55 +00:00
|
|
|
guard let deviceId: String = data["endpointId"] as? String else {
|
2021-02-28 09:22:53 +00:00
|
|
|
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
|
|
|
|
}
|
2021-02-28 11:56:55 +00:00
|
|
|
let deviceId:String? = data["endpointId"] as? String ?? nil
|
2021-02-28 09:22:53 +00:00
|
|
|
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 {
|
2021-02-28 12:37:42 +00:00
|
|
|
let jsonData = try JSONSerialization.data(withJSONObject: dict)
|
2021-02-28 11:56:55 +00:00
|
|
|
if let device = MPCManager.instance.findDevice(for: dict["endpointId"] as! String) {
|
2021-02-28 09:22:53 +00:00
|
|
|
currentReceivedDevice = device
|
|
|
|
try device.send(data: jsonData)
|
|
|
|
result(true)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
} catch let error as NSError {
|
|
|
|
print(error)
|
|
|
|
}
|
|
|
|
result(false)
|
|
|
|
default:
|
|
|
|
result(FlutterMethodNotImplemented)
|
|
|
|
return
|
|
|
|
}
|
2021-02-28 08:36:16 +00:00
|
|
|
}
|
2021-02-28 09:22:53 +00:00
|
|
|
|
2021-02-28 08:36:16 +00:00
|
|
|
}
|