iOS--React Native 系統(tǒng)藍牙插件

一:介紹

React Native (簡稱RN)是Facebook于2015年4月開源的跨平臺移動應用開發(fā)框架旧巾,是Facebook早先開源的JS框架 React 在原生移動應用平臺的衍生產(chǎn)物幻林,目前支持iOS和安卓兩大平臺。RN使用Javascript語言智亮,類似于HTML的JSX克懊,以及CSS來開發(fā)移動應用洋丐,因此熟悉Web前端開發(fā)的技術(shù)人員只需很少的學習就可以進入移動應用開發(fā)領(lǐng)域豪诲。

在React Native移動平臺項目開發(fā)中,除了React Native 提供的封裝好的部分插件和原聲組建外达椰,在實際的項目中還需要使用到很多其他的插件翰蠢,比如網(wǎng)絡(luò)請求、數(shù)據(jù)庫啰劲、相機梁沧、相冊、通訊錄蝇裤、視頻播放器廷支、瀏覽器、藍牙連接栓辜、圖片處理恋拍、消息推送、地圖藕甩、統(tǒng)計施敢、埋點等等APP開發(fā)中需要用到的功能,都為IDE開發(fā)平臺提供封裝好的插件辛萍,以便項目開發(fā)使用悯姊。

另外羡藐,這些博文都是來源于我日常開發(fā)中的技術(shù)總結(jié)贩毕,在時間允許的情況下,我會針對技術(shù)點分別分享iOS仆嗦、Android兩個版本辉阶,如果有其他技術(shù)點需要,可在文章后留言瘩扼,我會盡全力幫助大家谆甜。這篇文章重點介紹系統(tǒng)藍牙插件的開發(fā)與使用

二:實現(xiàn)思路分析

系統(tǒng)藍牙插件是通過調(diào)用系統(tǒng) CoreBluetooth 藍牙庫實現(xiàn)藍牙掃描、連接集绰、發(fā)送數(shù)據(jù)等功能规辱。并通過 BlueToothPlugin 類開放 BlueToothPlugin 接口提供給 H5頁面端調(diào)用。

具體的實現(xiàn)思路如下:

  1. 新建 BlueToothPlugin 類栽燕,實現(xiàn) RCTBridgeModule 協(xié)議

  2. 添加 RCT_EXPORT_MODULE() 宏

  3. 添加 React Native 跟控制器

  4. 聲明被 JavaScript 調(diào)用的藍牙初始化方法

  5. 聲明被 JavaScript 調(diào)用的發(fā)送藍牙數(shù)據(jù)方法

  6. 聲明被 JavaScript 調(diào)用的斷開藍牙連接方法

  7. 實現(xiàn)判斷藍牙狀態(tài)代理方法

  8. 實現(xiàn)藍牙外設(shè)發(fā)現(xiàn)代理方法

  9. 實現(xiàn)外設(shè)服務(wù)特征的代理方法

  10. 實現(xiàn)寫入藍牙數(shù)據(jù)后回調(diào)的代理方法

  11. Javascript調(diào)用瀏覽器方法

三:實現(xiàn)源碼分析

實現(xiàn)源碼分析是根據(jù)上面列出的具體實現(xiàn)思路來為大家解刨內(nèi)部的實現(xiàn)流程及核心代碼分析罕袋。

1. 新建 BlueToothPlugin 類改淑,實現(xiàn) RCTBridgeModule 協(xié)議

新建繼承 NSObject 的 BlueToothPlugin 類,并實現(xiàn) RCTBridgeModule 協(xié)議

// BlueToothPlugin.h
#import <Foundation/Foundation.h>
#import <React/RCTBridgeModule.h>
#import "RCTEventEmitter.h"
#import <CoreBluetooth/CoreBluetooth.h>
@interface BlueToothPlugin : RCTEventEmitter<RCTBridgeModule,CBCentralManagerDelegate, CBPeripheralDelegate>
@end

2. 添加 RCT_EXPORT_MODULE() 宏

為了實現(xiàn) RCTBridgeModule 協(xié)議浴讯,BlueToothPlugin 的類需要包含RCT_EXPORT_MODULE() 宏朵夏。
并在這個宏里面添加一個參數(shù)“ BlueToothPlugin”用來指定在 JavaScript 中訪問這個模塊的名字。
如果你不指定榆纽,默認就會使用這個 Objective-C 類的名字仰猖。
如果類名以 RCT 開頭,則 JavaScript 端引入的模塊名會自動移除這個前綴奈籽。

// BlueToothPlugin.m
#import "BlueToothPlugin.h"
@implementation BlueToothPlugin
RCT_EXPORT_MODULE(BlueToothPlugin);
@end

