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,5 +1,25 @@
|
||||
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) {
|
||||
@ -8,7 +28,151 @@ public class SwiftNearbyConnectionsPlugin: NSObject, FlutterPlugin {
|
||||
registrar.addMethodCallDelegate(instance, channel: channel)
|
||||
}
|
||||
|
||||
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
|
||||
result("iOS " + UIDevice.current.systemVersion)
|
||||
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) {
|
||||
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