mirror of
https://github.com/hackku21/nearby_connections.git
synced 2024-10-27 19:14:01 +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 Flutter
|
||||||
import UIKit
|
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 class SwiftNearbyConnectionsPlugin: NSObject, FlutterPlugin {
|
||||||
public static func register(with registrar: FlutterPluginRegistrar) {
|
public static func register(with registrar: FlutterPluginRegistrar) {
|
||||||
let channel = FlutterMethodChannel(name: "nearby_connections", binaryMessenger: registrar.messenger())
|
let channel = FlutterMethodChannel(name: "nearby_connections", binaryMessenger: registrar.messenger())
|
||||||
let instance = SwiftNearbyConnectionsPlugin()
|
let instance = SwiftNearbyConnectionsPlugin()
|
||||||
registrar.addMethodCallDelegate(instance, channel: channel)
|
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) {
|
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