蓝牙的最基本的用法,搜索和配对!
首先看下效果如下
开启蓝牙
开启蓝牙需要注册清单文件,初始化蓝牙适配器,添加广播监听,最后才是正式开启蓝牙。
清单文件加权限
<!-- 蓝牙权限 -->
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
5.0以上的版本需要加入gps权限
<!-- 5.0之后蓝牙需要获取gps权限 -->
<uses-feature android:name="android.hardware.location.gps" />
6.0以上的版本需要手动申请定位权限
<!-- 6.0之后蓝牙需要位置权限 记得用6.0后的权限访问 -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
注:6.0加入权限之后记得手动获取权限!不然蓝牙功能无法正常使用
初始化蓝牙(BluetoothAdapter)
初始化相当简单直接调用getDefaultAdapter方法就可以了
//初始化蓝牙
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (bluetoothAdapter == null) {
Toast.makeText(this, "设备不存在蓝牙", Toast.LENGTH_SHORT).show();
return;
}
初始化之后就可以用BluetoothAdapter对象进行对蓝牙的操作
BluetoothAdapter常用方法表格如下
| 方法 | 说明 |
|---|---|
| getDefaultAdapter | 默认本地适配器,如果此硬件平台不支持蓝牙,则为空。 |
| isEnabled | 如果蓝牙当前已启用并准备好使用,则返回true。 |
| getState | 获取本地蓝牙适配器的当前状态。STATE_OFF(关闭)、STATE_TURNING_ON(正在打开)、STATE_ON(开启)、STATE_TURNING_OFF(正在关闭) |
| enable | 强制开启蓝牙 |
| disable | 强制关闭蓝牙 |
| disable(boolean persist) | 强制关闭蓝牙,是否保留设置。 |
| getAddress | 获取蓝牙地址 |
| getName | 获取蓝牙名字 |
| factoryReset | 出厂重置蓝牙 |
| setName(String name) | 设置蓝牙名字 |
| getScanMode | 获取蓝牙的扫描模式,扫描模式确定是否可以连接或被发现。SCAN_MODE_NONE(蓝牙未开启)、SCAN_MODE_CONNECTABLE(不可见)、SCAN_MODE_CONNECTABLE_DISCOVERABLE(可见) |
| setScanMode(@ScanMode int mode, int duration) | (需要使用反射)设置蓝牙的扫描模式,单独的setScanMode(int mode)改变状态设置默认蓝牙可见时间 |
| getDiscoverableTimeout、setDiscoverableTimeout(int timeout) | (需要使用反射)获取和设置默认蓝牙可见时间 |
| startDiscovery | 开始扫描其他蓝牙 |
| cancelDiscovery | 取消扫描 |
| isDiscovering | 是否在扫描中 |
| getBondedDevices | 获取已绑定蓝牙 |
| getConnectionState | 获取蓝牙连接状态。STATE_CONNECTED(已连接)、STATE_DISCONNECTED(未连接)、STATE_CONNECTING(连接中) |
添加广播
初始化之后就需要监听蓝牙的广播,不然无法获取搜索到了蓝牙设备
//绑定广播
IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothDevice.ACTION_FOUND);//找到设备的广播
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);//搜索完成的广播
filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);//蓝牙状态改变的广播
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);//开始扫描的广播
filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);//配对状态改变
registerReceiver(mReceiver, filter);
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
BluetoothDevice bluetoothDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// Log.e("-s-", "action = " + action);
switch (action) {
//蓝牙状态改变
case BluetoothAdapter.ACTION_STATE_CHANGED:
Log.e("-s-", "蓝牙状态改变");
checkBluetooth();
break;
//开始扫描
case BluetoothAdapter.ACTION_DISCOVERY_STARTED:
Log.e("-s-", "开始扫描蓝牙");
allAdapter.clear();
changeText("开始扫描蓝牙");
showToast("开始扫描蓝牙");
break;
//搜索完成
case BluetoothAdapter.ACTION_DISCOVERY_FINISHED:
Log.e("-s-", "搜索完成");
changeText("搜索完成");
showToast("搜索完成");
break;
//找到设备
case BluetoothDevice.ACTION_FOUND:
Log.e("-s-", "找到设备");
changeText("搜索中...");
printDevice(bluetoothDevice);
allAdapter.add(bluetoothDevice);
break;
//配对状态改变
case BluetoothDevice.ACTION_BOND_STATE_CHANGED:
Log.e("-s-", "配对状态改变");
if (bluetoothDevice.getBondState() == BluetoothDevice.BOND_BONDING) {
changeText(bluetoothDevice.getName() + " 配对中");
Log.e("-s-", "配对中");
} else if (bluetoothDevice.getBondState() == BluetoothDevice.BOND_BONDED) {
changeText(bluetoothDevice.getName() + " 已配对成功");
Log.e("-s-", "已配对成功");
} else {
changeText(bluetoothDevice.getName() + " 已取消配对");
Log.e("-s-", "已取消配对");
}
printDevice(bluetoothDevice);
updataBonds();
break;
default:
}
}
};
以上代码有常用的几个蓝牙相关的广播,这边主要讲下另一个比较需要注意的APIBluetoothDevice
以下表格是常用的BluetoothDevice方法
| 方法 | 说明 |
|---|---|
| getAddress | 获取蓝牙设备的地址 |
| getName | 获取蓝牙设备的名称(可能会空) |
| getType | 获得蓝牙的设备类型。DEVICE_TYPE_UNKNOWN(未知)、DEVICE_TYPE_CLASSIC(br/edr设备)、DEVICE_TYPE_LE(低能量-仅限LE)、DEVICE_TYPE_DUAL(双模,BR/EDR/LE) |
| getAlias | (需要反射调用)获取蓝牙设备的别名(可能会空) |
| getAliasName | (需要反射调用)获取蓝牙的名称,优先别名,别名为空则返回名称,名称也有可能为空 |
| createBond | 启动与远程设备的连接(配对)过程。 |
| createBond(int transport) | (需要反射调用)使用指定的传输启动与远程设备的绑定(配对)过程。TRANSPORT_AUTO(没有偏好的GATT连接)、TRANSPORT_BREDR(优先和BR/EDR设备GATT连接)、TRANSPORT_LE(优先和LE设备GATT连接) |
| cancelBondProcess | (需要反射调用)取消createBond创建的配对请求 |
| removeBond | (需要反射调用)取消设备配对 |
| getBondState | 获取设备的绑定状态。BOND_NONE(未绑定)、BOND_BONDING(绑定中)、BOND_BONDED(已绑定) |
| isConnected | 返回是否有与此设备的打开连接。 |
| getBluetoothClass | 获取远程设备的蓝牙类。 |
正式开启蓝牙
有了BluetoothAdapter的初始化对象和广播监听蓝牙之后就可以开启蓝牙了!
- 强制开启
上面BluetoothAdapter的常用方法里面有一个强制开启蓝牙的方法
//强制开启蓝牙
bluetoothAdapter.enable();
在低于5.0以下的手机会直接打开蓝牙,以上就会以弹窗的形式提示是否允许。
- 正常打开蓝牙
if (!bluetoothAdapter.isEnabled()) {
//单独打开蓝牙 可以连接 默认不可见
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(intent, REQUEST_ENABLE);
}
首先判断了蓝牙是否可用并且没有打开,在正常打开蓝牙。这样打开的蓝牙默认是可连接但不会被其他设备发现。
- 可见打开蓝牙
if (!bluetoothAdapter.isEnabled()) {
//打开蓝牙并且自己蓝牙可见
Intent discoveryIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);//默认是120秒
discoveryIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);//设置持续时间(最多300秒)
startActivityForResult(discoveryIntent, REQUEST_ENABLE);
}
还是一样首先判断了蓝牙是否可用并且没有打开,在正常打开蓝牙。这样打开的蓝牙可以连接并且可以被其他设备发现。
关闭蓝牙
上面BluetoothAdapter的常用方法里面有一个强制关闭蓝牙的方法,正常我们直接使用这个方法就可以了,因为没有其他的方法了。
if (bluetoothAdapter.isEnabled()) {
bluetoothAdapter.disable();
}
搜索蓝牙
- 全部搜索蓝牙
//是否可用并开启蓝牙
if (bluetoothAdapter.isEnabled()) {
//是否在扫描状态
if (bluetoothAdapter.isDiscovering()) {
bluetoothAdapter.cancelDiscovery();
}
//开始扫描
bluetoothAdapter.startDiscovery();
}
调用搜索之后 结果都是在广播中回调的
搜索广播片段如下 添加广播中有完整的片段
String action = intent.getAction();
//获取获得的设备
BluetoothDevice bluetoothDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
switch (action) {
//开始扫描
case BluetoothAdapter.ACTION_DISCOVERY_STARTED:
Log.e("-s-", "开始扫描蓝牙");
...
break;
//搜索完成
case BluetoothAdapter.ACTION_DISCOVERY_FINISHED:
Log.e("-s-", "搜索完成");
...
break;
//找到设备
case BluetoothDevice.ACTION_FOUND:
Log.e("-s-", "找到设备");
//每次会获取到一个设备,可以加入到自己的listview中作为展示
...
break;
}
- 已配对蓝牙
直接取上面的方法getBondedDevices就可以了。
//清空已配对listview的适配器
bondAdapter.clear();
//遍历已配对的Set<BluetoothDevice>
for (BluetoothDevice device : bluetoothAdapter.getBondedDevices()) {
//加入已配对listview的适配器
bondAdapter.add(device);
}
配对蓝牙
由于createBond方法其实没有隐藏,所以可以直接调用方法进行配对,然后再广播中进行监听实现配对成功和失败的提示。
//正常配对
if (device.createBond()) {
Log.e("-s-", "开始配对");
...
} else {
Log.e("-s-", "配对失败");
...
}
或者调用反射来实现配对,网上找到的资料一般都是下面这个。但是上面的正常配对其实也是可以的。
//反射配对
try {
Method method = BluetoothDevice.class.getMethod("createBond");
boolean result = (boolean) method.invoke(device);
if (result) {
Log.e("-s-", "开始配对");
...
}else {
Log.e("-s-", "配对失败");
...
}
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
Log.e("-s-", "配对失败");
...
}
取消配对蓝牙
由于没有取消方法被隐藏了,就必须用反射来实现取消了
//反射取消配对
try {
Method method = BluetoothDevice.class.getMethod("removeBond");
boolean result = (boolean) method.invoke(device);
if (result) {
Log.e("-s-", "取消成功");
....
} else {
Log.e("-s-", "取消失败");
...
}
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
Log.e("-s-", "取消失败");
...
}
全部代码
BlueActivity.class
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.os.ParcelUuid;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Switch;
import android.widget.TextView;
import android.widget.Toast;
import com.gjn.baserecycleradapterlibrary.BaseRecyclerAdapter;
import com.gjn.baserecycleradapterlibrary.RecyclerViewHolder;
import com.gjn.permissionlibrary.PermissionUtils;
import com.gjn.testproject.R;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class BlueActivity extends AppCompatActivity {
private static final int REQUEST_ENABLE = 0x1001;
private static final int REQUEST_DISABLE = 0x1002;
Button btn1, btn2, btn3, btn4, btn5, btn6;
TextView tv;
RecyclerView rv, rv2;
Switch sw;
private BluetoothAdapter bluetoothAdapter;
private BaseRecyclerAdapter<BluetoothDevice> allAdapter;
private BaseRecyclerAdapter<BluetoothDevice> bondAdapter;
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
BluetoothDevice bluetoothDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// Log.e("-s-", "action = " + action);
switch (action) {
//蓝牙状态改变
case BluetoothAdapter.ACTION_STATE_CHANGED:
Log.e("-s-", "蓝牙状态改变");
checkBluetooth();
break;
//开始扫描
case BluetoothAdapter.ACTION_DISCOVERY_STARTED:
Log.e("-s-", "开始扫描蓝牙");
allAdapter.clear();
changeText("开始扫描蓝牙");
showToast("开始扫描蓝牙");
break;
//搜索完成
case BluetoothAdapter.ACTION_DISCOVERY_FINISHED:
Log.e("-s-", "搜索完成");
changeText("搜索完成");
showToast("搜索完成");
break;
//找到设备
case BluetoothDevice.ACTION_FOUND:
Log.e("-s-", "找到设备");
changeText("搜索中...");
printDevice(bluetoothDevice);
allAdapter.add(bluetoothDevice);
break;
//配对状态改变
case BluetoothDevice.ACTION_BOND_STATE_CHANGED:
Log.e("-s-", "配对状态改变");
if (bluetoothDevice.getBondState() == BluetoothDevice.BOND_BONDING) {
changeText(bluetoothDevice.getName() + " 配对中");
Log.e("-s-", "配对中");
} else if (bluetoothDevice.getBondState() == BluetoothDevice.BOND_BONDED) {
changeText(bluetoothDevice.getName() + " 已配对成功");
Log.e("-s-", "已配对成功");
} else {
changeText(bluetoothDevice.getName() + " 已取消配对");
Log.e("-s-", "已取消配对");
}
printDevice(bluetoothDevice);
updataBonds();
break;
default:
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_blue);
PermissionUtils.requestPermissions(this, PermissionUtils.CODE_LOCATION, PermissionUtils.CODE_PHONE);
btn1 = findViewById(R.id.btn_1);
btn2 = findViewById(R.id.btn_2);
btn3 = findViewById(R.id.btn_3);
btn4 = findViewById(R.id.btn_4);
btn5 = findViewById(R.id.btn_5);
btn6 = findViewById(R.id.btn_6);
tv = findViewById(R.id.tv_state);
sw = findViewById(R.id.sw_state);
rv = findViewById(R.id.rv_ly);
rv2 = findViewById(R.id.rv_ypd);
//初始化蓝牙
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (bluetoothAdapter == null) {
Toast.makeText(this, "设备不存在蓝牙", Toast.LENGTH_SHORT).show();
return;
}
//绑定广播
IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothDevice.ACTION_FOUND);//找到设备的广播
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);//搜索完成的广播
filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);//蓝牙状态改变的广播
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);//开始扫描的广播
filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);//配对状态改变
registerReceiver(mReceiver, filter);
//初始化RecyclerView和适配器
rv.setLayoutManager(new LinearLayoutManager(this));
rv2.setLayoutManager(new LinearLayoutManager(this));
allAdapter = new BaseRecyclerAdapter<BluetoothDevice>(this, R.layout.item_blue, null) {
@Override
public void bindData(RecyclerViewHolder holder, BluetoothDevice device, int position) {
holder.setTextViewText(R.id.tv_name, device.getName());
holder.setTextViewText(R.id.tv_address, device.getAddress());
if (BluetoothDevice.BOND_BONDED == device.getBondState()) {
holder.setTextViewText(R.id.tv_state, "已配对");
} else {
holder.setTextViewText(R.id.tv_state, "未配对");
}
}
};
rv.setAdapter(allAdapter);
bondAdapter = new BaseRecyclerAdapter<BluetoothDevice>(this, R.layout.item_blue, null) {
@Override
public void bindData(RecyclerViewHolder holder, BluetoothDevice device, int position) {
holder.setTextViewText(R.id.tv_name, device.getName());
holder.setTextViewText(R.id.tv_address, device.getAddress());
if (BluetoothDevice.BOND_BONDED == device.getBondState()) {
holder.setTextViewText(R.id.tv_state, "已配对");
} else {
holder.setTextViewText(R.id.tv_state, "未配对");
}
}
};
rv2.setAdapter(bondAdapter);
checkBluetooth();
initData();
}
private void initData() {
allAdapter.setOnItemClickListener(new BaseRecyclerAdapter.OnItemClickListener() {
@Override
public void onItemClick(View view, int pos) {
bond(allAdapter.getItem(pos));
}
});
bondAdapter.setOnItemClickListener(new BaseRecyclerAdapter.OnItemClickListener() {
@Override
public void onItemClick(View view, int pos) {
unBond(bondAdapter.getItem(pos));
}
});
btn1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (!bluetoothAdapter.isEnabled()) {
//单独打开蓝牙
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(intent, REQUEST_ENABLE);
}
}
});
btn2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
bluetoothAdapter.enable();
}
});
btn5.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
Method setScanMode = BluetoothAdapter.class.getMethod("setScanMode", int.class);
boolean result = (boolean) setScanMode.invoke(bluetoothAdapter, BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE);
Log.e("-s-", "result = " + result);
Method getDiscoverableTimeout = BluetoothAdapter.class.getMethod("getDiscoverableTimeout");
int time = (int) getDiscoverableTimeout.invoke(bluetoothAdapter);
Log.e("-s-", "time = " + time);
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
});
btn6.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//打开蓝牙并且自己蓝牙可见
Intent discoveryIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);//默认是120秒
discoveryIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);//设置持续时间(最多300秒)
startActivityForResult(discoveryIntent, REQUEST_ENABLE);
}
});
btn3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (bluetoothAdapter.isEnabled()) {
bluetoothAdapter.disable();
}
}
});
btn4.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (bluetoothAdapter.isEnabled()) {
if (bluetoothAdapter.isDiscovering()) {
bluetoothAdapter.cancelDiscovery();
}
bluetoothAdapter.startDiscovery();
}
}
});
}
private void unBond(BluetoothDevice device) {
if (device.getBondState() == BluetoothDevice.BOND_BONDED) {
//反射取消配对
try {
Method method = BluetoothDevice.class.getMethod("removeBond");
boolean result = (boolean) method.invoke(device);
if (result) {
Log.e("-s-", "取消成功");
showToast("取消成功");
} else {
Log.e("-s-", "取消失败");
showToast("取消失败");
}
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
}
private void bond(BluetoothDevice device) {
if (device.getBondState() == BluetoothDevice.BOND_NONE) {
// //反射配对
// try {
// Method method = BluetoothDevice.class.getMethod("createBond");
// boolean result = (boolean) method.invoke(device);
// if (result) {
// Log.e("-s-", "配对成功");
// showToast("配对成功");
// }else {
// Log.e("-s-", "配对失败");
// showToast("配对失败");
// }
// } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
// e.printStackTrace();
// }
//正常配对
if (device.createBond()) {
Log.e("-s-", "开始配对");
tv.setText(device.getName() + " 开始配对");
showToast("开始配对");
} else {
Log.e("-s-", "配对失败");
showToast(device.getName() + " 配对失败");
}
}
}
private void changeText(String str) {
tv.setText(str);
}
private void showToast(String s) {
Toast.makeText(this, s, Toast.LENGTH_SHORT).show();
}
private void checkBluetooth() {
switch (bluetoothAdapter.getScanMode()) {
case BluetoothAdapter.SCAN_MODE_CONNECTABLE:
Log.e("-s-", "蓝牙可连接");
tv.setText("蓝牙可连接");
break;
case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE:
Log.e("-s-", "蓝牙可连接可发现");
tv.setText("蓝牙可连接可发现");
break;
case BluetoothAdapter.SCAN_MODE_NONE:
default:
Log.e("-s-", "蓝牙不可连接不可见");
tv.setText("蓝牙不可连接不可见");
}
if (bluetoothAdapter.isEnabled()) {
sw.setChecked(true);
updataBonds();
} else {
sw.setChecked(false);
allAdapter.clear();
bondAdapter.clear();
}
}
private void updataBonds() {
bondAdapter.clear();
for (BluetoothDevice device : bluetoothAdapter.getBondedDevices()) {
bondAdapter.add(device);
}
}
private void printDevice(BluetoothDevice device) {
Log.e("-s-", "Name = " + device.getName());
Log.e("-s-", "Address = " + device.getAddress());
Log.e("-s-", "BondState = " + device.getBondState());
Log.e("-s-", "Type = " + device.getType());
if (device.getUuids() != null) {
for (ParcelUuid uuid : device.getUuids()) {
Log.e("-s-", "uuid = " + uuid);
}
}
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(mReceiver);
}
}
activity_blue.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.gjn.testproject.blue.BlueActivity">
<Switch
android:id="@+id/sw_state"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:enabled="false"
android:text="蓝牙状态"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text="默认打开蓝牙"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/sw_state" />
<Button
android:id="@+id/btn_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text="强制打开蓝牙"
app:layout_constraintStart_toEndOf="@+id/btn_1"
app:layout_constraintTop_toBottomOf="@+id/sw_state" />
<Button
android:id="@+id/btn_3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text="关闭蓝牙"
app:layout_constraintStart_toEndOf="@+id/btn_2"
app:layout_constraintTop_toBottomOf="@+id/sw_state" />
<Button
android:id="@+id/btn_4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text="搜索蓝牙"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btn_1" />
<Button
android:id="@+id/btn_5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text="设置蓝牙可见"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btn_1" />
<Button
android:id="@+id/btn_6"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text="可见打开蓝牙"
app:layout_constraintStart_toEndOf="@+id/btn_4"
app:layout_constraintTop_toBottomOf="@+id/btn_3" />
<android.support.v7.widget.RecyclerView
android:id="@+id/rv_ypd"
android:layout_width="0dp"
android:layout_height="100dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.032"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView11" />
<android.support.v7.widget.RecyclerView
android:id="@+id/rv_ly"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView12" />
<TextView
android:id="@+id/tv_state"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:text="无操作"
android:textSize="18sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<TextView
android:id="@+id/textView11"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:text="已配对设备"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btn_4" />
<TextView
android:id="@+id/textView12"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text="全部设备"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/rv_ypd" />
</android.support.constraint.ConstraintLayout>
资料
Android BLE 蓝牙开发入门
Android蓝牙开发(一)之打开蓝牙和设备搜索
Android蓝牙开发(二)之蓝牙配对和蓝牙连接