iOS開發拓展篇—藍牙之mutipeerConnectivity的使用

藍牙

mutipeerConnectivity

簡介

* iOS 7引入的一個全新框架

* 多點鏈接

* 替代GameKit框架

* 多用於文件的傳輸

* iOS設備不聯網也能跟附近的人聊天

* FireChat
* See You Around
* 以上近場聊天App都是基於mutipeerConnectivity框架

* 搜索和傳輸的方式

* 雙方WIFI和藍牙都沒有打開:沒法實現
* 雙方都開啓藍牙:經過藍牙發現和傳輸
* 雙方都開啓WIFI:經過WIFI Direct發現和傳輸,速度接近AirDrop
* 雙方同時開啓了WIFI和藍牙:模擬AirDrop,經過低功耗藍牙技術掃描發現握手,而後經過WIFI Direct傳輸

案例界面搭建

開發思路步驟

1. 註冊一個廣播           告訴別人    個人設備是能夠被發現
2. 掃描藍牙設備           須要實現代理方法
3. 使用一個MCSession對象  存儲當前會話  須要實現代理方法
4. 使用MCSession對象     發送和接收數據

鏈接設備

  • 建立MCSession對象用於存放當前鏈接的會話
// 建立MCSession對象
// initWithPeer:設備的ID
// 用於存放當前的鏈接的會話
self.mc_Session = [ [MCSession alloc] initWithPeer:[[MCPeerID alloc] initWithDisplayName:[UIDevice currentDevice].name]];
  • 開啓廣播對象,通知正在搜索的設備他們是可用的
#define SERVICE_TYPE @"SLZeng"

/**
 *   只要開啓了可被搜索的廣播,那麼鏈接藍牙按鈕就不可點
 */
- (IBAction)foundConnect:(id)sender {
    UISwitch *switchBtn = (UISwitch *)sender;
    if (switchBtn.isOn) {
        // 廣播對象,告訴其它的設備他們是可用的
        if (self.advertiserAssistant == nil) {
            // 建立廣播對象
            // initWithServiceType: 廣播類型的標示(由於廣播可能比較多,因此最好每一個廣播綁定一個惟一標示)
            // session:當前會話
            // discoveryInfo: 廣播信息
            self.advertiserAssistant = [[MCAdvertiserAssistant alloc] initWithServiceType:SERVICE_TYPE discoveryInfo:nil session:self.mc_Session];
        }
        // 開啓廣播
        [self.advertiserAssistant start];
        self.connectBT.enabled = NO;
    }else{
        self.connectBT.enabled = YES;
    }
    
}
  • 開始搜索藍牙設備
- (IBAction)connectBlueTooth {
    // 建立搜索藍牙設備控制器
    MCBrowserViewController *mbVC = [[MCBrowserViewController alloc] initWithServiceType:SERVICE_TYPE session:self.mc_Session];
    // 設置控制器代理
    mbVC.delegate = self;
    // 跳轉到搜索控制器
    [self presentViewController:mbVC animated:YES completion:nil];
}

選擇數據

- (IBAction)selectImage {
    // 1. 建立圖片選擇器
    UIImagePickerController *imgPicker = [[UIImagePickerController alloc] init];
    // 2. 判斷圖片選擇器是否可用
    if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeSavedPhotosAlbum]) {
        // 選擇器打開的類型
        imgPicker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
        // 設置代理
        imgPicker.delegate = self;
        // 打開圖片選擇器
        [self presentViewController:imgPicker animated:YES completion:nil];
    }
}
  • 圖片選擇器代理中獲取數據
// 選擇完畢調用
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info
{
//    NSLog(@"info == %@",info);
    // 設置顯示圖片
    self.showImage.image = info[UIImagePickerControllerOriginalImage];
    // 隱藏圖片顯示器
    [picker dismissViewControllerAnimated:YES completion:nil];
}
  • 在搜索控制器的鏈接完成的代理方法中隱藏搜索控制器
/**
 *  鏈接完成
 *
 *  @param browserViewController 搜索控制器
 */
- (void)browserViewControllerDidFinish:(MCBrowserViewController *)browserViewController
{
    [browserViewController dismissViewControllerAnimated:YES completion:nil];
    NSLog(@"%s %d",__func__,__LINE__);
}

發送數據

  • 實現搜索控制器的代理方法,獲取鏈接上的設備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
- (IBAction)sendImage {

    // 判斷是否有圖片
    if (!self.showImage.image) return;
    
    // 獲取圖片
    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的代理方法接受數據
- (void)session:(MCSession *)session didReceiveData:(NSData *)data fromPeer:(MCPeerID *)peerID
{
    NSLog(@"%s %d",__func__, __LINE__);
    NSLog(@"data = %@, peer = %@", data, peerID);
}

顯示數據

  • 在MCSeesion代理方法中設置獲取過來的數據
/**
 *  接收到數據的時候調用
 *
 *  @param session 會話
 *  @param data    數據
 *  @param peerID  設備的ID
 */
- (void)session:(MCSession *)session didReceiveData:(NSData *)data fromPeer:(MCPeerID *)peerID
{
    NSLog(@"%s %d",__func__,__LINE__);
//    NSLog(@"data = %@ , peer = %@",data,peerID);
    UIImage *image = [[UIImage alloc] initWithData:data];
    if(image != nil){
        // 設置數據
        dispatch_async(dispatch_get_main_queue(), ^{
            self.showImage.image = image;
        });
    }
}
  • 只要設置MCSeesion代理,必須實現的代理方法,否則報錯。
/**
 *  會話狀態發生改變的時候調用
 *
 *  @param session 會話
 *  @param peerID  設備的ID
 *  @param state   狀態
 */
- (void)session:(MCSession *)session peer:(MCPeerID *)peerID didChangeState:(MCSessionState)state
{
    NSLog(@"%s  %d",__func__,__LINE__);
}
相關文章
相關標籤/搜索