AdventCalendar
iOS
Swift
iOSDay 14

iOSでBluetooth通信するサンプルコード

More than 3 years have passed since last update.


概要


  • iPhoneでBluetooth通信を動かしてみたかったので、かんたんなサンプルを書いてみました

  • 基本的に、MultipeerConnectivityで用意されている各クラスの初期化とデリゲートの実装だけ行えば、簡単にBluetooth通信ができました


つくったもの(Bluetooth通信のサンプル)


  • 画面をタップすると、自分の端末に円がアニメーション表示されます

  • Bluetooth通信で座標を送り、相手の端末にも同じ円が表示します

  • 長押しで円がでかくなります

  • スプラトゥーン風にしたかったのですが、だいぶコレジャナイ

sample.png


サンプルコード



  • BluetoothGameSample


    • (エラー処理などいろいろ足りないです。とりあえずのサンプルになってます)




実行時の注意


  • 端末のBluetooth設定をONにする必要があります(「設定」アプリ > Bluetooth > オン)

  • アプリ起動すると、周囲に同じアプリが起動していないか探しに行きます(60秒タイムアウト)

  • Bluetooth通信はシミュレータでは試せないようです


要点


0.使用したクラスについて



  • 参考サイトにもあるように、MCBrowserViewControllerを使うと簡単に接続先の選択~接続の確立までをUI付きで提供してくれます。

  • ただ、今回は接続先の 選択画面を挟みたくなかった ので、MCBrowserViewControllerの代わりにMCNearbyServiceBrowserを使用し、最初に見つけた端末に即接続しに行っています


1.Bluetooth通信準備


  • サンプルではちょっと処理を加えていますが、Bluetooth通信に最低限必要な初期化処理は以下のはず。


  • MCNearbyServiceAdvertiserMCNearbyServiceBrowserの役割については、参考サイトの招待状の例えがわかりやすかったです

    func initialize() {

self.peerID = MCPeerID(displayName: UIDevice.currentDevice().name)
self.session = MCSession(peer: peerID)
self.session.delegate = self

self.advertiser = MCNearbyServiceAdvertiser(peer: peerID, discoveryInfo: nil, serviceType: serviceType)
self.advertiser.delegate = self
self.advertiser.startAdvertisingPeer()

self.browser = MCNearbyServiceBrowser(peer: peerID, serviceType: serviceType)
self.browser.delegate = self
self.browser.startBrowsingForPeers()
}

    // MARK: - MCNearbyServiceAdvertiserDelegate

func advertiser(advertiser: MCNearbyServiceAdvertiser, didReceiveInvitationFromPeer peerID: MCPeerID, withContext context: NSData?, invitationHandler: (Bool, MCSession) -> Void) {
invitationHandler(true, self.session);
}

    // MARK: - MCNearbyServiceBrowserDelegate

func browser(browser: MCNearbyServiceBrowser, foundPeer peerID: MCPeerID, withDiscoveryInfo info: [String : String]?) {
self.browser.invitePeer(peerID, toSession: session, withContext: nil, timeout: 60)
}


2.データの送信



  • ViewControllerのタッチイベントで、「相手端末への座標の送信」と「自分の座標への円の描画」を行っています

  • 以下はデータ送信部分


NearbyManager.swift

    func sendMessage(point : PointModel) {

do {
let data = NSKeyedArchiver.archivedDataWithRootObject(point)
try self.session.sendData(data,
toPeers: self.session.connectedPeers,
withMode: MCSessionSendDataMode.Unreliable)
} catch {
print(error)
}
}


3.データの受信


  • 受け取った座標データに従って、相手の円を描画しています

  • 以下はデータ受信部分


NearbyManager.swift

    // MARK: - MCSessionDelegate

func session(session: MCSession, didReceiveData data: NSData,
fromPeer peerID: MCPeerID) {
dispatch_async(dispatch_get_main_queue()) {
let point = NSKeyedUnarchiver.unarchiveObjectWithData(data) as! PointModel
self.canvasVC?.paintEnemyPuddle(point)
}
}


まとめと課題



  • MultipeerConnectivityで用意されている各クラスのデリゲートを実装すれば、Bluetooth通信は簡単に実装できる

  • いろいろ考慮が足りていないので、実際に使うとなるといろいろ手を入れる必要がありそう


    • この実装だと通信のタイムラグで2端末間の表示にズレが出ることがあるので、少なくともユーザのアクションの実行時間はデータとして持たせる必要がある

    • エラー処理全般を入れていないので、相手が遠く離れた時やアプリを終了したときなど対応が必要

    • 上記に関連するが、状況によってデータが相手に届かないことがある。ロストしたデータのフォローも必要




参考