android藍牙系列——基礎科普以及搜索藍牙設備顯示列表

摘要

第一篇算是個熱身,這一片開始來寫些硬菜了,這篇就是實際和藍牙打交道了,所以要用到真機調試喲,這篇我會把基本上要講的概念都通俗易懂的來一遍,這樣我們腦子里先有個邏輯,我們就好操作了,先看一下我們的剖析圖

下面概念相關的可去原文查看: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

二.藍牙的工作原理

1.藍牙通信的主從關系

藍牙技術規(guī)定每一對設備之間進行藍牙通訊時,必須一個為主角色,另一為從角色,

才能進行通信,通信時,必須由主端進行查找,發(fā)起配對,建鏈成功后,雙方即可收發(fā)數據。 理論上,一個藍牙主端設備,可同時與 7 個藍牙從端設備進行通訊。一個具備藍牙通訊功 能的設備, 可以在兩個角色間切換,平時工作在從模式,等待其它主設備來連接,需要時, 轉換為主模式,向其它設備發(fā)起呼叫。一個藍牙設備以主模式發(fā)起呼叫時,需要知道對方的 藍牙地址,配對密碼等信息,配對完成后,可直接發(fā)起呼叫。

2.藍牙的呼叫過程

藍牙主端設備發(fā)起呼叫,首先是查找,找出周圍處于可被查找的藍牙設備。主端設備 找到從端藍牙設備后,與從端藍牙設備進行配對,此時需要輸入從端設備的 PIN 碼,也有 設備不需要輸入 PIN 碼。配對完成后,從端藍牙設備會記錄主端設備的信任信息,此時主 端即可向從端設備發(fā)起呼叫,已配對的設備在下次呼叫時,不再需要重新配對。已配對的設備,做為從端的藍牙耳機也可以發(fā)起建鏈請求,但做數據通訊的藍牙模塊一般不發(fā)起呼叫。鏈路建立成功后,主從兩端之間即可進行雙向的數據或語音通訊。在通信狀態(tài)下,主端和從 端設備都可以發(fā)起斷鏈,斷開藍牙鏈路。

3.藍牙一對一的串口數據傳輸應用

藍牙數據傳輸應用中,一對一串口數據通訊是最常見的應用之一,藍牙設備在出廠前 即提前設好兩個藍牙設備之間的配對信息,主端預存有從端設備的 PIN 碼、地址等,兩端 設備加電即自動建鏈,透明串口傳輸,無需外圍電路干預。一對一應用中從端設備可以設為兩種類型,一是靜默狀態(tài),即只能與指定的主端通信,不被別的藍牙設備查找;二是開發(fā)狀 態(tài),既可被指定主端查找,也可以被別的藍牙設備查找建鏈。

三.藍牙 Android 編程應用

1.相關部署

參考獲取本地藍牙

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

1.藍牙協議

我們直接看圖(簡單的概念)

2.藍牙權限

<uses-permissionandroid:name="android.permission.BLUETOOTH"/>

<uses-permissionandroid:name="android.permission.BLUETOOTH_ADMIN"/>

3.編寫程序

activity_main.xml

布局很簡單,就一個搜索按鈕和一個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>

步驟分析

1.首先獲取本地的藍牙適配器

// 獲取本地藍牙適配器

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("搜索完成!");

}

}

};

好了,到此,我們的程序算是完成了

MainActivity

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("搜索完成!");

}

}

};

}

我們運行一下

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容