Android藍牙的基本介紹與實現
10.6 藍牙的基本介紹與實現(1)
藍牙,是一種支持設備短距離通信(一般10m內,且無阻隔媒介)的無線電技術。能在包括移動電話、PDA、無線耳機、筆記本電腦等衆多設備之間進行無線信息交換。利用"藍牙"技術,能夠有效地簡化移動通信終端設備之間的通信,也能夠成功地簡化設備與Internet之間的通信,這樣數據傳輸變得更加迅速高效,爲無線通信拓寬道路。
幾個術語
在Android手機平臺中,只到Android 2.0才引入藍牙接口。在開發時,需要真機測試,如果需要數據傳輸,還需要兩臺機器,另外藍牙需要硬件支持,但一般的智能手機上都會有這方面的支持,特別是Android系統的手機。
正式開發Android 藍牙時,需要在Android項目中的AndroidManifest.xml中添加對應權限:
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH" />
以下介紹android.bluetooth.*中的重要類的作用,如表10-7所示。
表10-7 android.bluetooth.*中的重要類的作用
類 名 | 作 用 |
本地藍牙設備的適配類,所有的藍牙 操作都要通過該類完成 | |
BluetoothClass | 用於描述遠端設備的類型,特點等信息 |
藍牙設備類,代表了藍牙通訊過程中的遠端設備 | |
BluetoothServerSocket | |
BluetoothSocket | 藍牙設備客戶端,類似Socket |
BluetoothClass.Device | 藍牙關於設備信息 |
BluetoothClass.Device.Major | 藍牙設備管理 |
BluetoothClass.Service | 藍牙相關服務 |
其中BluetoothAdapter是一個非常重要的適配類,它包含打開藍牙、關閉藍牙、藍牙狀態、搜索藍牙等重要方法,如表10-8所示。
表10-8 BluetoothAdapter適配類包含的方法
方 法 | 作 用 |
getDefaultAdapter | 得到默認藍牙適配器 |
getRemoteDevice | 得到指定藍牙的BluetoothDevice |
isEnabled | 藍牙是否開啓 |
getState | 得到藍牙狀態 |
enable | 打開藍牙 |
Disable | 關閉藍牙 |
getAddress | 得到藍牙適配器地址 |
getName | 得到藍牙的名字 |
setName | 設置藍牙的名字 |
getScanMode | 得到當前藍牙的掃描模式 |
setScanMode | 設置當前藍牙的設置模式 |
startDiscovery | 開始搜索藍牙設備 |
cancelDiscovery | 取消搜索藍牙設備 |
isDiscovering | 是否允許被搜索 |
getBondedDevices | 得到BluetoothDevice集合到本地適配器 |
listenUsingRfcommWithServiceRecord | 創建一個監聽,安全記錄藍牙 RFCOMM藍牙套接字 |
checkBluetoothAddress | 檢查藍牙地址是否正確 |
Android操作藍牙不是很困難,主要就是打開藍牙、關閉藍牙、搜索藍牙、藍牙客戶端、藍牙服務器等。藍牙客戶端、服務器和Socket基礎中講解的差不多,但藍牙中是用BluetoothSocket和BluetoothServerSocket兩個類來操作。
關於Android在操作藍牙過程中的幾個要點和操作方式如下。
1.打開藍牙的方式有兩種
(1)Intent enabler = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enabler, REQUEST_ENABLE);
(2)BluetoothAdapter _bluetooth = BluetoothAdapter.getDefaultAdapter();
_bluetooth.enable();
第一種方式Android系統會彈出一個提示框,提示用戶是否開啓藍牙設備。第二種方式不會提示,會直接打開藍牙設備,在運用當中視情況而定,有些情況需要友好提示,有些情況則可直接打開使用。
2.使設備能夠被搜索
基於安全性考慮,設置開啓可被搜索後,Android系統就會默認給出120秒的時間,其他遠程設備在這120秒內可以搜索到它:
Intent enabler = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
startActivityForResult(enabler, REQUEST_DISCOVERABLE);
3.搜索藍牙設備
BluetoothAdapter _bluetooth = BluetoothAdapter.getDefaultAdapter()
_bluetooth.startDiscovery();
4.關閉藍牙設備
BluetoothAdapter _bluetooth = BluetoothAdapter.getDefaultAdapter();
_bluetooth.disable ();
5.創建藍牙客戶端
BluetoothSocket socket= device.
createRfcommSocketToServiceRecord(UUID.fromString(UUID號));socket.connect();
6.創建藍牙服務器
BluetoothServerSocket _serverSocket=_bluetooth.
listenUsingRfcommWithServiceRecord(服務器名稱, UUID.fromString(UUID號));BluetoothSocket socket = _serverSocket.accept();
InputStream inputStream = socket.getInputStream();
看到_serverSocket.accept()大家想到前面Socket章節所講到的ServerSocket也有這個方法,原理上它們其實是一樣的,都是阻塞等待客戶端的數據,如果客戶端沒有數據過來,它將一直阻塞在此處。
在上述幾個重要步驟方法中,最重要的是藍牙客戶端和服務器,這兩個操作是在商業應用中和日常使用中最頻繁的,例如,利用藍牙傳遞數據、遊戲、聊天等。目前市場上出現很多關於利用藍牙技術做的聊天工具和傳輸數據文件的應用,它們都是採用BluetoothSocket和BluetoothServerSocket技術。
另外還有一點注意,藍牙和WiFi都是比較耗電的功能模塊,所以,在不使用藍牙的情況下,建議關閉它。
藍牙的基本操作和代碼實現
代碼部分就實現打開藍牙、關閉藍牙、搜索藍牙、允許搜索。目前唯一比較複雜的地方就是如何建立藍牙客戶端和藍牙服務器。
下面看看代碼是如何實現藍牙服務器和藍牙客戶端的,代碼如下,代碼來源EX_10_05:
服務器端:
………………………………省略部分代碼…………………………..
setTitle("藍牙服務端");
// 聲明變量
BluetoothAdapter bluetooth = null;//本地藍牙設備
BluetoothServerSocket serverSocket = null;// 藍牙設備Socket服務端
BluetoothSocket socket = null;// 藍牙設備Socket客戶端
OutputStream os = null;// 藍牙輸出流
InputStream is = null;// 藍牙輸入流
try {
// 1.得到本地設備
bluetooth = BluetoothAdapter.getDefaultAdapter();
// 2.創建藍牙Socket服務器
serverSocket = bluetooth.
listenUsingRfcommWithServiceRecord("btspp",
UUID.fromString("00000000-2527-eef3-ffff-ffffe3160865"));// 3.阻塞等待Socket客戶端請求
socket = serverSocket.accept();
if (socket != null) {
// 4.處理輸出流
os = socket.getOutputStream();
os.write("我是服務器!".getBytes());
if (os != null) {
os.flush();
os.close();
}
// 5.處理輸入流
is = socket.getInputStream();
byte[] bytes = new byte[is.available()];
is.read(bytes);
System.out.println("服務器端讀取客戶端傳輸的數據時:" + new String(bytes));
if (is != null)
is.close();
if (socket != null)
socket.close();
if (serverSocket != null)
serverSocket.close();
}
} catch (Exception e) {
e.printStackTrace();
}
客戶端:
………………………………省略部分代碼…………………………..
setTitle("藍牙客戶端");
//聲明變量
BluetoothAdapter bluetooth = null;//本地藍牙設備
BluetoothDevice device = null;//遠程藍牙設備
BluetoothSocket socket = null;//藍牙Socket客戶端
OutputStream os = null;//輸出流
InputStream is = null;//輸入流
try {
//1.得到本地藍牙設備的默認適配器
bluetooth = BluetoothAdapter.getDefaultAdapter();
//2.通過本地藍牙設備得到遠程藍牙設備
device = bluetooth.getRemoteDevice("A0:75:91:E0:88:D3");
//3.根據UUID 創建並返回一個BluetoothSocket
socket = device.createRfcommSocketToServiceRecord(UUID
.fromString("00000000-2527-eef3-ffff-ffffe3160865"));
if (socket != null) {
// 連接
socket.connect();
//4處理客戶端輸出流
os = socket.getOutputStream();
os.write("我是客戶端!".getBytes());
os.flush();
os.close();
//5處理客戶端輸入流
is = socket.getInputStream();
byte[] b = new byte[is.available()];
is.read(b);
System.out.println("客戶端接收到服務器傳輸的數據::" + new String(b));
is.close();
socket.close();
}
} catch (Exception e) {
e.printStackTrace();
}
代碼解釋:
測試代碼時,需要手動打開藍牙並自行配置好藍牙客戶端和服務器,也就是藍牙配對。代碼中注意服務器端和客戶端的UUID:00000000-2527-eef3-ffff-ffffe3160865,兩個地方一定要一樣,另外客戶端代碼中的bluetooth.getRemoteDevice("A0:75:91:E0:88:D3")是通過服務器端的地址獲取遠程藍牙服務器。
從代碼角度看其實都很簡單,讀者要多練並且多靈活運用。如果前期讀者對Socket的學習過關的話,學習藍牙Socket編程是非常輕鬆的。由於BluetoothSocket支持OutputStream和InputStream,所以,可以利用它們相互傳輸任何數據