同步操作将从 leesonzhong/Android BLE 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
参考网址https://www.jianshu.com/p/2dba7f067372,android蓝牙BLE(一) —— 扫描
新建工程。在工程的AndroidManifest添加蓝牙权限
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>
在Activity也要动态申请权限,添加下面代码,在启动蓝牙功能前调用initPermission方法申请权限。
//申请多个权限
//1、首先声明一个数组permissions,将需要的权限都放在里面
String[] permissions = new String[]{Manifest.permission.ACCESS_FINE_LOCATION,Manifest.permission.ACCESS_COARSE_LOCATION};
//2、创建一个mPermissionList,逐个判断哪些权限未授予,未授予的权限存储到mPerrrmissionList中
List<String> mPermissionList = new ArrayList<>();
private final int mRequestCode = 200;//权限请求码
//权限判断和申请
private void initPermission() {
mPermissionList.clear();//清空没有通过的权限
//逐个判断你要的权限是否已经通过
for (int i = 0; i < permissions.length; i++) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (checkSelfPermission( permissions[i]) != PackageManager.PERMISSION_GRANTED) {
mPermissionList.add(permissions[i]);//添加还未授予的权限
}
}
}
//申请权限
if (mPermissionList.size() > 0) {//有权限没有通过,需要申请
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(permissions, mRequestCode);
}
}
}
@Override
public void onRequestPermissionsResult(int permsRequestCode, String[] permissions, int[] grantResults) {
switch (permsRequestCode) {
case 200:{
initPermission();
}break;
}
}
获取BluetoothManager和BluetoothAdapt,BluetoothAdapt具备启动蓝牙和扫描蓝牙列表的功能。
//首先获取BluetoothManager
BluetoothManager bluetoothManager=(BluetoothManager)getSystemService(Context.BLUETOOTH_SERVICE);
//获取BluetoothAdapter
BluetoothAdapter mBluetoothAdapter = bluetoothManager.getAdapter();
判断蓝牙是否开启,蓝牙开启后开始扫描。
if (!mBluetoothAdapter.isEnabled()) {
boolean enable = mBluetoothAdapter.enable(); //返回值表示 是否成功打开了蓝牙功能
if (enable){
return;
}
}
if(android.os.Build.VERSION.SDK_INT >= 21) {
//标记当前的为扫描状态
mScanning = true;
//获取5.0新添的扫描类
if (mBLEScanner == null){
//mBLEScanner是5.0新添加的扫描类,通过BluetoothAdapter实例获取。
mBLEScanner = mBluetoothAdapter.getBluetoothLeScanner();
}
//开始扫描
//mScanCallback是ScanCallback实例。
mBLEScanner.startScan(mScanCallback);
} else {
//标记当前的为扫描状态
mScanning = true;
//5.0以下 开始扫描
//mLeScanCallback是BluetoothAdapter.LeScanCallback实例
mBluetoothAdapter.startLeScan(mLeScanCallback);
}
//超过SCAN_TIME时间后停止搜索
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
//停止扫描设备
if(android.os.Build.VERSION.SDK_INT >= 21) {
//标记当前的为未扫描状态
mScanning = false;
mBLEScanner.stopScan(mScanCallback);
} else {
//标记当前的为未扫描状态
mScanning = false;
//5.0以下 停止扫描
mBluetoothAdapter.stopLeScan(mLeScanCallback);
}
}
}, SCAN_TIME);
扫描的方法需要提供对应的callback,callback类里面的函数里面可以得到扫描得到的蓝牙列表。可以用个列表数组添加扫描得到的设备,记得在开始扫描蓝牙前把列表数组清空。
/**
* 搜索蓝牙的结果
*/
private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
//在这里可以把搜索到的设备保存起来
//device.getName();获取蓝牙设备名字
//device.getAddress();获取蓝牙设备mac地址
//这里的rssi即信号强度,即手机与设备之间的信号强度。
if(device.getName()==null){
return;
}
for(int i=0; i<bluetoothDeviceArrayList.size(); i++){
if(device.getAddress().equals(bluetoothDeviceArrayList.get(i).getAddress())){
return;
}
}
bluetoothDeviceArrayList.add(device);
}
};
private ScanCallback mScanCallback = new ScanCallback() {
//当一个蓝牙ble广播被发现时回调
@Override
public void onScanResult(int callbackType, ScanResult result) {
super.onScanResult(callbackType, result);
//扫描类型有开始扫描时传入的ScanSettings相关
//对扫描到的设备进行操作。如:获取设备信息。
BluetoothDevice device = result.getDevice();
if(device.getName()==null){
return;
}
for(int i=0; i<bluetoothDeviceArrayList.size(); i++){
if(device.getAddress().equals(bluetoothDeviceArrayList.get(i).getAddress())){
return;
}
}
bluetoothDeviceArrayList.add(device);
}
//批量返回扫描结果
//@param results 以前扫描到的扫描结果列表。
@Override
public void onBatchScanResults(List<ScanResult> results) {
super.onBatchScanResults(results);
}
//当扫描不能开启时回调
@Override
public void onScanFailed(int errorCode) {
super.onScanFailed(errorCode);
//扫描太频繁会返回ScanCallback.SCAN_FAILED_APPLICATION_REGISTRATION_FAILED,表示app无法注册,无法开始扫描。
//android 7.0后不能在30秒内扫描次数超过5次
}
};
得到蓝牙设备的列表数据后,一般是让用户选择好要连接的设备名称,根据对应的地址获取蓝牙设备BluetoothDevice后,调用连接connectGatt方法进行连接,并获得返回的BluetoothGatt。
final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
mBluetoothGatt = device.connectGatt(getActivity(), false, mGattCallback);//真正的连接。这个方法需要三个参数:一个Context对象,自动连接(boolean值,表示只要BLE设备可用是否自动连接到它)
连接蓝牙设备时需要提供对应的callback,callback类提供了各种连接状态和结果的回调方法。onConnectionStateChange可以得到蓝牙设备连接的状态,可以判断对应蓝牙设备是连接还是断开,连接成功后调用discoverServices方法。onServicesDiscovered可以得到发现的service和service包含的Characteristic,需要调用mBluetoothGatt.discoverServices()。蓝牙发送和接收数据是对Characteristic进行操作,如果没有确定的service和characteristic的UUID,就遍历characteristic获得可写和可读的characteristic存储起来,如果有确定的UUID就只存储对应的characteristic。onCharacteristicWrite可以知道写入到蓝牙外设的特征值是否成功,需要调用mBluetoothGatt.writeCharacteristic。onCharacteristicRead可以得到蓝牙外设发送的特征值,需要调用mBluetoothGatt.readCharacteristic。但是由于不知道蓝牙外设什么时候发送特征值,所以一般不会使用mBluetoothGatt.readCharacteristic方法,而是对Characteristic进行监听。onCharacteristicChanged可以监听到蓝牙外设有发送特征值并得到对应特征值,需要调用mBluetoothGatt.setCharacteristicNotification和mBluetoothGatt.writeDescriptor启动监听,前提是该Characteristic具有NOTIFY属性
//定义蓝牙Gatt回调类
public class daqiBluetoothGattCallback extends BluetoothGattCallback{
//连接状态回调
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
super.onConnectionStateChange(gatt, status, newState);
// status 用于返回操作是否成功,会返回异常码。
// newState 返回连接状态,如BluetoothProfile#STATE_DISCONNECTED、BluetoothProfile#STATE_CONNECTED
//操作成功的情况下
if (status == BluetoothGatt.GATT_SUCCESS){
//判断是否连接码
if (newState == BluetoothProfile.STATE_CONNECTED) {
}else if(newState == BluetoothProfile.STATE_DISCONNECTED){
//判断是否断开连接码
}
}else{
//异常码
}
}
//服务发现回调
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
super.onServicesDiscovered(gatt, status);
}
//特征写入回调
@Override
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicWrite(gatt, characteristic, status);
}
//外设特征值改变回调
@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
super.onCharacteristicChanged(gatt, characteristic);
}
//描述写入回调
@Override
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
super.onDescriptorWrite(gatt, descriptor, status);
}
//特征读取回调
@Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicRead(gatt, characteristic, status);
}
}
对Characteristic设置监听,当特征值改变时,接收到蓝牙外设发送的值,onCharacteristicChanged方法会回调
for (int i=0; i<readCharacteristicArrayList.size(); i++){
BluetoothGattCharacteristic characteristic = readCharacteristicArrayList.get(i);
mBluetoothGatt.setCharacteristicNotification(characteristic, true);
// enable remote notification
List<BluetoothGattDescriptor> gattDescriptors = characteristic.getDescriptors();
for (BluetoothGattDescriptor gattDescriptor : gattDescriptors) {
gattDescriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
mBluetoothGatt.writeDescriptor(gattDescriptor);
}
}
发送给蓝牙外设数据
for (int i=0; i<writeCharacteristicArrayList.size(); i++){
BluetoothGattCharacteristic characteristic = writeCharacteristicArrayList.get(i);
characteristic.setValue(byteArray);
mBluetoothGatt.writeCharacteristic(characteristic);
}
断开蓝牙外设的连接。调用disconnect()后,会触发手机会触发onConnectionStateChange()的回调。但调用完disconnect()紧接着马上调用close(),会终止BluetoothGattCallback#onConnectionStateChange()的回调
mBluetoothGatt.disconnect();
mBluetoothGatt.close();
支持4个蓝牙设备连接并操作,比较简单,使用数组存储不同蓝牙设备的连接状态mConnectionState、蓝牙设备mBluetoothGatt、特征CharacteristicArrayList
private boolean[] mConnectionState = new boolean[]{false,false,false,false} ;//是否正在连
private BluetoothGatt[] mBluetoothGatt = new BluetoothGatt[4];
private List<List<BluetoothGattCharacteristic>> fourWriteCharacteristicArrayList = new ArrayList<>();
private List<List<BluetoothGattCharacteristic>> fourReadCharacteristicArrayList = new ArrayList<>();
private List<List<BluetoothGattCharacteristic>> fourNotifyCharacteristicArrayList = new ArrayList<>();
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。