iOS藍牙須知
iOS提供了4個框架用于實現藍牙連接
1.gameKit.framework(用法簡單)
只能用于iOS設備之間的連接,多用于游戲(比如五子棋游戲),從iOS7開始過期(請參考http://www.lxweimin.com/p/f58e57f1b424)
2.MultipeerConnectivity.framework
只能用于iOS設備之間的連接,從iOS7開始引入,主要用于文件共享(僅限于沙盒的文件)
3.ExternalAccessory.frameWork
可用于第三方藍牙設備交互,但是藍牙設備必須經過蘋果MFi認證(國內較少)
4.CoreBluetooh.framework(時下熱門)
可用于第三方藍牙設備交互,必須要支持藍牙4.0(硬件至少是4s,系統至少iOS6,藍牙4.0以低功耗著稱,一般也叫BLE(Bluetooth low Energy) 目前應用比較多的案例:運動手環,嵌入式設備,智能家居)
Core Bluetooth框架簡介
Core Bluetooth基本常識
1.每個藍牙4.0設備都是通過服務(Service)和特征(Characteristic)來展示自己的
2.一個設備必然包含一個或多個服務,每個服務下面又包含若干個特征
3.特征是與外界交互的最小單位(比如說:一個藍牙4.0設備,用特征A來描述自己的出場信息,用特征B來收發數據)
4.服務和特征都是用UUID來唯一標識的,通過UUID就能區分不同的服務和特征
5.設備里面的各個服務(Service)和特征(Characteristic)的功能,均由藍牙設備硬件廠商提供,比如那些是用來交互(讀寫),那些可獲取模塊信息(只讀)等
Core Bluetooth的開發步驟
1.建立中心設備(手機)
2.掃描外圍設備(Discover Peripheral)
3.連接外圍設備(Connect Peripheral)
4.掃描外圍設備的服務和特征(Discover Service and Characteristic)
5.利用特征與外圍設備做數據交互(Explore And Interact)
6.斷開連接(Disconnect)
如何讓iOS模擬器也能測試藍牙4.0程序
1.買一個CSR藍牙4.0USB適配器,插在Mac上
2.在終端輸入 sudo nvram bluetoothHostControllerSwitchBehavior="never"
3.重啟Mac
上代碼
//
// ViewController.m
// 藍牙(CoreBlueTooth)
//
// Created by ws on 2017/6/14.
// Copyright ? 2017年 王松. All rights reserved.
//
#import "ViewController.h"
#import <CoreBluetooth/CoreBluetooth.h>
@interface ViewController ()<CBCentralManagerDelegate,CBPeripheralDelegate>
///中央管理者
@property(nonatomic,strong)CBCentralManager*mgr;
///存儲掃描到的外圍設備
@property(nonatomic,strong)NSMutableArray*peripherals;
@end
@implementation ViewController
-(NSMutableArray *)peripherals{
if (!_peripherals) {
_peripherals = [NSMutableArray array];
}
return _peripherals;
}
#pragma mark 1.建立中央管理者
-(CBCentralManager *)mgr{
if (!_mgr) {
//1.建立中央管理者
self.mgr = [[CBCentralManager alloc]initWithDelegate:self queue:nil];
}
return _mgr;
}
#pragma mark CBCentralManager必須實現方法
/**
狀態發生改變的時候會執行該方法(藍牙4.0沒有打開變成打開狀態就會執行該方法)
*/
- (void)centralManagerDidUpdateState:(CBCentralManager *)central{
//判斷狀態
if (central.state) {
}
}
#pragma mark 掃描到外圍設備執行的代理方法
/**
當發現外圍設備的時候會調用該方法
@param peripheral 發現的外圍設備
@param advertisementData 外圍設備發出的信號
@param RSSI 信號強度
*/
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *, id> *)advertisementData RSSI:(NSNumber *)RSSI{
//先判斷 如果我的數組里面已經包含了某個外圍設備就不存儲啦
if (![self.peripherals containsObject:peripheral]) {
[self.peripherals addObject:peripheral];
}
}
#pragma mark 用戶連接外圍設備
-(void)connect:(CBPeripheral *)peripheral{
//連接外圍設備
[self.mgr connectPeripheral:peripheral options:nil];
}
#pragma mark 連接到某一個外圍設備就會調用該代理方法
/**
連接到某一個外圍設備所走的方法
@param peripheral 連接上的外圍設備
*/
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral{
//1.掃描所有的服務
//參數:指定掃描該外圍設備的那些服務(nil 表示掃描該外圍設備的所有服務)
[peripheral discoverServices:nil];
//2.設置外圍設備的代理
peripheral.delegate = self;
}
#pragma mark CBPeripheralDelegate外圍設備的代理方法
/**
發現掃描到該外圍設備的服務的時候執行該方法(掃描到服務之后直接添加到peripheral.services數組對象里面)
*/
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(nullable NSError *)error{
//對掃描到的該外圍設備的服務進行遍歷
for (CBService *service in peripheral.services) {
//拿到你想要的某個服務
if ([service.UUID.UUIDString isEqualToString:@"某個服務的UUID"]) {
NSLog(@"拿到你想要的某個服務");
//掃描服務里面的所有特征
//參數1:CBUUID:可以指定這個服務里想要掃描的特征(nil 表示掃描這個服務里面的所有的特征)
[peripheral discoverCharacteristics:nil forService:service];
}
}
}
/**
當掃描某一個服務的特征的時候會執行該方法(掃描到特征之后直接添加到service.characteristics數組對象里面)
@param service 在哪一個服務里的特征
*/
-(void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error{
for (CBCharacteristic *characteristic in service.characteristics) {
if ([characteristic.UUID.UUIDString isEqualToString:@"某個特征的UUID"]) {
//拿到特征 和外圍設備進行交互
//讀
// [peripheral readValueForCharacteristic:characteristic];
//寫
// peripheral writeValue:<#(nonnull NSData *)#> forCharacteristic:<#(nonnull CBCharacteristic *)#> type:<#(CBCharacteristicWriteType)#>
}
}
}
- (void)viewDidLoad {
[super viewDidLoad];
//1.建立中央管理者
//2.掃描所有的外圍設備
//參數1:CBUUID 可以將你想要掃描的服務的外圍設備傳入(傳nil表示掃描所有的外圍設備)
//參數2:什么操作
[self.mgr scanForPeripheralsWithServices:nil options:nil];
}