🪶

SwiftUI BlueTooth

2024/09/29に公開

SwiftUIでBlueTooth通信ができるらしい?

Flutterを使ってBlueTooth通信の機能を実装してみようとしたがなんか難しいぞ💦
Swift, Kotlinのコードを呼ばないといけないらしい?

つまりこういうことだ

  1. Swift, Kotlinでコードを書く
  2. Flutterから呼ぶ
  3. 面倒くさくないか...

パッケージも必要らしいからそれじゃあオリジナルで作ってみるかと思った。

https://developer.apple.com/documentation/corebluetooth

概要

Core Bluetooth フレームワークは、Bluetooth 搭載の低エネルギー(LE)および基本レート/拡張データレート(BR/EDR)ワイヤレステクノロジーと通信するためにアプリに必要なクラスを提供します。

Core Bluetooth フレームワークのクラスをサブクラス化しないでください。これらのクラスをオーバーライドすると、未定義の動作になります。

macOS上で動作するiPadアプリでは、Core Bluetoothのバックグラウンド実行モードはサポートされていません。

重要

Info.plistにアクセスが必要なデータタイプの使用説明キーが含まれていないと、アプリがクラッシュします。iOS 13 以降にリンクされたアプリで Core Bluetooth API にアクセスするには、NSBluetoothAlwaysUsageDescription キーを含めます。iOS 12 以前では、Bluetooth 周辺機器データにアクセスするために NSBluetoothPeripheralUsageDescription をインクルードします。

Info.plistの設定してコード書いたら実装できた。

近くのマウスやキーボードを探知する

SwiftUIでBlueTooth通信をして近くに置いてあるマウスやキーボードーを探知して、表示する機能を作ってみた。

info.plistを設定する
Privacy - Bluetooth Always Usage Descriptionと記載する。適切な説明も書く。今回は適切かわからないが。。。

全体のソースコード

import SwiftUI
import CoreBluetooth

class BluetoothManager: NSObject, ObservableObject, CBCentralManagerDelegate {
    @Published var connectedDevices: [CBPeripheral] = []
    private var centralManager: CBCentralManager!
    
    override init() {
        super.init()
        self.centralManager = CBCentralManager(delegate: self, queue: nil)
    }
    
    func startScanning() {
        if centralManager.state == .poweredOn {
            centralManager.scanForPeripherals(withServices: nil, options: nil)
        }
    }
    
    func centralManagerDidUpdateState(_ central: CBCentralManager) {
        if central.state == .poweredOn {
            print("Bluetooth is powered on")
        } else {
            print("Bluetooth is not available")
        }
    }
    
    func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
        if !connectedDevices.contains(peripheral) {
            connectedDevices.append(peripheral)
        }
    }
}

struct ContentView: View {
    @StateObject private var bluetoothManager = BluetoothManager()
    
    var body: some View {
        VStack {
            Button(action: {
                bluetoothManager.startScanning()
            }) {
                Text("計測開始")
                    .padding()
                    .background(Color.blue)
                    .foregroundColor(.white)
                    .cornerRadius(10)
            }
            
            List(bluetoothManager.connectedDevices, id: \.identifier) { device in
                VStack(alignment: .leading) {
                    Text(device.name ?? "Unknown Device")
                        .font(.headline)
                    Text(device.identifier.uuidString)
                        .font(.subheadline)
                }
            }
        }
        .padding()
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

https://x.com/JBOY83062526/status/1838940070843408690

感想

まさか本当にBlueToothに対応したマウスやキーボードと接続できるか確認できる機能を実装できるとは思わなかった。FlutterだとBlueTooth連携が弱いらしい。

気軽にお家でIOTアプリ作る練習できるかも?

Discussion