上文讲解了如何启动蓝牙功能。现在我们已经启动了蓝牙功能,接下来要做的是获取要连接的对象的蓝牙信息。
上文连接:Android 教你如何写蓝牙程序1——消息传递、启动蓝牙
1 获取已存储的蓝牙连接对象
我们先讲简单的,现在单纯要获取已存储的蓝牙连接对象信息。
//获取蓝牙适配器
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
//获取所有已连接的蓝牙设备信息,每一个蓝牙设备信息用BluetoothDevice存储
Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
这就完了。。
BluetoothDevice类有几个重要的方法
String getName();//获取蓝牙名
String getAddress();//获取MAC地址,用于连接配对
BluetoothGatt connectGatt(Context context, boolean autoConnect,BluetoothGattCallback callback)
//最后一个方法用于与特定设备建立建立连接,该方法在BLE低功耗建立蓝牙连接的时候需要用到
//本文为了连接HC-06模块采用Socket的方式建立蓝牙连接,不用BLE的方法。
2 搜索其他设备
//开启蓝牙搜索
mBluetoothAdapter.startDiscovery();
//结束蓝牙搜索
mBluetoothAdapter.cancelDiscovery();
//判断当前是否在蓝牙搜索
mBluetoothAdapter.isDiscovering() //返回boolean
我们希望搜索到新的设备时,可以自动运行一些程序,这可以利用广播监听功能实现,监听的动作为 BluetoothDevice.ACTION_FOUND。当搜索到新的蓝牙设备时将广播该字段。
下面是广播接收程序
class BlueToothStateChange extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if(BluetoothDevice.ACTION_FOUND.equals(action)) {
//下面这句话可获取搜索到的新设备信息
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
//这里更新UI界面,并把刚获得的蓝牙设备信息存好
}
}
}
//注册广播接收器
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
context.registerReceiver(mReceiver, filter);
//启动蓝牙搜索功能
if(!mBluetoothAdapter.isDiscovering()){
mBluetoothAdapter.startDiscovery();
}
注意,mBluetoothAdapter.startDiscovery();这句话将启动蓝牙设备搜索功能,并耗费大量资源,搜索到想要的设备之后,要及时使用mBluetoothAdapter.cancelDiscovery();关闭搜索功能。
3 具体的UI设计
我们先从用户的角度想一下,作为用户,我们希望怎么选择我们想要接连的对象呢?我采取的办法是:用AlertDialog构建一个临时对话框,并加入单选列表,把所有可连接的蓝牙设备显示出来,当用户点击确定的时候,获取选择的对象,这样就能得知目标信息了,并可以执行下一步了。
在 AlertDialog 中加入一个搜索蓝牙设备的功能,当广播接收器接收到新的设备信息后,自动更新临时对话框。
以下是这一部分的完整代码
public class BlueToothTool{
//来自布局的信息
BluetoothAdapter mBluetoothAdapter;//蓝牙适配器
Context context;
Handler handlerToMain;
//客户端
private List<MapEntry> existBlueToothMap = new ArrayList<>();//用于存储已有的蓝牙信息
public MapEntry clientMapEntry = null;//存储客户端蓝牙信息
BluetoothDevice mDevice;
//对话框
AlertDialog alertDialog = null;
public BlueToothTool(BluetoothAdapter mBluetoothAdapter, Context context, Handler handler){
this.mBluetoothAdapter = mBluetoothAdapter;
this.context = context;
this.handlerToMain = handler;
//打开蓝牙功能
BlueToothFuctionStart();
}
/**
* 1.尝试打开蓝牙功能
*/
private void BlueToothFuctionStart(){
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if(mBluetoothAdapter!=null){
//检测是否开启了蓝牙功能,注意startActivity会开启子线程,无法在此语句后面直接判断蓝牙功能是否被开启
if(!mBluetoothAdapter.isEnabled()) {
//尝试开启蓝牙功能
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
context.startActivity(enableBtIntent);
//注册对蓝牙状态功能的监听事件
//实例化IntentFilter对象
IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
context.registerReceiver(bluetoothStateBroadcastReceive,filter);
}else{
//直接执行下一步
//获取过去配对过的信息
//2.1查找已配对的设备
getExistBlueTooth();
show();
}
}else{
Toast.makeText(context,"您的设备不支持蓝牙系统",Toast.LENGTH_SHORT).show();
}
}
/**
* 1.1通过广播对蓝牙状态进行监听
*/
private BluetoothStateBroadcastReceive bluetoothStateBroadcastReceive = new BluetoothStateBroadcastReceive();
private class BluetoothStateBroadcastReceive extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
switch (action) {
case BluetoothAdapter.ACTION_STATE_CHANGED:
int blueState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, 0);
if (blueState == BluetoothAdapter.STATE_ON) {
try {
//注销对象
context.unregisterReceiver(bluetoothStateBroadcastReceive);
} catch (Exception e){
Log.d("蓝牙状态","注销监听失败,监听对象不存在");
}
}
//执行下一步
//获取过去配对过的信息
//2.1查找已配对的设备
getExistBlueTooth();
show();
}
}
}
}
/**
* 1.2 查询已配对过的设备,并重置blueExistToothName数组
*/
public void getExistBlueTooth(){
Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
if (pairedDevices.size() > 0) {
int i = 0;
for (BluetoothDevice device : pairedDevices) {
//2.1把名字和地址取出来
existBlueToothMap.add(device);
}
}
}
//用于获取所有蓝牙设备信息的名称和MAC地址
public ArrayList<MapEntry> getExistBlueToothNameAndValue(){
ArrayList<MapEntry> arr = new ArrayList<>();
for (int i = 0; i < existBlueToothMap.size(); i++) {
arr.add(new MapEntry(existBlueToothMap.get(i).getName(),existBlueToothMap.get(i).getAddress()));
}
return arr;
}
/*
用于存储名称和地址
*/
public class MapEntry{
private String key;
private String value;
private MapEntry(){}
public MapEntry(String e,String v){
this.key = e;
this.value = v;
}
public String getKey() {
return key;
}
public String getValue() {
return value;
}
public String toString(){
return key + " :" + value;
}
}
/**
* 2.尝试配对设备
* 根据已经获得的蓝牙设备信息建立对话框
*/
public void show() {
if (mBluetoothAdapter.isEnabled()) {
if (existBlueToothMap.size() > 0) {
//2.2弹出对话框
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle("蓝牙配对");
final ArrayList<MapEntry> tempArr = getExistBlueToothNameAndValue();
String[] showArr = new String[existBlueToothMap.size()];
for (int i = 0; i < tempArr.size(); i++) {
showArr[i] = tempArr.get(i).getKey() + " :" + tempArr.get(i).getValue();
}
final int[] choose = new int[1];
final Boolean[] isChoose = {false};
//蓝牙的信息列表
builder.setSingleChoiceItems(showArr, -1, new DialogInterface.OnClickListener() {
@Override//第二个参数指的是默认第几项被选中
public void onClick(DialogInterface dialog, int which) {
//选中了哪个
choose[0] = which;
isChoose[0] = true;
}
});
//搜索设备
builder.setNeutralButton("搜索其他设备", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//3.在此处进行其他设备的搜索
//注册广播
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
context.registerReceiver(mReceiver, filter);
//启动蓝牙搜索功能
if(!mBluetoothAdapter.isDiscovering()){
mBluetoothAdapter.startDiscovery();
}
Toast.makeText(context,"正在进行蓝牙搜索",Toast.LENGTH_SHORT).show();
show();
}
});
//确定
builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if(isChoose[0]) {
if (mBluetoothAdapter.isDiscovering())
mBluetoothAdapter.cancelDiscovery();
//注销广播监听
try {
context.unregisterReceiver(mReceiver);
} catch (Exception e) {
Log.d("蓝牙搜索接收器", "注销失败,不存在该接收器");
}
Toast.makeText(context, "正在尝试连接蓝牙设备", Toast.LENGTH_SHORT).show();
//存储客户端蓝牙信息
clientMapEntry = new MapEntry(tempArr.get(choose[0]).getKey(), tempArr.get(choose[0]).getValue());
//获取目标蓝牙设备信息
mDevice = existBlueToothMap.get(choose[0]);
//此处可进行下一步
}
}
});
//取消
builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
close();
}
});
alertDialog = builder.show();
}
}
}
/**
* 2.1广播搜索其他的蓝牙设备
* 下列语句用于注册广播接收
*/
// 新建一个 BroadcastReceiver来接收ACTION_FOUND广播
private BlueToothStateChange mReceiver = new BlueToothStateChange();
class BlueToothStateChange extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if(BluetoothDevice.ACTION_FOUND.equals(action)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
existBlueToothMap.add(new MapEntry(device.getName(), device.getAddress()));
if (alertDialog.isShowing())
alertDialog.dismiss();
show();//重新弹出对话框
}
}
}
/**
* 关闭连接
*/
public void close(){
//关闭广播搜索
try {
if (!mBluetoothAdapter.isDiscovering()) {
mBluetoothAdapter.cancelDiscovery();
}
}catch (Exception e){
Log.d("蓝牙搜索","关闭失败,可能尚未开启,或者谁没没有蓝牙功能");
}
//注销广播监听
try {
context.unregisterReceiver(mReceiver);
}catch (Exception e){
Log.d("蓝牙搜索接收器","注销失败,不存在该接收器");
}
}
}