摘要
第一篇算是個熱身,這一片開始來寫些硬菜了,這篇就是實際和藍牙打交道了,所以要用到真機調試喲,這篇我會把基本上要講的概念都通俗易懂的來一遍,這樣我們腦子里先有個邏輯,我們就好操作了,先看一下我們的剖析圖
下面概念相關的可去原文查看:http://www.epx.com.br/artigos/bluetooth_gatt.php
藍牙這個名稱來自于第十世紀的一位丹麥國王哈拉爾藍牙王,Blatand 在英文里的意思就是哈拉爾藍牙王
可以被解釋為 Bluetooth( 藍牙 )因為國王喜歡吃藍莓,牙齦每天都是藍色的所以叫藍牙。
在行業(yè)協會籌備階段,需要一個極具有表現力的名字來命名這項高新技術。行業(yè)組織人員, 在經過一夜關于歐洲歷史和未來無線技術發(fā)展的討論后,有些人認為用 Blatand 國王的名字 命名再合適不過了。Blatand 國王將挪威,瑞典和丹麥統(tǒng)一起來;他的口齒伶俐,善于交際,就如同這項即將面世的技術,技術將被定義為允許不同工業(yè)領域之間的協調工作,保持著各個系統(tǒng)領域之間的良好交流,例如計算機,手機和汽車行業(yè)之間的工作。名字于是就這么定 下來了。
藍牙的創(chuàng)始人是愛立信公司,愛立信早在 1994 年就已進行研發(fā)。1997 年,愛立信與 其他設備生產商聯系,并激發(fā)了他們對該項技術的濃厚興趣。 1998 年 2 月,跨國大公司, 包括諾基亞、蘋果、三星組成的一個特殊興趣小組(SIG),他們共同的目標是建立一 個全球性的小范圍無線通信技術,即藍牙。
而藍牙這個標志的設計:它取自 Harald Bluetooth 名字中的「H」和「B」兩個字母, 用古北歐字母來表示,將這兩者結合起來,就成為了藍牙的 logo
藍牙技術規(guī)定每一對設備之間進行藍牙通訊時,必須一個為主角色,另一為從角色,
才能進行通信,通信時,必須由主端進行查找,發(fā)起配對,建鏈成功后,雙方即可收發(fā)數據。 理論上,一個藍牙主端設備,可同時與 7 個藍牙從端設備進行通訊。一個具備藍牙通訊功 能的設備, 可以在兩個角色間切換,平時工作在從模式,等待其它主設備來連接,需要時, 轉換為主模式,向其它設備發(fā)起呼叫。一個藍牙設備以主模式發(fā)起呼叫時,需要知道對方的 藍牙地址,配對密碼等信息,配對完成后,可直接發(fā)起呼叫。
藍牙主端設備發(fā)起呼叫,首先是查找,找出周圍處于可被查找的藍牙設備。主端設備 找到從端藍牙設備后,與從端藍牙設備進行配對,此時需要輸入從端設備的 PIN 碼,也有 設備不需要輸入 PIN 碼。配對完成后,從端藍牙設備會記錄主端設備的信任信息,此時主 端即可向從端設備發(fā)起呼叫,已配對的設備在下次呼叫時,不再需要重新配對。已配對的設備,做為從端的藍牙耳機也可以發(fā)起建鏈請求,但做數據通訊的藍牙模塊一般不發(fā)起呼叫。鏈路建立成功后,主從兩端之間即可進行雙向的數據或語音通訊。在通信狀態(tài)下,主端和從 端設備都可以發(fā)起斷鏈,斷開藍牙鏈路。
藍牙數據傳輸應用中,一對一串口數據通訊是最常見的應用之一,藍牙設備在出廠前 即提前設好兩個藍牙設備之間的配對信息,主端預存有從端設備的 PIN 碼、地址等,兩端 設備加電即自動建鏈,透明串口傳輸,無需外圍電路干預。一對一應用中從端設備可以設為兩種類型,一是靜默狀態(tài),即只能與指定的主端通信,不被別的藍牙設備查找;二是開發(fā)狀 態(tài),既可被指定主端查找,也可以被別的藍牙設備查找建鏈。
參考獲取本地藍牙
2.UUID
1.1 認識一下 UUID UUID 含義是通用唯一識別碼 (Universally Unique Identifier),這 是一個軟件建構的標 準,也是被開源軟件基金會 (Open Software Foundation, OSF) 的組織應用在分布式計算 環(huán)境 (Distributed Computing Environment, DCE) 領域的一部分。
在藍牙 3.0 及一下版本中,UUID 被用于唯一標識一個服務,比如文件傳輸服務,串口 服務、打印機服務等,如下:
藍牙串口服務
SerialPortServiceClass_UUID = ‘{00001101-0000-1000-8000-00805F9B34FB}’
LANAccessUsingPPPServiceClass_UUID = ‘{00001102-0000-1000-8000-00805F9B34FB}’
撥號網絡服務
DialupNetworkingServiceClass_UUID = ‘{00001103-0000-1000-8000-00805F9B34FB}’
信息同步服務
IrMCSyncServiceClass_UUID = ‘{00001104-0000-1000-8000-00805F9B34FB}’ SDP_OBEXObjectPushServiceClass_UUID = ‘{00001105-0000-1000-8000-00805F9B34FB} ’
文件傳輸服務
OBEXFileTransferServiceClass_UUID = ‘{00001106-0000-1000-8000-00805F9B34FB}’ IrMCSyncCommandServiceClass_UUID = ‘{00001107-0000-1000-8000-00805F9B34FB}’
藍牙的連接有主從設備,提供服務的可以認為是從設備。主設備通過 UUID 訪問從設備 提供具有相同 UUID 的服務,從而建立客服端—服務器(C/S)模式。
四.實際應用
我們新建一個Eclipse工程:BluetoothGet
我們直接看圖(簡單的概念)
<uses-permissionandroid:name="android.permission.BLUETOOTH"/>
<uses-permissionandroid:name="android.permission.BLUETOOTH_ADMIN"/>
3.編寫程序
布局很簡單,就一個搜索按鈕和一個textview的列表
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<Button
android:id="@+id/btnSearch"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="搜索藍牙設備" />
<TextView
android:id="@+id/tvDevices"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
步驟分析
// 獲取本地藍牙適配器
mBluetoothAdapter=BluetoothAdapter.getDefaultAdapter();
2.判斷手機是否支持藍牙
// 判斷手機是否支持藍牙
if (mBluetoothAdapter == null) {
Toast.makeText(this, "設備不支持藍牙", Toast.LENGTH_SHORT).show();
finish();
}
3.判斷藍牙是否打開
// 判斷是否打開藍牙
if (!mBluetoothAdapter.isEnabled()) {
// 彈出對話框提示用戶是后打開
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(intent, 1);
// 不做提示,強行打開
// mBluetoothAdapter.enable();
}
4.獲取已經配對的設備// 獲取已經配對的設備? ? SetpairedDevices = mBluetoothAdapter.getBondedDevices();
// 判斷是否有配對過的設備
if (pairedDevices.size() > 0) {
for (BluetoothDevice device : pairedDevices) {
// 遍歷到列表中
tvDevices.append(device.getName() + ":" + device.getAddress());
Log.i("已配對設備", tvDevices.getText().toString());
}
}
5.搜索的點擊事件
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btnSearch:
//設置進度條
setProgressBarIndeterminateVisibility(true);
setTitle("正在搜索...");
// 判斷是否在搜索,如果在搜索,就取消搜索
if (mBluetoothAdapter.isDiscovering()) {
mBluetoothAdapter.cancelDiscovery();
}
// 開始搜索
mBluetoothAdapter.startDiscovery();
break;
}
}
6.搜索的廣播
1.注冊廣播
/**
* 異步搜索藍牙設備——廣播接收
*/
// 找到設備的廣播
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
// 注冊廣播
registerReceiver(receiver, filter);
// 搜索完成的廣播
filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
// 注冊廣播
registerReceiver(receiver, filter);
1.廣播接收器
// 廣播接收器
private final BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// 收到的廣播類型
String action = intent.getAction();
// 發(fā)現設備的廣播
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
// 從intent中獲取設備
BluetoothDevice device = intent
.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// 判斷是否配對過
if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
// 添加到列表
tvDevices.append(device.getName() + ":"
+ device.getAddress() + "\n");
}
// 搜索完成
} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED
.equals(action)) {
//關閉進度條
setProgressBarIndeterminateVisibility(true);
setTitle("搜索完成!");
}
}
};
好了,到此,我們的程序算是完成了
package com.lgl.bluetoothget;
import java.util.Set;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity implements OnClickListener {
// 本地藍牙適配器
private BluetoothAdapter mBluetoothAdapter;
// 搜索到藍牙添加
private TextView tvDevices;
// 搜索藍牙的按鈕
private Button btnSearch;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView() {? ? ?
?? tvDevices = (TextView) findViewById(R.id.tvDevices);? ? ?
?? btnSearch = (Button) findViewById(R.id.btnSearch);? ? ?
?? btnSearch.setOnClickListener(this);? ? ?
?? // 獲取本地藍牙適配器? ? ?
?? mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();? ? ?
?? // 判斷手機是否支持藍牙? ? ?
?? if (mBluetoothAdapter == null) {? ? ? ? ?
?? Toast.makeText(this, "設備不支持藍牙", Toast.LENGTH_SHORT).show();? ? ??
? ? ? finish();? ? ?
?? }? ? ?
?? // 判斷是否打開藍牙? ?
? ?if (!mBluetoothAdapter.isEnabled()) {? ? ? ??
? ? // 彈出對話框提示用戶是后打開??
? ? Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);? ? ? ? ? ??
? ? startActivityForResult(intent, 1);? ? ? ? ? ?
? ? ?// 不做提示,強行打開? ? ? ? ?
? ? ?// mBluetoothAdapter.enable();? ? ?
?? }? ? ?
?? // 獲取已經配對的設備? ? ??
? SetpairedDevices = mBluetoothAdapter
.getBondedDevices();
// 判斷是否有配對過的設備
if (pairedDevices.size() > 0) {
for (BluetoothDevice device : pairedDevices) {
// 遍歷到列表中
tvDevices.append(device.getName() + ":" + device.getAddress());
Log.i("已配對設備", tvDevices.getText().toString());
}
}
/**
* 異步搜索藍牙設備——廣播接收
*/
// 找到設備的廣播
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
// 注冊廣播
registerReceiver(receiver, filter);
// 搜索完成的廣播
filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
// 注冊廣播
registerReceiver(receiver, filter);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btnSearch:
// 設置進度條
setProgressBarIndeterminateVisibility(true);
setTitle("正在搜索...");
// 判斷是否在搜索,如果在搜索,就取消搜索
if (mBluetoothAdapter.isDiscovering()) {
mBluetoothAdapter.cancelDiscovery();
}
// 開始搜索
mBluetoothAdapter.startDiscovery();
break;
}
}
// 廣播接收器
private final BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// 收到的廣播類型
String action = intent.getAction();
// 發(fā)現設備的廣播
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
// 從intent中獲取設備
BluetoothDevice device = intent
.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// 判斷是否配對過
if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
// 添加到列表
tvDevices.append(device.getName() + ":"
+ device.getAddress() + "\n");
}
// 搜索完成
} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED
.equals(action)) {
// 關閉進度條
setProgressBarIndeterminateVisibility(true);
setTitle("搜索完成!");
}
}
};
}
我們運行一下