3. 添加React Native跟控制器

如果不添加React Native跟控制器饥侵,view將不能正常顯示出來,實現(xiàn)方法如下:

// BlueToothPlugin.m
#import <React/RCTUtils.h>

引入<React/RCTUtils.h>之后衣屏,在視圖初始化或者顯示的時候爆捞,按照如下方法調(diào)用即可

UIViewController *vc = RCTPresentedViewController();

4. 聲明被 JavaScript 調(diào)用的藍牙初始化方法

藍牙初始化方法是對 CBCentralManager 的初始化以及代理調(diào)用線程設(shè)置,React Native需要明確的聲明要給 JavaScript 導出的方法勾拉,否則 React Native 不會導出任何方法煮甥。下面通過舉例來展示聲明的方法,通過RCT_EXPORT_METHOD()宏來實現(xiàn):

// ScanPlugin.m
#import "ScanPlugin.h"
#import <React/RCTUtils.h>
@implementation ScanPlugin
RCT_EXPORT_MODULE(ScanPlugin);

RCT_EXPORT_METHOD(initPeripheral:(NSDictionary *)arguments
                  withCompletionHandler:(RCTResponseSenderBlock)completion
                  failureHandler:(RCTResponseSenderBlock)failure)
{
    NSLog(@"調(diào)起藍牙初始化方法");
    self.cMgr = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
}
@end

5. 聲明被 JavaScript 調(diào)用的發(fā)送藍牙數(shù)據(jù)方法

發(fā)送藍牙數(shù)據(jù)方法是在獲取外設(shè)并連接成功之后調(diào)用藕赞,需要獲取寫入特征 characteristic成肘,需要發(fā)送的數(shù)據(jù),數(shù)據(jù)為 NSData 類型斧蜕。

核心源碼如下:

RCT_EXPORT_METHOD(sendData:(NSDictionary *)arguments
                  withCompletionHandler:(RCTResponseSenderBlock)completion
                  failureHandler:(RCTResponseSenderBlock)failure)
{
      NSLog(@"調(diào)起藍牙發(fā)送數(shù)據(jù)方法");
      NSData *data = [self p_dataWithString:arguments[@"data"]];
    if (self.characteristic) {
        [self.peripheral writeValue:data forCharacteristic:self.characteristic type:CBCharacteristicWriteWithResponse];
    }
}

6. 聲明被 JavaScript 調(diào)用的斷開藍牙連接方法

當連接的設(shè)備藍牙連接成功后如果想主動斷開連接双霍,需要調(diào)用 cancelPeripheralConnection 方法來實現(xiàn),傳參需要斷開設(shè)備的 peripheral 批销。
React Native需要明確的聲明要給 JavaScript 導出的方法洒闸,否則 React Native 不會導出任何方法。代碼如下:

RCT_EXPORT_METHOD(disconnectBlueTooth:(RCTResponseSenderBlock)completion
                  failureHandler:(RCTResponseSenderBlock)failure)
{
      NSLog(@"調(diào)起斷開藍牙連接方法");
      [self.cMgr cancelPeripheralConnection:self.peripheral];
}
7. 實現(xiàn)判斷藍牙狀態(tài)代理方法

藍牙狀態(tài)獲取需要通過實現(xiàn)代理均芽,在 CBCentralManager 初始化時會觸發(fā)代理方法丘逸,并且只有獲取到藍牙的狀態(tài)才可以進行藍牙連接,否則提前連接無效掀宋。
源碼如下:

- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
    switch (central.state) {
        case CBManagerStateUnknown:{
            NSLog(@"未知狀態(tài)");
        }
            break;
        case CBManagerStateResetting:
        {
            NSLog(@"重置狀態(tài)");
        }
            break;
        case CBManagerStateUnsupported:
        {
            NSLog(@"不支持的狀態(tài)");
        }
            break;
        case CBManagerStateUnauthorized:
        {
            NSLog(@"未授權(quán)的狀態(tài)");
        }
            break;
        case CBManagerStatePoweredOff:
        {
            NSLog(@"關(guān)閉狀態(tài)");
        }
            break;
        case CBManagerStatePoweredOn:
        {
            NSLog(@"開啟狀態(tài)-可用狀態(tài)");
            [self.centralManager scanForPeripheralsWithServices:nil options:nil];
        }
            break;
        default:
            break;
    }
}
8. 實現(xiàn)藍牙外設(shè)發(fā)現(xiàn)代理方法

