- 整理大神班視頻
一、GameKit
簡介:
- 實現藍牙設備之間的
通訊
- 只能使用在
iOS設備
之間同一個應用
內連接 - 從
iOS7
開始過期了 - 但是GameKit是
最基本的
藍牙通訊框架 - 通過藍牙可以實現文件的共享(僅限設備沙盒中的文件)
- 此框架一般用於遊戲開發(比如五子棋對戰)
過程:
- 使用藍牙將兩個iOS設備連接起來
- 搜索對方的設備
- 實現將手機中的圖片發送給對方
藍牙互連:
// 初始化鏈接藍牙控制器
GKPeerPickerController *peerCtr = [[GKPeerPickerController alloc]init];
// 顯示匹配到的藍牙設備
[peerCtr show];
* GKPeerPickerController
代理
/*
* 連接藍牙的方式 附近 在線
*/
- (void)peerPickerController:(GKPeerPickerController *)picker didSelectConnectionType:(GKPeerPickerConnectionType)type {
}
// 連接會話的方式 附近 在線
- (GKSession *)peerPickerController:(GKPeerPickerController *)picker sessionForConnectionType:(GKPeerPickerConnectionType)type {
return nil;
}
/* 連接成功
* peerID 連接成功的設備id
* session 當前回話 只需要保存當前的會話 即 可 數據傳遞
*/
- (void)peerPickerController:(GKPeerPickerController *)picker didConnectPeer:(NSString *)peerID toSession:(GKSession *)session {
// 隱藏選擇器
[picker dismiss];
// 接收數據的回調 GameKIt 必須實現的
[session setDataReceiveHandler:self withContext:nil];
// 保存會話
self.session = session;
}
/*
* 退出
*/
- (void)peerPickerControllerDidCancel:(GKPeerPickerController *)picker
{
}
// 只要有數據回來 那麼就會調用
- (void) receiveData:(NSData *)data fromPeer:(NSString *)peer inSession: (GKSession *)session context:(void *)context
{
}
圖片相互發送:
// 發送圖片
- (IBAction)sendImage {
// 拿到需要發送出去的圖片
UIImage *image = self.showImageView.image;
// 將圖片轉換成NSData類型
NSData *imgData = UIImagePNGRepresentation(image);
/**
* 發送數據給所有匹配上的用戶
*
* @param GKSendDataMode 數據發送的模式:(安全/不安全模式)
* GKSendDataUnreliable : 不安全模式:就像發10個傳單,傳單直接往人羣中砸過去,能不能收到不管
* GKSendDataReliable:安全模式:就像發10個傳單,每一個傳單都得發到路人的手上,纔再發下一個傳單
* @return
*/
[self.m_Session sendDataToAllPeers:imgData withDataMode:GKSendDataUnreliable error:nil];
}
設置圖片:
* GameKit提供的接受數據是方法的回調
* 需要監聽接收傳遞過來的數據
* 在連接成功代理方法中設置監聽
// 若執行下面方法,必須設置
// 接收數據的回調 GameKIt 必須實現的
// [session setDataReceiveHandler:self withContext:nil];
/** 監聽傳遞過來的數據
* setDataReceiveHandler: 由哪個對象來監聽數據的接受
* withContext : 監聽需要傳遞的參數
*/
[session setDataReceiveHandler:self withContext:nil];
/** 實現監聽方法
* 只設置由誰監聽傳遞過來的數據還是不足的,
* 因爲我們還是不能拿到傳遞過來的數據,進入監聽方法的頭文件可以看到
* SEL = -receiveData:fromPeer:inSession:context:
* 所以我們必須實現這個方法才能拿到接收到的數據,這個回調方法方法
*/
/**
* 實現接收數據的回調方法
*
* @param data 接收到的數據
* @param peer 傳遞數據的設備ID
* @param session 當前回話
* @param context 註冊監聽傳遞過來的數據
*/
- (void) receiveData:(NSData *)data fromPeer:(NSString *)peer inSession: (GKSession *)session context:(void *)context
{
}
二、mutipeerConnectivity
簡介
- iOS 7引入的一個全新框架
- 多點連接
- 替代GameKit框架
- 多用於文件的傳輸
* iOS設備不聯網也能跟附近的人聊天
* FireChat
* See You Around
* 以上近場聊天App都是基於mutipeerConnectivity框架
* 搜索和傳輸的方式
* 雙方WIFI和藍牙都沒有打開:無法實現
* 雙方都開啓藍牙:通過藍牙發現和傳輸
* 雙方都開啓WIFI:通過WIFI Direct發現和傳輸,速度接近AirDrop
* 雙方同時開啓了WIFI和藍牙:模擬AirDrop,通過低功耗藍牙技術掃描發現握手,然後通過WIFI Direct傳輸
連接設備
- 創建MCSession對象用於存放當前連接的會話
// 創建MCSession對象
// initWithPeer:設備的ID
// 用於存放當前的連接的會話
self.mc_Session = [ [MCSession alloc]initWithPeer:[[MCPeerID alloc] initWithDisplayName:[UIDevice currentDevice].name]];
- 開啓廣播對象,通知正在搜索的設備他們是可用的
// 廣播對象,告訴其它的設備他們是可用的
// 創建廣播對象
// initWithServiceType: 廣播類型的標示(因爲廣播可能比較多,所以最好每個廣播綁定一個唯一標示)(自定義字符串,類似cell的註冊ID)
// session:當前會話
// discoveryInfo: 廣播信息
MCAdvertiserAssistant *advertiserAssistant =[[MCAdvertiserAssistant alloc] initWithServiceType:SERVICE_TYPE discoveryInfo:nil session:self.mc_Session];
}
// 開啓廣播
[self.advertiserAssistant start];
- 開始搜索藍牙設備
// 創建搜索藍牙設備控制器
MCBrowserViewController *mbVC = [[MCBrowserViewController alloc]initWithServiceType:SERVICE_TYPE session:self.mc_Session];
// 設置控制器代理
mbVC.delegate = self;
// 跳轉到搜索控制器
[self presentViewController:mbVC animated:YES completion:nil];
選擇數據
- 在搜索控制器的連接完成的代理方法中隱藏搜索控制器
/**
* 連接完成
*
* @param browserViewController 搜索控制器
*/
- (void)browserViewControllerDidFinish:(MCBrowserViewController *)browserViewController
{
[browserViewController dismissViewControllerAnimated:YES completion:nil];
}
發送數據
- 實現搜索控制器的代理方法,獲取連接上的設備ID
#pragma mark - MCBrowserViewControllerDelegate
/**
* 連接成功
*
* @param browserViewController 搜索控制器
* @param peerID 連接上的設備ID
* @param info 連接的信息
*
* @return YES : 只發送連接上的用戶
*/
- (BOOL)browserViewController:(MCBrowserViewController *)browserViewController
shouldPresentNearbyPeer:(MCPeerID *)peerID
withDiscoveryInfo:(nullable NSDictionary<NSString *, NSString *> *)info
{
self.peerID = peerID;
NSLog(@"info == %@ peer = %@",info, peerID);
return YES;
}
- 將圖片發送給連接上的ID
// 獲取圖片
UIImage *image = self.showImage.image;
// 將圖片轉換成NSData類型
NSData *data = UIImagePNGRepresentation(image);
/**
* 發送數據
* toPeers : 發給的設備ID的數組
* withMode: 發送模式,是否是安全模式
*/
if (self.peerID != nil) {
[self.mc_Session sendData:data toPeers:@[self.peerID] withMode:MCSessionSendDataUnreliable error:nil];
}
}
接收數據
- 實現MCSession的代理方法接受數據
- 在MCSeesion代理方法中設置獲取過來的數據
// 接收的數據
- (void)session:(MCSession *)session didReceiveData:(NSData *)data fromPeer:(MCPeerID *)peerID
{
UIImage *image = [[UIImage alloc]initWithData:data];
if(image != nil){
// 設置數據
dispatch_async(dispatch_get_main_queue(), ^{
self.showImage.image = image;
});
}
}
三、CoreBlueTooth
簡介:
- 可用於第三方藍牙設備交互,設備必須支持藍牙4.0
- iPhone的設備必須是4S或者更新
- iPad設備必須是iPad mini或者更新
- iOS的系統必須是iOS 6或者更新
- 藍牙4.0以
低功耗
著稱,所以一般被稱爲BLE(bluetooth low energy) - 應用場景
- 運動手環
- 智能家居
- 拉卡拉藍牙刷卡器
核心概念
- CBCentralManager:中心設備(用來連接到外部設備的管家)
- CBPeripheralManager:外部設備(第三方的藍牙4.0設備)
開發步驟
- 建立中心管家
// 1. 創建中心管家,並且設置代理
self.cmgr = [[CBCentralManager alloc]initWithDelegate:self queue:nil];
- 掃描外設(discover)
// 2. 在代理方法中掃描外部設備
/**
* scanForPeripheralsWithServices :如果傳入指定的數組,那麼就只會掃描數組中對應ID的設備
* 如果傳入nil,那麼就是掃描所有可以發現的設備
* 掃描完外部設備就會通知CBCentralManager的代理
*/
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
if ([central state] == CBCentralManagerStatePoweredOn) {
[self.cmgr scanForPeripheralsWithServices:nil options:nil];
}
}
/**
* 發現外部設備,每發現一個就會調用這個方法
* 所以可以使用一個數組來存儲每次掃描完成的數組
*/
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *,id> *)advertisementData RSSI:(NSNumber *)RSSI
{
// 有可能會導致重複添加掃描到的外設
// 所以需要先判斷數組中是否包含這個外設
if(![self.peripherals containsObject:peripheral]){
[self.peripherals addObject:peripheral];
}
}
- 連接外設
/**
* 模擬開始連接方法
*/
- (void)start
{
// 3. 連接外設
for (CBPeripheral *ppl in self.peripherals) {
// 掃描外設的服務
// 這個操作應該交給外設的代理方法來做
// 設置代理
ppl.delegate = self;
[self.cmgr connectPeripheral:ppl options:nil];
}
}
- 掃描外設中的服務和特徵
- 服務和特徵的關係
每個藍牙4.0的設備都是通過服務和特徵來展示自己的,一個設備必然包含一個或多個服務,每個服務下面又包含若干個特徵。
/**
* 連接外設成功調用
*/
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
{
// 查找外設服務
[peripheral discoverServices:nil];
}
/**
* 發現服務就會調用代理方法
*
* @param peripheral 外設
*/
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
{
// 掃描到設備的所有服務
NSArray *services = peripheral.services;
// 根據服務再次掃描每個服務對應的特徵
for (CBService *ses in services) {
[peripheral discoverCharacteristics:nil forService:ses];
}
}
- 與外設做數據交互
- 在指定的特徵下做相應的操作
/**
* 發現服務對應的特徵
*/
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
{
// 服務對應的特徵
NSArray *ctcs = service.characteristics;
// 遍歷所有的特徵
for (CBCharacteristic *character in ctcs) {
// 根據特徵的唯一標示過濾
if ([character.UUID.UUIDString isEqualToString:@"XMG"]) {
NSLog(@"可以吃飯了");
}
}
}
- 斷開連接
/**
* 斷開連接
*/
- (void)stop
{
// 斷開所有連接上的外設
for (CBPeripheral *per in self.peripherals) {
[self.cmgr cancelPeripheralConnection:per];
}
}