ios開發之藍芽4.0技術
前言
前端時間,同學在做專案過程中遇到關於藍芽方面的問題,今天我就給大家進行詳細的進行講解下藍芽在iOS開發中的具體實現.在介紹藍芽前,大家要搞清楚什麼是藍芽?
什麼是藍芽?
隨著藍芽低功耗技術BLE(Bluetooth Low Energy)的發展,藍芽技術正在一步步成熟,如今的大部分移動裝置都配備有藍芽4.0,相比之前的藍芽技術耗電量大大降低。從iOS的發展史也不難看出蘋果目前對藍芽技術也是越來越關注,例如蘋果於2013年9月釋出的iOS7就配備了iBeacon技術,這項技術完全基於藍芽傳輸。但是眾所周知蘋果的裝置對於許可權要求也是比較高的,因此在iOS中並不能像Android
藍芽在開發中的框架有哪些?
- GameKit.framework:iOS7之前的藍芽通訊框架,從iOS7開始過期,但是目前多數應用還是基於此框架。
- MultipeerConnectivity.framework:iOS7開始引入的新的藍芽通訊開發框架,用於取代GameKit。
- CoreBluetooth.framework:功能強大的藍芽開發框架,要求裝置必須支援藍芽4.0。
藍芽在開發中的框架優缺點?
現在就給大家來總結下這三種框架的優缺點.
前兩個框架使用起來比較簡單,但是缺點也比較明顯:僅僅支援iOS裝置,傳輸內容僅限於沙盒或者照片庫中使用者選擇的檔案,並且第一個框架只能在同一個應用之間進行傳輸(一個iOS裝置安裝應用A,另一個iOS裝置上安裝應用B是無法傳輸的)。當然CoreBluetooth就擺脫了這些束縛,它不再侷限於iOS裝置之間進行傳輸,你可以通過iOS裝置向
藍芽框架之GameKit框架
其實從名稱來看這個框架並不是專門為了支援藍芽傳輸而設計的,它是為遊戲設計的。而很多遊戲中會用到基於藍芽的點對點資訊傳輸,因此這個框架中集成了藍芽傳輸模組。前面也說了這個框架本身有很多限制,但是在iOS7之前的很多藍芽傳輸都是基於此框架的,所以有必要對它進行了解。GameKit中的藍芽使用設計很簡單,並沒有給開發者留有太多的複雜介面,而多數連線細節開發者是不需要關注的。GameKit中提供了兩個關鍵類來操作藍芽連線:
GKPeerPickerController:藍芽查詢、連線用的檢視控制器,通常情況下應用程式A開啟後會呼叫此控制器的show方法來展示一個藍芽查詢的檢視,一旦發現了另一個同樣在查詢藍芽連線的客戶客戶端B就會出現在檢視列表中,此時如果使用者點選連線B,B客戶端就會詢問使用者是否允許A連線B,如果允許後A和B之間建立一個藍芽連線。
GKSession:連線會話,主要用於傳送和接受傳輸資料。一旦A和B建立連線GKPeerPickerController的代理方法會將A、B兩者建立的會話(GKSession)物件傳遞給開發人員,開發人員拿到此物件可以傳送和接收資料。
其實理解了上面兩個類之後,使用起來就比較簡單了,下面就以一個圖片傳送程式來演示GameKit中藍芽的使用。此程式一個客戶端執行在模擬器上作為客戶端A,另一個執行在iPhone真機上作為客戶端B(注意A、B必須運行同一個程式,GameKit藍芽開發是不支援兩個不同的應用傳輸資料的)。兩個程式執行之後均呼叫GKPeerPickerController來發現周圍藍芽裝置,一旦A發現了B之後就開始連線B,然後iOS會詢問使用者是否接受連線,一旦接受之後就會呼叫GKPeerPickerController的-(void)peerPickerController:(GKPeerPickerController )picker
didConnectPeer:(NSString )peerID toSession:(GKSession *)session代理方法,在此方法中可以獲得連線的裝置id(peerID)和連線會話(session);此時可以設定會話的資料接收控制代碼(相當於一個代理)並儲存會話以便傳送資料時使用;一旦一端(假設是A)呼叫會話的sendDataToAllPeers: withDataMode: error:方法傳送資料,此時另一端(假設是B)就會呼叫控制代碼的
- (void) receiveData:(NSData )data fromPeer:(NSString )peer inSession: (GKSession )session context:(void )context方法,在此方法可以獲得傳送資料並處理。下面是程式程式碼:
<code class="hljs objectivec has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#import <span class="hljs-title" style="box-sizing: border-box;">"ViewController.h"</span></span> <span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#import <span class="hljs-title" style="box-sizing: border-box;"><GameKit/GameKit.h></span></span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">@interface</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">ViewController</span> ()<<span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">GKPeerPickerControllerDelegate</span>,<span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">UIImagePickerControllerDelegate</span>,<span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">UINavigationBarDelegate</span>></span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">@property</span> (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">weak</span>, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">nonatomic</span>) <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">IBOutlet</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">UIImageView</span> *imageView;<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//照片顯示檢視</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">@property</span> (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">strong</span>,<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">nonatomic</span>) GKSession *session;<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//藍芽連線會話</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">@end</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">@implementation</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">ViewController</span></span> <span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#pragma mark - 控制器檢視方法</span> - (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span>)viewDidLoad { [<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">super</span> viewDidLoad]; GKPeerPickerController *pearPickerController=[[GKPeerPickerController alloc]init]; pearPickerController<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.delegate</span>=<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span>; [pearPickerController show]; } <span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#pragma mark - UI事件</span> - (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">IBAction</span>)selectClick:(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">UIBarButtonItem</span> *)sender { UIImagePickerController *imagePickerController=[[UIImagePickerController alloc]init]; imagePickerController<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.delegate</span>=<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span>; [<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span> presentViewController:imagePickerController animated:<span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">YES</span> completion:<span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">nil</span>]; } - (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">IBAction</span>)sendClick:(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">UIBarButtonItem</span> *)sender { NSData *data=UIImagePNGRepresentation(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span><span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.imageView</span><span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.image</span>); <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSError</span> *error=<span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">nil</span>; [<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span><span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.session</span> sendDataToAllPeers:data withDataMode:GKSendDataReliable error:&error]; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (error) { <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSLog</span>(@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"傳送圖片過程中發生錯誤,錯誤資訊:%@"</span>,error<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.localizedDescription</span>); } } <span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#pragma mark - GKPeerPickerController代理方法</span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/** * 連線到某個裝置 * * @param picker 藍芽點對點連線控制器 * @param peerID 連線裝置藍芽傳輸ID * @param session 連線會話 */</span> -(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span>)peerPickerController:(GKPeerPickerController *)picker didConnectPeer:(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSString</span> *)peerID toSession:(GKSession *)session{ <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span><span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.session</span>=session; <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSLog</span>(@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"已連線客戶端裝置:%@."</span>,peerID); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//設定資料接收處理控制代碼,相當於代理,一旦資料接收完成呼叫它的-receiveData:fromPeer:inSession:context:方法處理資料</span> [<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span><span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.session</span> setDataReceiveHandler:<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span> withContext:<span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">nil</span>]; [picker dismiss];<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//一旦連線成功關閉視窗</span> } <span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#pragma mark - 藍芽資料接收方法</span> - (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span>) receiveData:(NSData *)data fromPeer:(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSString</span> *)peer inSession: (GKSession *)session context:(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> *)context{ <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">UIImage</span> *image=[<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">UIImage</span> imageWithData:data]; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span><span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.imageView</span><span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.image</span>=image; UIImageWriteToSavedPhotosAlbum(image, <span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">nil</span>, <span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">nil</span>, <span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">nil</span>); <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSLog</span>(@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"資料傳送成功!"</span>); } <span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#pragma mark - UIImagePickerController代理方法</span> -(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span>)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSDictionary</span> *)info{ <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span><span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.imageView</span><span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.image</span>=[info objectForKey:UIImagePickerControllerOriginalImage]; [<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span> dismissViewControllerAnimated:<span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">YES</span> completion:<span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">nil</span>]; } -(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span>)imagePickerControllerDidCancel:(UIImagePickerController *)picker{ [<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span> dismissViewControllerAnimated:<span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">YES</span> completion:<span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">nil</span>]; } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">@end</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li><li style="box-sizing: border-box; padding: 0px 5px;">62</li><li style="box-sizing: border-box; padding: 0px 5px;">63</li><li style="box-sizing: border-box; padding: 0px 5px;">64</li><li style="box-sizing: border-box; padding: 0px 5px;">65</li><li style="box-sizing: border-box; padding: 0px 5px;">66</li><li style="box-sizing: border-box; padding: 0px 5px;">67</li><li style="box-sizing: border-box; padding: 0px 5px;">68</li><li style="box-sizing: border-box; padding: 0px 5px;">69</li><li style="box-sizing: border-box; padding: 0px 5px;">70</li><li style="box-sizing: border-box; padding: 0px 5px;">71</li><li style="box-sizing: border-box; padding: 0px 5px;">72</li><li style="box-sizing: border-box; padding: 0px 5px;">73</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li><li style="box-sizing: border-box; padding: 0px 5px;">62</li><li style="box-sizing: border-box; padding: 0px 5px;">63</li><li style="box-sizing: border-box; padding: 0px 5px;">64</li><li style="box-sizing: border-box; padding: 0px 5px;">65</li><li style="box-sizing: border-box; padding: 0px 5px;">66</li><li style="box-sizing: border-box; padding: 0px 5px;">67</li><li style="box-sizing: border-box; padding: 0px 5px;">68</li><li style="box-sizing: border-box; padding: 0px 5px;">69</li><li style="box-sizing: border-box; padding: 0px 5px;">70</li><li style="box-sizing: border-box; padding: 0px 5px;">71</li><li style="box-sizing: border-box; padding: 0px 5px;">72</li><li style="box-sizing: border-box; padding: 0px 5px;">73</li></ul>
執行效果(左側是真機,右側是模擬器,程式演示了兩個客戶端互發圖片的場景:首先是模擬器傳送圖片給真機,然後真機發送圖片給模擬器)
藍芽框架之MultipeerConnectivity框架
前面已經說了GameKit相關的藍芽操作類從iOS7已經全部過期,蘋果官方推薦使用MultipeerConnectivity代替。但是應該瞭解,MultipeerConnectivity.framework並不僅僅支援藍芽連線,準確的說它是一種支援Wi-Fi網路、P2P Wi-Fi已經藍芽個人區域網的通訊框架,它遮蔽了具體的連線技術,讓開發人員有統一的介面程式設計方法。通過MultipeerConnectivity連線的節點之間可以安全的傳遞資訊、流或者其他檔案資源而不必通過網路服務。此外使用MultipeerConnectivity進行近場通訊也不再侷限於同一個應用之間傳輸,而是可以在不同的應用之間進行資料傳輸(當然如果有必要的話你仍然可以選擇在一個應用程式之間傳輸)。
要了解MultipeerConnectivity的使用必須要清楚一個概念:廣播(Advertisting)和發現(Disconvering),這很類似於一種Client-Server模式。假設有兩臺裝置A、B,B作為廣播去傳送自身服務,A作為發現的客戶端。一旦A發現了B就試圖建立連線,經過B同意二者建立連線就可以相互發送資料。在使用GameKit框架時,A和B既作為廣播又作為發現,當然這種情況在MultipeerConnectivity中也很常見。
A.廣播
無論是作為伺服器端去廣播還是作為客戶端去發現廣播服務,那麼兩個(或更多)不同的裝置之間必須要有區分,通常情況下使用MCPeerID物件來區分一臺裝置,在這個裝置中可以指定顯示給對方檢視的名稱(display name)。另外不管是哪一方,還必須建立一個會話MCSession用於傳送和接受資料。通常情況下會在會話的-(void)session:(MCSession )session peer:(MCPeerID )peerID didChangeState:(MCSessionState)state代理方法中跟蹤會話狀態(已連線、正在連線、未連線);在會話的-(void)session:(MCSession )session didReceiveData:(NSData )data fromPeer:(MCPeerID *)peerID代理方法中接收資料;同時還會呼叫會話的-(void)sendData: toPeers:withMode: error:方法去傳送資料。
廣播作為一個伺服器去釋出自身服務,供周邊裝置發現連線。在MultipeerConnectivity中使用MCAdvertiserAssistant來表示一個廣播,通常建立廣播時指定一個會話MCSession物件將廣播服務和會話關聯起來。一旦呼叫廣播的start方法周邊的裝置就可以發現該廣播並可以連線到此服務。在MCSession的代理方法中可以隨時更新連線狀態,一旦建立了連線之後就可以通過MCSession的connectedPeers獲得已經連線的裝置。
B.發現
前面已經說過作為發現的客戶端同樣需要一個MCPeerID來標誌一個客戶端,同時會擁有一個MCSession來監聽連線狀態併發送、接受資料。除此之外,要發現廣播服務,客戶端就必須要隨時查詢服務來連線,在MultipeerConnectivity中提供了一個控制器MCBrowserViewController來展示可連線和已連線的裝置(這類似於GameKit中的GKPeerPickerController),當然如果想要自己定製一個介面來展示裝置連線的情況你可以選擇自己開發一套UI介面。一旦通過MCBroserViewController選擇一個節點去連線,那麼作為廣播的節點就會收到通知,詢問使用者是否允許連線。由於初始化MCBrowserViewController的過程已經指定了會話MCSession,所以連線過程中會隨時更新會話狀態,一旦建立了連線,就可以通過會話的connected屬性獲得已連線裝置並且可以使用會話傳送、接受資料。
下面用兩個不同的應用程式來演示使用MultipeerConnectivity的使用過程,其中一個應用執行在模擬器中作為廣播節點,另一個執行在iPhone真機上作為發現節點,並且實現兩個節點的圖片互傳。
首先看一下作為廣播節點的程式:
介面:
點選“開始廣播”來發布服務,一旦有節點連線此服務就可以使用“選擇照片”來從照片庫中選取一張圖片併發送到所有已連線節點。
程式:
<code class="hljs objectivec has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#import <span class="hljs-title" style="box-sizing: border-box;">"ViewController.h"</span></span> <span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#import <span class="hljs-title" style="box-sizing: border-box;"><MultipeerConnectivity/MultipeerConnectivity.h></span></span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">@interface</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">ViewController</span> ()<<span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">MCSessionDelegate</span>,<span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">MCAdvertiserAssistantDelegate</span>, <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">UIImagePickerControllerDelegate</span>,<span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">UINavigationControllerDelegate</span>></span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">@property</span> (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">strong</span>,<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">nonatomic</span>) MCSession *session; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">@property</span> (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">strong</span>,<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">nonatomic</span>) MCAdvertiserAssistant *advertiserAssistant; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">@property</span> (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">strong</span>,<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">nonatomic</span>) UIImagePickerController *imagePickerController; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">@property</span> (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">weak</span>, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">nonatomic</span>) <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">IBOutlet</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">UIImageView</span> *photo; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">@end</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">@implementation</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">ViewController</span></span> <span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#pragma mark - 控制器檢視事件</span> - (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span>)viewDidLoad { [<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">super</span> viewDidLoad]; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//建立節點,displayName是用於提供給周邊裝置檢視和區分此服務的</span> MCPeerID *peerID=[[MCPeerID alloc]initWithDisplayName:@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"KenshinCui_Advertiser"</span>]; _session=[[MCSession alloc]initWithPeer:peerID]; _session<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.delegate</span>=<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span>; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//建立廣播</span> _advertiserAssistant=[[MCAdvertiserAssistant alloc]initWithServiceType:@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"cmj-stream"</span> discoveryInfo:<span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">nil</span> session:_session]; _advertiserAssistant<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.delegate</span>=<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span>; } <span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#pragma mark - UI事件</span> - (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">IBAction</span>)advertiserClick:(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">UIBarButtonItem</span> *)sender { <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//開始廣播</span> [<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span><span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.advertiserAssistant</span> start]; } - (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">IBAction</span>)selectClick:(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">UIBarButtonItem</span> *)sender { _imagePickerController=[[UIImagePickerController alloc]init]; _imagePickerController<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.delegate</span>=<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span>; [<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span> presentViewController:_imagePickerController animated:<span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">YES</span> completion:<span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">nil</span>]; } <span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#pragma mark - MCSession代理方法</span> -(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span>)session:(MCSession *)session peer:(MCPeerID *)peerID didChangeState:(MCSessionState)state{ <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSLog</span>(@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"didChangeState"</span>); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">switch</span> (state) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">case</span> MCSessionStateConnected: <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSLog</span>(@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"連線成功."</span>); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">break</span>; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">case</span> MCSessionStateConnecting: <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSLog</span>(@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"正在連線..."</span>); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">break</span>; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">default</span>: <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSLog</span>(@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"連線失敗."</span>); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">break</span>; } } <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//接收資料</span> -(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span>)session:(MCSession *)session didReceiveData:(NSData *)data fromPeer:(MCPeerID *)peerID{ <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSLog</span>(@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"開始接收資料..."</span>); <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">UIImage</span> *image=[<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">UIImage</span> imageWithData:data]; [<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span><span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.photo</span> setImage:image]; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//儲存到相簿</span> UIImageWriteToSavedPhotosAlbum(image, <span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">nil</span>, <span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">nil</span>, <span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">nil</span>); } <span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#pragma mark - MCAdvertiserAssistant代理方法</span> <span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#pragma mark - UIImagePickerController代理方法</span> -(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span>)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSDictionary</span> *)info{ <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">UIImage</span> *image=[info objectForKey:UIImagePickerControllerOriginalImage]; [<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span><span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.photo</span> setImage:image]; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//傳送資料給所有已連線裝置</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSError</span> *error=<span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">nil</span>; [<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span><span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.session</span> sendData:UIImagePNGRepresentation(image) toPeers:[<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span><span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.session</span> connectedPeers] withMode:MCSessionSendDataUnreliable error:&error]; <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSLog</span>(@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"開始傳送資料..."</span>); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (error) { <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSLog</span>(@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"傳送資料過程中發生錯誤,錯誤資訊:%@"</span>,error<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.localizedDescription</span>); } [<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span><span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.imagePickerController</span> dismissViewControllerAnimated:<span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">YES</span> completion:<span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">nil</span>]; } -(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span>)imagePickerControllerDidCancel:(UIImagePickerController *)picker{ [<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span><span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.imagePickerController</span> dismissViewControllerAnimated:<span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">YES</span> completion:<span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">nil</span>]; } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">@end</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li><li style="box-sizing: border-box; padding: 0px 5px;">62</li><li style="box-sizing: border-box; padding: 0px 5px;">63</li><li style="box-sizing: border-box; padding: 0px 5px;">64</li><li style="box-sizing: border-box; padding: 0px 5px;">65</li><li style="box-sizing: border-box; padding: 0px 5px;">66</li><li style="box-sizing: border-box; padding: 0px 5px;">67</li><li style="box-sizing: border-box; padding: 0px 5px;">68</li><li style="box-sizing: border-box; padding: 0px 5px;">69</li><li style="box-sizing: border-box; padding: 0px 5px;">70</li><li style="box-sizing: border-box; padding: 0px 5px;">71</li><li style="box-sizing: border-box; padding: 0px 5px;">72</li><li style="box-sizing: border-box; padding: 0px 5px;">73</li><li style="box-sizing: border-box; padding: 0px 5px;">74</li><li style="box-sizing: border-box; padding: 0px 5px;">75</li><li style="box-sizing: border-box; padding: 0px 5px;">76</li><li style="box-sizing: border-box; padding: 0px 5px;">77</li><li style="box-sizing: border-box; padding: 0px 5px;">78</li><li style="box-sizing: border-box; padding: 0px 5px;">79</li><li style="box-sizing: border-box; padding: 0px 5px;">80</li><li style="box-sizing: border-box; padding: 0px 5px;">81</li><li style="box-sizing: border-box; padding: 0px 5px;">82</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li><li style="box-sizing: b
相關推薦
iOS開發之藍芽4.0技術完美實現
前言 前端時間,同學在做專案過程中遇到關於藍芽方面的問題,今天我就給大家進行詳細的進行講解下藍芽在iOS開發中的具體實現.在介紹藍芽前,大家要搞清楚什麼是藍芽? 什麼是藍芽? 隨著藍芽低功耗技術BLE(Bluetooth Low Energy)的發展,
ios開發之藍芽4.0技術
前言 前端時間,同學在做專案過程中遇到關於藍芽方面的問題,今天我就給大家進行詳細的進行講解下藍芽在iOS開發中的具體實現.在介紹藍芽前,大家要搞清楚什麼是藍芽? 什麼是藍芽? 隨著藍芽低功耗技術BLE(Bluetooth Low Energy)的發展
iOS開發 藍芽4.0的各種親身經歷踩過得坑
1.首先建立這個三個引數 @property (nonatomic,strong)CBCentralManager * manager; @property (nonatomic,strong)CBPeripheral * peripheral;
BlueTooth 藍芽與藍芽4 0技術細節
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!  
BlueTooth 藍芽與藍芽4 0技術細節
雖然藍芽(Bluetooth)3.0都還尚未完全普及,Bluetooth SIG(藍芽技術聯盟,Bluetooth Special InterestGroup,後文簡稱BluetoothSIG)卻又再次推出了藍芽4.0規範,並表示這又是藍芽發展史上一次重大的革新。值藍芽4.0推出之時,我們特地採訪了Blu
iOS開發 之 可穿戴裝置 藍芽4.0 BLE 開發
1 前言 當前有越來越多的可穿戴裝置使用了藍芽4.0 BLE(Bluetooth Low Energy)。對於iOS開發而言,Apple之前專門推出CoreBluetooth的Framework來支援BLE的開發。對於硬體開發有了解的朋友應該知道,在之前使用低
Android藍芽開發之低功耗藍芽(藍芽4.0)開發全記錄
主要內容概況 前面我記錄了開發藍芽2.0的過程,今天準備介紹現在的主流藍芽技術,藍芽4.0的開發,該藍芽技術是在Android4.3(API級別18)版本引入的API。 官方文件 具體的區別主要以下幾點: 1.新的藍芽技術提供了連線服務的方法,以前是沒有提供連線藍芽的方法
iOS藍芽開發(二):iOS 藍芽4.0中心模式 程式碼實現
上一篇簡單介紹了藍芽的部分基礎知識,詳細的東西大家可以去github上搜babyBluetooth,裡面有一些學習資料 iOS連線外設的流程 建立中心管理者 掃描外設 discoverPeripheral 連線外設 connectPeripheral
Android BLE藍芽4.0開發—Android手機與BLE終端通訊
轉載自: https://blog.csdn.net/fu908323236/article/details/76208997 這篇部落格主要講解AndroidBLE藍芽4.0的基本概念,以及基礎用法。 BLE 即 Bluetooth Low Energy,藍芽低功耗技術,是藍芽
iOS藍芽4.0協議簡單介紹
iOS開發藍芽4.0的框架是CoreBluetooth,本文主要介紹CoreBluetooth的使用,關於本文中的程式碼片段大多來自github上的一個demo,地址是myz1104/Bluetooth。 在CoreBluetooth中有兩個主要的部分,Central和Peripher
Android 藍芽4.0(ble)開發的解決方案
最近,隨著智慧穿戴式裝置、智慧醫療以及智慧家居的普及,藍芽開發在移動開中顯得非常的重要。由於公司需要,研究了一下,藍芽4.0在Android中的應用。以下是我的一些總結。 1.先介紹一下關於藍芽4.0中的一些名詞吧:
IOS藍芽4.0與讀卡器通訊
IOS學習也一段時間了,該上點乾貨了。前段時間研究了一下IOS藍芽通訊相關的東西,把研究的一個成果給大家分享一下。 一 專案背景 簡單介紹一下做的東西,裝置是一個金融刷卡器,通過藍芽與iphone手機通訊。手機端的app通過傳送不同的指令(通過藍芽)控制刷卡器執行一些動作
android 藍芽4.0(BLE)開發
最近剛好專案需要手機與藍芽模組通訊,基於藍芽4.0,網上資料較少也有些小坑,故作一下總結。 關鍵術語和概念 藍芽有傳統藍芽(3.0以下)和低功耗藍芽(BLE,又稱藍芽4.0)之分,而藍芽4.0開發需要android4.3版本(API 18)及以上才支援
ANDROID藍芽4.0開發_藍芽開發例項原始碼下載
一個整合目前主流藍芽的demo、android藍芽4.0開發、專案中使用到了搜尋BLE終端和讀寫BLE終端、另外還有在程式裡面開房藍芽、在Demo裡面還處理了收到BLE終端資料互動的事件、程式碼裡都有中文註釋、要讀性應該非常好的、應該會對開發有一定幫助、有興趣的哥們可以下
電子產品開發之藍芽耳機收納盒控制微控制器晶片
今日分享一款電子產品—藍芽耳機收納盒及藍芽耳機收納盒控制微控制器晶片。使用藍芽耳機的各位肯定都是曉得藍芽耳機收納盒的。大部分藍芽耳機都會隨機配備一款與之匹配的充電盒,充電盒能為其提供電力以及收納存放的功能。 藍芽耳機充電很多事使用Micro USB充電,充電口附近會有充電指示燈。拿出耳機
Hollong 低功耗藍芽4.0/4.1/4.2 BLE Sniffer協議分析儀
名稱:緯圖Hollong BLE藍芽 監控分析儀 品牌:ViewTool/緯圖 型號:VTH201A 典型應用: - 抓取BLE藍芽傳輸資料,分析資料傳輸協議; - 實時捕獲、顯示、分析、過濾協議資料,減少除錯時間,加速產品進入市場; - 協助開發除錯BLE相關
Hollong 藍芽4.0/4.1/4.2 BLE協議監控分析儀
品牌:ViewTool/緯圖型號:VTH201A 典型應用: - 抓取BLE藍芽傳輸資料,分析資料傳輸協議; - 協助開發除錯BLE相關軟體,韌體; - 實時捕獲、顯示、解析、過濾和偵測協議錯誤,減少除錯時間,加速產品進入市場; - 幫助學習BLE藍芽傳輸協議; &nb
藍芽4.0 BLE SimpleBLEPeripheral_新增新CHAR值及UUID
UUID, 就是用來唯一識別一個特徵值的ID. handle,就是對應的attribute 的一個控制代碼。 所有對特徵值的操作,都是通過對UUID 的搜尋得到對應的handle之後,通過handle來操作
藍芽4.0 BLE 資料傳輸 (二)
轉載自: https://blog.csdn.net/rfidunion/article/details/79711055 在第一部分我們瞭解了幾個專業詞彙,接下來我們再瞭解一下資料的傳送 一、資料傳送 在BLE協議棧中進行資料傳送分為兩個方面,一個事GATT的cl
藍芽4.0 BLE 資料傳輸 (一)
原文地址:http://blog.sina.com.cn/s/blog_869234dc0102uxl3.html 在這之前我們得先了解一下一些專業詞彙: 1、profile profile可以理解為一種規範,一個標準的通訊協議,它存在於從機中。 藍芽組織規