在發(fā)起藍牙掃面之后深纲,如果掃面到設(shè)備會在 didDiscoverPeripheral 代理方法中回調(diào)相關(guān)設(shè)備數(shù)據(jù),其中包括劲妙,中心管理者 central湃鹊、外設(shè) peripheral、設(shè)備自定義數(shù)據(jù) advertisementData镣奋、RSSI 信號強度币呵。

核心源碼如下:

- (void)centralManager:(CBCentralManager *)central // 中心管理者
 didDiscoverPeripheral:(CBPeripheral *)peripheral // 外設(shè)
     advertisementData:(NSDictionary *)advertisementData // 外設(shè)攜帶的數(shù)據(jù)
                  RSSI:(NSNumber *)RSSI // 外設(shè)發(fā)出的藍牙信號強度
{
}
  1. 實現(xiàn)外設(shè)服務(wù)特征的代理方法

實現(xiàn)外設(shè)服務(wù)特征,這個是比較重要的方法侨颈,你在這里可以通過事先知道UUID找到你需要的特征余赢,訂閱特征掸驱,或者這里寫入數(shù)據(jù)給特征也可以。源碼如下:

- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
{
        // 遍歷所有的特征
    for (CBCharacteristic *characteristic in service.characteristics)
    {
        NSLog(@"特征值:%@",characteristic.UUID.UUIDString);
         }
}
  1. 實現(xiàn)寫入藍牙數(shù)據(jù)后回調(diào)的代理方法

在寫入數(shù)據(jù)成功之后没佑,會通過 didWriteValueForCharacteristic 方法回調(diào)告訴我們數(shù)據(jù)發(fā)送成功毕贼,可以在該方法中進行下一步操作。源碼如下:

- (void)peripheral:(CBPeripheral*)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{
}
11. Javascript調(diào)用瀏覽器方法

現(xiàn)在從 Javascript 里可以這樣調(diào)用這個方法:

import { NativeModules } from "react-native";
const BlueToothPlugin = NativeModules.BlueToothPlugin;
BlueToothPlugin.initPeripheral({"peripheralName": "", "peripheralServiceID": "", "peripheralCharacteristicID": ""}, (msg) => {
                                         Alert.alert(JSON.stringify(msg));

                                         },(err) => {
                                         Alert.alert(JSON.stringify(err));
                                         });
BlueToothPlugin.sendData({"data": ""}, (msg) => {
                                         Alert.alert(JSON.stringify(msg));

                                         },(err) => {
                                         Alert.alert(JSON.stringify(err));
                                         });
BlueToothPlugin.disconnectBlueTooth((msg) => {
                                         Alert.alert(JSON.stringify(msg));

                                         },(err) => {
                                         Alert.alert(JSON.stringify(err));
                                         });
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蛤奢,一起剝皮案震驚了整個濱河市鬼癣,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌啤贩,老刑警劉巖待秃,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異痹屹,居然都是意外死亡章郁,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進店門志衍,熙熙樓的掌柜王于貴愁眉苦臉地迎上來暖庄,“玉大人,你說我怎么就攤上這事楼肪∨嗬” “怎么了?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵春叫,是天一觀的道長肩钠。 經(jīng)常有香客問我,道長暂殖,這世上最難降的妖魔是什么价匠? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮呛每,結(jié)果婚禮上踩窖,老公的妹妹穿的比我還像新娘。我一直安慰自己莉给,他們只是感情好毙石,可當我...
    茶點故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布廉沮。 她就那樣靜靜地躺著颓遏,像睡著了一般。 火紅的嫁衣襯著肌膚如雪滞时。 梳的紋絲不亂的頭發(fā)上叁幢,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天,我揣著相機與錄音坪稽,去河邊找鬼曼玩。 笑死鳞骤,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的黍判。 我是一名探鬼主播豫尽,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼顷帖!你這毒婦竟也來了美旧?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤贬墩,失蹤者是張志新(化名)和其女友劉穎榴嗅,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體陶舞,經(jīng)...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡嗽测,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了肿孵。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片唠粥。...
    茶點故事閱讀 38,059評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖停做,靈堂內(nèi)的尸體忽然破棺而出厅贪,到底是詐尸還是另有隱情,我是刑警寧澤雅宾,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布养涮,位于F島的核電站,受9級特大地震影響眉抬,放射性物質(zhì)發(fā)生泄漏贯吓。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一蜀变、第九天 我趴在偏房一處隱蔽的房頂上張望悄谐。 院中可真熱鬧,春花似錦库北、人聲如沸爬舰。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽情屹。三九已至,卻和暖如春杂腰,著一層夾襖步出監(jiān)牢的瞬間垃你,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留惜颇,地道東北人皆刺。 一個月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像凌摄,于是被迫代替她去往敵國和親羡蛾。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,792評論 2 345