
相關資料:
1.http://blog.csdn.net/laorenshen/article/details/41149803
2.http://www.cnblogs.com/findumars/p/5149128.html
一、理清概念
1.藍牙設備:是指代有藍牙通信的手機、電腦、平板、打印機、耳機等。
2.設備名稱:是指設備打開藍牙功能后,在其他設備中顯示的名字,如圖1用的A、B、C等。
3.藍牙關態:如果A手機沒有打開藍牙功能,A手機是不能使用搜索的。就算A打開藍牙,其他的設備沒打開,A也是搜索不到的,如E。
4.服務名稱:每一個設備上打開藍牙時,都會提供不同的服務,服務的名稱是在其他設備上顯示的。
5.服務是從哪里來的?其實打開藍牙功能,只是設備開啟此功能,但沒有實際的應用功能。必須由某個程序或應用建立相關的服務,其他設備才能與此設備通信。
二、Delphi中提供了什么?
1.藍牙相關功能在System.Bluetooth.pas單元。
2.Bluetooth.pas提供的對像
TBluetoothManager:藍牙管理器。用於藍牙設備管理,包括發現藍牙設備,獲取配對設備,處理遠程配對請求等功能。
TBluetoothDeviceList:是藍牙設備列表。可以通過TBluetoothManager.GetPairedDevices獲得配對設備列表
TBluetoothAdapter:本機藍牙設備,實現配對、取消配對等功能,可通過
TBluetoothDevice:遠端藍牙設備,每個遠端設備可以提供若干個服務
TBluetoothService:遠端藍牙設備服務,包括服務名和UUID
TBluetoothServiceList:服務列表。可通過TBluetoothDevice.GetServices獲得遠端設備服務列表
TBluetoothSocket:藍牙通訊套接字。
三、實例解析
小米手機2
1.打開藍牙
2.點擊“發現設備”,過一會就會在下面的列表中顯示出所有搜索到的藍牙設備。
3.在出現的藍牙設備列表中,選一個。比如“小米手機5”。
4.點擊“配對”,這時小米手機5會收到配對信息。
5.這時配對設備列表中就會出現小米手機5,選中它。
6.點擊“服務”,出現N個服務,但這時你不知道怎么與小米手機5通信。對的還少個服務。
7.操作小米手機5中的第三步。
8.在服務列表中選中最下方的(暈,不知道為什么名字是個空串)。
9.進入服務演示頁面。
10.點“發送短信給”不好意思,我不小心點了二下,所以小米手機5收到二次。
11.這時小米手機5就收到了信息。
小米手機5
1.打開藍牙
2.接受小米手機2的配對請求。
3.點擊“創建文本服務”
PS:
1.同一個程序里包括了發送信息,與接收信息。所以程序可以在二個手機上測試。
2.現在只能小米手機2給小米手機5發信息,為什么呢?因為小米手機2沒有建服務呀。
3.如果小米手機5的程序退出,你會發現小米手機2上查看服務,剛才小米手機5建立的服務不見了。
4.圖片本來很清楚,但為了文章的大小,就成了現在的慘不忍睹了。望大家見諒。
Delphi官方實例源碼:
1 unit Unit1; 2 3 interface 4 5 uses 6 System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, 7 FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, System.Bluetooth, 8 FMX.Layouts, FMX.ListBox, FMX.StdCtrls, FMX.Memo, FMX.Controls.Presentation, 9 FMX.Edit, FMX.TabControl, FMX.ScrollBox; 10 11 type 12 //讀取數據線程 13 TServerConnectionTH = class(TThread) 14 private 15 { Private declarations } 16 FServerSocket: TBluetoothServerSocket; 17 FSocket: TBluetoothSocket; 18 FData: TBytes; 19 protected 20 procedure Execute; override; 21 public 22 { Public declarations } 23 constructor Create(ACreateSuspended: Boolean); 24 destructor Destroy; override; 25 end; 26 27 TForm1 = class(TForm) 28 ButtonDiscover: TButton; 29 ButtonPair: TButton; 30 ButtonUnPair: TButton; 31 ButtonPairedDevices: TButton; 32 DisplayR: TMemo; 33 Edit1: TEdit; 34 Button2: TButton; 35 FreeSocket: TButton; 36 Labeldiscoverable: TLabel; 37 ComboBoxDevices: TComboBox; 38 ComboBoxPaired: TComboBox; 39 Panel1: TPanel; 40 TabControl1: TTabControl; 41 TabItem1: TTabItem; 42 TabItem2: TTabItem; 43 LabelNameSarver: TLabel; 44 ButtonServices: TButton; 45 ComboBoxServices: TComboBox; 46 PanelClient: TPanel; 47 LabelClient: TLabel; 48 ButtonConnectToRFCOMM: TButton; 49 PanelServer: TPanel; 50 ButtonCloseReadingSocket: TButton; 51 ButtonOpenReadingSocket: TButton; 52 LabelServer: TLabel; 53 Label1: TLabel; 54 procedure ButtonDiscoverClick(Sender: TObject); 55 procedure ButtonPairClick(Sender: TObject); 56 procedure ButtonUnPairClick(Sender: TObject); 57 procedure ButtonPairedDeviceClick(Sender: TObject); 58 procedure FormShow(Sender: TObject); 59 procedure ButtonOpenReadingSocketClick(Sender: TObject); 60 procedure ButtonConnectToRFCOMMClick(Sender: TObject); 61 procedure ButtonCloseReadingSocketClick(Sender: TObject); 62 procedure Button2Click(Sender: TObject); 63 procedure FormClose(Sender: TObject; var Action: TCloseAction); 64 procedure FreeSocketClick(Sender: TObject); 65 function ManagerConnected:Boolean; 66 function GetServiceName(GUID: string): string; 67 procedure ComboBoxPairedChange(Sender: TObject); 68 procedure ButtonServicesClick(Sender: TObject); 69 private 70 { Private declarations } 71 FBluetoothManager: TBluetoothManager; 72 FDiscoverDevices: TBluetoothDeviceList; 73 FPairedDevices: TBluetoothDeviceList; 74 FAdapter: TBluetoothAdapter; 75 FData: TBytes; 76 FSocket: TBluetoothSocket; 77 ItemIndex: Integer; 78 ServerConnectionTH: TServerConnectionTH; 79 procedure DevicesDiscoveryEnd(const Sender: TObject; const ADevices: TBluetoothDeviceList); 80 procedure PairedDevices; 81 procedure SendData; 82 public 83 { Public declarations } 84 end; 85 86 Const 87 ServiceName = 'Basic Text Server'; 88 ServiceGUI = '{B62C4E8D-62CC-404B-BBBF-BF3E3BBB1378}'; 89 var 90 Form1: TForm1; 91 92 implementation 93 94 {$R *.fmx} 95 {$R *.NmXhdpiPh.fmx ANDROID} 96 {$R *.LgXhdpiPh.fmx ANDROID} 97 {$R *.SmXhdpiPh.fmx ANDROID} 98 {$R *.Macintosh.fmx MACOS} 99 {$R *.iPhone4in.fmx IOS} 100 {$R *.Windows.fmx MSWINDOWS} 101 //配對(Pair) 102 procedure TForm1.ButtonPairClick(Sender: TObject); 103 begin 104 if ManagerConnected then 105 if ComboboxDevices.ItemIndex > -1 then 106 FAdapter.Pair(FDiscoverDevices[ComboboxDevices.ItemIndex]) 107 else 108 ShowMessage('沒有選擇的設備(No device selected)'); 109 end; 110 111 //取消配對(UnPair) 112 procedure TForm1.ButtonUnPairClick(Sender: TObject); 113 begin 114 if ManagerConnected then 115 if ComboboxPaired.ItemIndex > -1 then 116 FAdapter.UnPair(FPairedDevices[ComboboxPaired.ItemIndex]) 117 else 118 ShowMessage('未選擇配對設備(No Paired device selected)'); 119 end; 120 121 procedure TForm1.ComboBoxPairedChange(Sender: TObject); 122 begin 123 LabelNameSarver.Text := ComboBoxPaired.Items[ComboBoxPaired.ItemIndex]; 124 end; 125 126 procedure TForm1.PairedDevices; 127 var 128 I: Integer; 129 begin 130 ComboboxPaired.Clear; 131 if ManagerConnected then 132 begin 133 FPairedDevices := FBluetoothManager.GetPairedDevices; 134 if FPairedDevices.Count > 0 then 135 for I:= 0 to FPairedDevices.Count - 1 do 136 ComboboxPaired.Items.Add(FPairedDevices[I].DeviceName) 137 else 138 ComboboxPaired.Items.Add('沒有配對設備(No Paired Devices)'); 139 end; 140 end; 141 142 //配對設備(Paired Devices) 143 procedure TForm1.ButtonPairedDeviceClick(Sender: TObject); 144 begin 145 PairedDevices; 146 ComboboxPaired.DropDown; 147 end; 148 149 //服務(Services) 150 procedure TForm1.ButtonServicesClick(Sender: TObject); 151 var 152 LServices: TBluetoothServiceList; 153 LDevice: TBluetoothDevice; 154 I: Integer; 155 begin 156 ComboBoxServices.Clear; 157 if ManagerConnected then 158 if ComboboxPaired.ItemIndex > -1 then 159 begin 160 LDevice := FPairedDevices[ComboboxPaired.ItemIndex] as TBluetoothDevice; 161 LServices := LDevice.GetServices; 162 for I := 0 to LServices.Count - 1 do 163 ComboBoxServices.Items.Add(LServices[I].Name + ' --> ' + GUIDToString(LServices[I].UUID)); 164 ComboBoxServices.ItemIndex := 0; 165 ComboBoxServices.DropDown; 166 end 167 else 168 ShowMessage('未選擇配對設備(No paired device selected)'); 169 end; 170 171 //釋放客戶套接字(Free Client Socket) 172 procedure TForm1.FreeSocketClick(Sender: TObject); 173 begin 174 FreeAndNil(FSocket); 175 DisplayR.Lines.Add('客戶套接字釋放(Client socket set free)'); 176 DisplayR.GoToLineEnd; 177 end; 178 179 //清空(Clear) 180 procedure TForm1.Button2Click(Sender: TObject); 181 begin 182 DisplayR.ReadOnly := False; 183 DisplayR.SelectAll; 184 DisplayR.DeleteSelection; 185 DisplayR.ReadOnly := True; 186 end; 187 188 function TForm1.GetServiceName(GUID: string): string; 189 var 190 LServices: TBluetoothServiceList; 191 LDevice: TBluetoothDevice; 192 I: Integer; 193 begin 194 LDevice := FPairedDevices[ComboboxPaired.ItemIndex] as TBluetoothDevice; 195 LServices := LDevice.GetServices; 196 for I := 0 to LServices.Count - 1 do 197 begin 198 if StringToGUID(GUID) = LServices[I].UUID then 199 begin 200 Result := LServices[I].Name; 201 break; 202 end; 203 end; 204 end; 205 206 //發送短信給 - >(Send text to ->) 207 procedure TForm1.ButtonConnectToRFCOMMClick(Sender: TObject); 208 begin 209 if ManagerConnected then 210 try 211 SendData; 212 except 213 on E : Exception do 214 begin 215 DisplayR.Lines.Add(E.Message); 216 DisplayR.GoToTextEnd; 217 FreeAndNil(FSocket); 218 end; 219 end; 220 end; 221 222 //判斷藍牙的狀態 223 function TForm1.ManagerConnected:Boolean; 224 begin 225 if FBluetoothManager.ConnectionState = TBluetoothConnectionState.Connected then 226 begin 227 Labeldiscoverable.Text := FBluetoothManager.CurrentAdapter.AdapterName; 228 Result := True; 229 end 230 else 231 begin 232 Result := False; 233 DisplayR.Lines.Add('沒有發現藍牙設備(No Bluetooth device Found)'); 234 DisplayR.GoToTextEnd; 235 end 236 end; 237 238 //發送信息方法 239 procedure TForm1.SendData; 240 var 241 ToSend: TBytes; 242 LDevice: TBluetoothDevice; 243 begin 244 if (FSocket = nil) or (ItemIndex <> ComboboxPaired.ItemIndex) then 245 begin 246 if ComboboxPaired.ItemIndex > -1 then 247 begin 248 LDevice := FPairedDevices[ComboboxPaired.ItemIndex] as TBluetoothDevice; 249 DisplayR.Lines.Add(GetServiceName(ServiceGUI)); 250 DisplayR.GoToTextEnd; 251 FSocket := LDevice.CreateClientSocket(StringToGUID(ServiceGUI), False); 252 if FSocket <> nil then 253 begin 254 ItemIndex := ComboboxPaired.ItemIndex; 255 FSocket.Connect; 256 ToSend := TEncoding.UTF8.GetBytes(Edit1.Text); 257 FSocket.SendData(ToSend); 258 DisplayR.Lines.Add('短信已發送(Text Sent)'); 259 DisplayR.GoToTextEnd; 260 end 261 else 262 ShowMessage('Out of time -15s-'); 263 end 264 else 265 ShowMessage('未選擇配對設備(No paired device selected)'); 266 end 267 else 268 begin 269 ToSend := TEncoding.UTF8.GetBytes(Edit1.Text); 270 FSocket.SendData(ToSend); 271 DisplayR.Lines.Add('短信已發送(Text Sent)'); 272 DisplayR.GoToTextEnd; 273 end; 274 end; 275 276 //發現設備(Discover devices) 277 procedure TForm1.ButtonDiscoverClick(Sender: TObject); 278 begin 279 ComboboxDevices.Clear; 280 if ManagerConnected then 281 begin 282 FAdapter := FBluetoothManager.CurrentAdapter; 283 FBluetoothManager.StartDiscovery(10000); 284 FBluetoothManager.OnDiscoveryEnd := DevicesDiscoveryEnd; 285 end; 286 end; 287 288 procedure TForm1.DevicesDiscoveryEnd(const Sender: TObject; const ADevices: TBluetoothDeviceList); 289 begin 290 TThread.Synchronize(nil, procedure 291 var 292 I: Integer; 293 begin 294 FDiscoverDevices := ADevices; 295 for I := 0 to ADevices.Count - 1 do 296 ComboboxDevices.Items.Add(ADevices[I].DeviceName + ' -> ' + ADevices[I].Address); 297 ComboboxDevices.ItemIndex := 0; 298 end); 299 end; 300 301 //創建文本服務(Create text service) 302 procedure TForm1.ButtonOpenReadingSocketClick(Sender: TObject); 303 begin 304 if (ServerConnectionTH = nil) and ManagerConnected then 305 begin 306 try 307 FAdapter := FBluetoothManager.CurrentAdapter; 308 ServerConnectionTH := TServerConnectionTH.Create(True); 309 ServerConnectionTH.FServerSocket := FAdapter.CreateServerSocket(ServiceName, StringToGUID(ServiceGUI), False); 310 ServerConnectionTH.Start; 311 DisplayR.Lines.Add(' - 創建服務(Service created): "'+ServiceName+'"'); 312 DisplayR.GoToTextEnd; 313 except 314 on E : Exception do 315 begin 316 DisplayR.Lines.Add(E.Message); 317 DisplayR.GoToTextEnd; 318 end; 319 end; 320 end; 321 end; 322 323 //刪除文字服務(Remove text service) 324 procedure TForm1.ButtonCloseReadingSocketClick(Sender: TObject); 325 begin 326 if ServerConnectionTH <> nil then 327 begin 328 ServerConnectionTH.Terminate; 329 ServerConnectionTH.WaitFor; 330 FreeAndNil(ServerConnectionTH); 331 DisplayR.Lines.Add(' - 服務刪除(Service removed) -'); 332 DisplayR.GoToTextEnd; 333 end 334 end; 335 336 //顯示窗體時,建立藍牙管理器,並檢查是否開啟 337 procedure TForm1.FormShow(Sender: TObject); 338 begin 339 try 340 LabelServer.Text := ServiceName; 341 LabelClient.Text := 'Client of '+ServiceName; 342 FBluetoothManager := TBluetoothManager.Current; 343 FAdapter := FBluetoothManager.CurrentAdapter; 344 if ManagerConnected then 345 begin 346 PairedDevices; 347 ComboboxPaired.ItemIndex := 0; 348 end; 349 except 350 on E : Exception do 351 begin 352 ShowMessage(E.Message); 353 end; 354 end; 355 end; 356 357 //關閉時,釋放線程 358 procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction); 359 begin 360 if ServerConnectionTH <> nil then 361 begin 362 ServerConnectionTH.Terminate; 363 ServerConnectionTH.WaitFor; 364 FreeAndNil(ServerConnectionTH); 365 end 366 end; 367 368 {TServerConnection} 369 constructor TServerConnectionTH.Create(ACreateSuspended: Boolean); 370 begin 371 inherited; 372 end; 373 374 //釋放資源 375 destructor TServerConnectionTH.Destroy; 376 begin 377 FSocket.Free; 378 FServerSocket.Free; 379 inherited; 380 end; 381 382 //讀取線程的讀取數據方法 383 procedure TServerConnectionTH.execute; 384 var 385 ASocket: TBluetoothSocket; 386 Msg: string; 387 begin 388 while not Terminated do 389 try 390 ASocket := nil; 391 while not Terminated and (ASocket = nil) do 392 ASocket := FServerSocket.Accept(100); 393 if(ASocket <> nil) then 394 begin 395 FSocket := ASocket; 396 while not Terminated do 397 begin 398 FData := ASocket.ReadData; 399 if length(FData) > 0 then 400 Synchronize(procedure 401 begin 402 Form1.DisplayR.Lines.Add(TEncoding.UTF8.GetString(FData)); 403 Form1.DisplayR.GoToTextEnd; 404 end); 405 sleep(100); 406 end; 407 end; 408 except 409 on E : Exception do 410 begin 411 Msg := E.Message; 412 Synchronize(procedure 413 begin 414 Form1.DisplayR.Lines.Add('服務器關閉套接字(Server Socket closed): ' + Msg); 415 Form1.DisplayR.GoToTextEnd; 416 end); 417 end; 418 end; 419 end; 420 421 end.
