Copy swift code

This commit is contained in:
Prerak Mann 2021-02-28 14:52:53 +05:30
parent 8b29fdc01f
commit aae94e8e9b
4 changed files with 484 additions and 4 deletions

56
ios/Classes/Device.swift Normal file
View 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?) { }
}

View 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
View 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"
}

View File

@ -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
}
} }
} }