这里直接上代码吧,我这边的应用场景是,比如我扫描附近的体重秤,注意,我扫描的时候,需要过滤,只把扫描到的特定型号的,体重秤
显示出来,比如附近的手机,血压计等都不能扫描出来.同时比如如果有两台体重秤的话,一台离的近,一台离的远,我需要把
离得近的体重秤,在显示的时候,优先显示在上面.根据离扫描设备的距离,做个倒序排序:
这里有个不好的地方,就是,我是用扫描到的设备的蓝牙的名称来进行过滤的,比如体重秤的话,他这个型号的,的蓝牙名称都是以
QN- 开头的,我直接判断,我扫描到的蓝牙设备是否以QN-开头,如果是,就认为是我要的体重秤设备..
实际上,对于不同的设备,连接蓝牙等的操作,要么会提供特定的操作API,来扫描,要么会提供蓝牙的UUID,我们可以通过UUID来过滤.
后面会实现一个用这种方法过滤的版本,再发出来.
这个蓝牙设备的UUID,一般都是一种品牌的机器,是一个UUID,所以可以用UUID进行过滤蓝牙设备.
去看代码吧:
1.这个是MainActivity的onCreate方法,里面initView()方法不用管,
去看看这个initBluetooth方法,用来判断当前设备是否支持蓝牙.后面searchDevices()方法,先不用管,deviceNum也不用管.
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.layout_setting); initView(); //初始化蓝牙设备: initBluetooth(); //搜索蓝牙设备 //searchDevices(); //初始化蓝牙搜索设备编号 deviceNum ="0"; }
2.initBluetooth方法,可以看到这个方法,里面可以判断设备是否支持蓝牙
private void initBluetooth() { bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); if (bluetoothAdapter == null) { Toast.makeText(this, "此设备不支持蓝牙操作", Toast.LENGTH_LONG).show(); return; } }
3.然后,比如我们点击按钮的时候开始扫描.
@Override public void onClick(View v) { int id = v.getId(); if (id == R.id.set_btn_tzc) { .....其他按钮点击处理 }else if(id == R.id.set_btn_ipset){ .....其他按钮点击处理事件 }else if(id == R.id.set_btn_search){ //判断用户是否未选择设备 if(deviceNum.equals("0")){ Toast.makeText(SettingActivity.this,"请选择先你要扫描的设备类型",Toast.LENGTH_SHORT).show(); return; } //1.显示正在扫描 BaseApplication.context().showDialog(SettingActivity.this, "正在扫描请稍后..."); final int[] deviceCount = {0}; macLists = new ArrayList<DeviceInfo>(); //定时器循环 final Timer scanTimer = new Timer(); TimerTask scanTask = new TimerTask(){ public void run() { //Looper.prepare(); if((deviceCount[0] < macLists.size()) && (macLists.size()>0)){ //1.有新设备添加,记录设备数量 deviceCount[0] = macLists.size(); }else if((deviceCount[0] == macLists.size()) && (macLists.size() > 0)){ //2.已经没有新设备被扫描到,扫描结束 BaseApplication.context().closeDialog(); scanTimer.cancel(); //3.按照信号强度排序 Collections.sort(macLists, new ComparatorSort()); ArrayList<String> tempDeviceList = new ArrayList<>(); for (DeviceInfo macList : macLists) { tempDeviceList.add(macList.getName()+"->"+macList.getAddress()); } //搜索蓝牙设备按钮 //String[] items3 = new String[]{"苍老湿", "小泽老湿", "波多野结衣老湿", "吉泽明步老湿"};//创建item final String[] items3 = (String[]) tempDeviceList.toArray(new String[tempDeviceList.size()]);//创建item new Thread(){ @Override public void run() { Looper.prepare(); AlertDialog alertDialog3 = new AlertDialog.Builder(SettingActivity.this) .setTitle("扫描设备列表:") .setIcon(R.mipmap.ic_launcher) .setItems(items3, new DialogInterface.OnClickListener() {//添加列表 @Override public void onClick(DialogInterface dialogInterface, int i) { //Toast.makeText(SettingActivity.this, "点的是:" + items3[i], Toast.LENGTH_SHORT).show(); //EditText mac_edit_text = findViewById(R.id.set_edittext_mac); //获取mac地址 //mac_edit_text.setText(items3[i]); Message message=new Message(); Bundle bundle=new Bundle(); bundle.putString("deviceMac", items3[i]); message.setData(bundle);//b message.what = 310; setMacHandler.sendMessage(message); } }) .create(); alertDialog3.show(); alertDialog3.getWindow().setLayout(1600,800); Looper.loop(); } }.start(); }else if(macLists.size() == 0 ){ BaseApplication.context().closeDialog(); scanTimer.cancel(); //Toast.makeText(this,"121",Toast.LENGTH_SHORT).show(); new Thread(){ @Override public void run() { Looper.prepare(); Toast.makeText(SettingActivity.this, "未扫描到设备", Toast.LENGTH_SHORT).show(); Looper.loop(); } }.start(); } //Looper.loop(); } }; scanTimer.schedule(scanTask,8000,5000); //这里就是说,点击按钮以后,接着去扫描蓝牙设备,先去扫描8秒钟, //然后去判断扫描到了多少设备,然后每隔5秒钟判断是否又扫描到了新设备 //如果没有新设备被扫描到了,这个时候取消timer,停止扫描,用一个alertDialog //来显示结果,并且把离扫描设备近的设备排序到前面. searchDevices(); //这里开始扫描蓝牙设备 } }
4.然后再去看蓝牙扫描方法,searchDevices()
private void searchDevices() { // 3、创建自定义蓝牙服务对象 // 注册Receiver来获取蓝牙设备相关的结果 IntentFilter intent = new IntentFilter("android.bluetooth.device.action.UUID"); intent.addAction(BluetoothDevice.ACTION_FOUND); // 用BroadcastReceiver来取得搜索结果 intent.addAction(BluetoothDevice.EXTRA_UUID); intent.addAction(BluetoothDevice.ACTION_UUID); intent.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED); intent.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); intent.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED); intent.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); registerReceiver(lk_hxq_searchDevices, intent); bluetoothAdapter.startDiscovery(); //BaseApplication.context().showDialog(SettingActivity.this, "正在连接设备..."); }
5.这里lk_hxq_searchDevices()就是扫描蓝牙设备的具体方法了
//2.搜索力康呼吸器设备 private BroadcastReceiver lk_hxq_searchDevices = new BroadcastReceiver() { public void onReceive(Context context, Intent intent) { String action = intent.getAction(); //commLock.lock(); if (action.equals(BluetoothDevice.ACTION_FOUND)) { //found device BluetoothDevice device = intent .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); String uuid = ""; Log.e("Adress001_Address:",device.getAddress()); Log.e("Adress001_Name:",device.getName()+""); Log.e("Adress001_Type:",device.getType()+""); if(device.getUuids()!=null){ ParcelUuid[] uudis = device.getUuids(); for (ParcelUuid uudi : uudis) { uuid = uuid + uudi.toString(); } } Log.e("Adress001_UUID:",uuid+""); //String deviceAddress = device.getName()+"->"+device.getAddress(); String deviceAddress = ""; String deviceName =""; double deviceSignal = 0.0; boolean isFind = false; if(deviceNum.equals("0")){ isFind = false; deviceName = "未知设备"; //deviceAddress = "未知设备->"+ device.getAddress(); deviceAddress = device.getAddress(); }else if(deviceNum.equals("1") && device.getName()!=null && device.getName().toString().startsWith("QN-")){ isFind = true; deviceName = "体重秤"; //deviceAddress = "体重秤->"+ device.getAddress(); deviceAddress = device.getAddress(); }else if(deviceNum.equals("2") && device.getName()!=null && device.getName().toString().startsWith("BPM-")){ isFind = true; deviceName = "血压计"; //deviceAddress = "血压计->"+ device.getAddress(); deviceAddress = device.getAddress(); }else if(deviceNum.equals("3") && device.getName()!=null && device.getName().toString().startsWith("BLE Device-")){ isFind = true; deviceName = "血压计"; //deviceAddress = "三合一->"+ device.getAddress(); deviceAddress = device.getAddress(); }else if(deviceNum.equals("4") && device.getName()!=null && device.getName().toString().startsWith("B20")){ isFind = true; deviceName = "呼吸器"; //deviceAddress = "呼吸器->"+ device.getAddress(); deviceAddress = device.getAddress(); }else if(deviceNum.equals("5") && device.getName()!=null && device.getName().toString().startsWith("weixin-")){ isFind = true; deviceName = "握力球"; //deviceAddress = "握力球->"+ device.getAddress(); deviceAddress = device.getAddress(); }else if(deviceNum.equals("6") && device.getName()!=null && device.getName().toString().startsWith("PC80B-")){ isFind = true; deviceName = "握力球"; //deviceAddress = "心电仪->"+ device.getAddress(); deviceAddress = device.getAddress(); }else if(deviceNum.equals("7")){ deviceName = "未知设备"; //deviceAddress = "未知设备->"+ device.getAddress(); deviceAddress = device.getAddress(); }else if(deviceNum.equals("8")){ deviceName = "未知设备"; //deviceAddress = "未知设备->"+ device.getAddress(); deviceAddress = device.getAddress(); }else{ isFind = false; } //找到检测设备以后,添加到设备列表中去 if(isFind){ if(macLists.contains(deviceAddress)){ }else{ //获取蓝牙信号强度,信号强度强的放在前面 //添加到列表 short rssi = intent.getExtras().getShort( BluetoothDevice.EXTRA_RSSI); int iRssi = abs(rssi); // 将蓝牙信号强度换算为距离 double power = (iRssi - 59) / 25.0; deviceSignal = power; //macLists.add(device.getAddress()); DeviceInfo deviceInfo = new DeviceInfo(); deviceInfo.setAddress(deviceAddress); deviceInfo.setName(deviceName); deviceInfo.setSignal(deviceSignal); macLists.add(deviceInfo); } }else{} mBluetoothGatt = device.connectGatt(SettingActivity.this, false, gattCallback); } else if (BluetoothDevice.ACTION_UUID.equals(action)) { BluetoothDevice device = intent .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); //String deviceAddress = device.getName()+"->"+device.getAddress(); String deviceAddress = ""; String deviceName =""; double deviceSignal = 0.0; boolean isFind = false; if(deviceNum.equals("0")){ isFind = false; deviceName = "未知设备"; //deviceAddress = "未知设备->"+ device.getAddress(); deviceAddress = device.getAddress(); }else if(deviceNum.equals("1") && device.getName()!=null && device.getName().toString().startsWith("QN-")){ isFind = true; deviceName = "体重秤"; //deviceAddress = "体重秤->"+ device.getAddress(); deviceAddress = device.getAddress(); }else if(deviceNum.equals("2") && device.getName()!=null && device.getName().toString().startsWith("BPM-")){ isFind = true; deviceName = "血压计"; //deviceAddress = "血压计->"+ device.getAddress(); deviceAddress = device.getAddress(); }else if(deviceNum.equals("3") && device.getName()!=null && device.getName().toString().startsWith("BLE Device-")){ isFind = true; deviceName = "血压计"; //deviceAddress = "三合一->"+ device.getAddress(); deviceAddress = device.getAddress(); }else if(deviceNum.equals("4") && device.getName()!=null && device.getName().toString().startsWith("B20")){ isFind = true; deviceName = "呼吸器"; //deviceAddress = "呼吸器->"+ device.getAddress(); deviceAddress = device.getAddress(); }else if(deviceNum.equals("5") && device.getName()!=null && device.getName().toString().startsWith("weixin-")){ isFind = true; deviceName = "握力球"; //deviceAddress = "握力球->"+ device.getAddress(); deviceAddress = device.getAddress(); }else if(deviceNum.equals("6") && device.getName()!=null && device.getName().toString().startsWith("PC80B-")){ isFind = true; deviceName = "握力球"; //deviceAddress = "心电仪->"+ device.getAddress(); deviceAddress = device.getAddress(); }else if(deviceNum.equals("7")){ deviceName = "未知设备"; //deviceAddress = "未知设备->"+ device.getAddress(); deviceAddress = device.getAddress(); }else if(deviceNum.equals("8")){ deviceName = "未知设备"; //deviceAddress = "未知设备->"+ device.getAddress(); deviceAddress = device.getAddress(); }else{ isFind = false; } //找到检测设备以后,添加到设备列表中去 if(isFind){ if(macLists.contains(deviceAddress)){ }else{ //获取蓝牙信号强度,信号强度强的放在前面 //添加到列表 short rssi = intent.getExtras().getShort( BluetoothDevice.EXTRA_RSSI); int iRssi = abs(rssi); // 将蓝牙信号强度换算为距离 double power = (iRssi - 59) / 25.0; deviceSignal = power; //macLists.add(device.getAddress()); DeviceInfo deviceInfo = new DeviceInfo(); deviceInfo.setAddress(deviceAddress); deviceInfo.setName(deviceName); deviceInfo.setSignal(deviceSignal); macLists.add(deviceInfo); } }else{} mBluetoothGatt = device.connectGatt(SettingActivity.this, false, gattCallback); } } };
6.扫描到了设备以后,然后会走到,扫描到设备以后的回调函数中去,
然后在回调函数中,可以判断,扫描到的设备具体是不是某个设备,比如判断是不是体重秤,或者是什么设备,这里通过UUID过滤,
不过因为上面我通过蓝牙的名称过滤的,所以我这里就没用到,但是我没有删除代码,实际上是可以通过这种方式过滤的,而且
正常情况下,通过这种方式过滤比较好,因为如果通过蓝牙名称过滤,蓝牙名称如果被修改了,或者有重名的,就会导致,程序,列出
的设备列表不太准确了.
注释掉的部分不用关注,用的时候删除就可以了.
Handler mainHandler = new Handler(); private BluetoothGattCallback gattCallback = new BluetoothGattCallback() { // 这里有9个要实现的方法,看情况要实现那些,用到那些就实现那些 //当连接状态发生改变的时候 @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, final int newState) { mBluetoothGatt.discoverServices(); mainHandler.post(new Runnable() { @Override public void run() { if (newState == BluetoothProfile.STATE_CONNECTED) {// lk_fgn_msg.setText("连接成功,请操作设备测量");// xyy_start.setVisibility(View.GONE);// fgn_sub.setVisibility(View.GONE); //lk_hxq_deviceOnline = true; System.out.println("onConnectionStateChange连接成功"); //BaseApplication.context().closeDialog(); //ToastUtils.toast(SettingActivity.this,"设备启动成功"); } else { //msg = null; //ToastUtils.toast(FaceBodyCheckActivity.this,"点击开始测量");// lk_fgn_msg.setText("点击开始测量");// fgn_sub.setVisibility(View.VISIBLE);// fgn_start.setVisibility(View.VISIBLE); //lk_hxq_deviceOnline = false; //BaseApplication.context().closeDialog(); System.out.println("onConnectionStateChange连接断开"); //Toast.makeText(SettingActivity.this, "设备连接已断开", Toast.LENGTH_SHORT).show(); } } }); } //回调响应特征写操作的结果。 @Override public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { System.out.println(status); if (status == BluetoothGatt.GATT_SUCCESS) { System.out.println("onCharacteristicWrite: 写入成功"); } else { System.out.println("onCharacteristicWrite: 失败"); } } //回调响应特征读操作的结果。 @Override public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { System.out.println(3333333); } //当服务被发现的时候回调的结果 @Override public void onServicesDiscovered(BluetoothGatt gatt, int status) { try { //设置serviceUUID,原型是:BluetoothGattService bluetoothGattService = bluetoothGatt.getService(UUID.fromString(SERVICESUUID)); bluetoothGattService = mBluetoothGatt.getService(UUID.fromString(DeviceFinal.LK_HXQ_SERVICESUUID)); //设置写入特征UUID,原型是:BluetoothGattCharacteristic writeCharacteristic = bluetoothGattService.getCharacteristic(UUID.fromString(WRITEUUID)); writeCharacteristic = bluetoothGattService.getCharacteristic(UUID.fromString(DeviceFinal.LK_HXQ_WRITEUUID)); //设置监听特征UUID,原型是:BluetoothGattCharacteristic notifyCharacteristic = bluetoothGattService.getCharacteristic(UUID.fromString(NOTIFYUUID)); notifyCharacteristic = bluetoothGattService.getCharacteristic(UUID.fromString(DeviceFinal.LK_HXQ_NOTIFYUUID)); //开启监听 //lk_hxq_resultValue = new ArrayList<>(); boolean notification = gatt.setCharacteristicNotification(notifyCharacteristic, true);// if (notification) {// List<BluetoothGattDescriptor> descriptorList = notifyCharacteristic.getDescriptors();// if (descriptorList != null && descriptorList.size() > 0) {// for (BluetoothGattDescriptor descriptor : descriptorList) {// descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);// mBluetoothGatt.writeDescriptor(descriptor);// }// }// }// int properties = notifyCharacteristic.getProperties();//16// System.out.println(notification + "" + properties); } catch (Exception e) { e.printStackTrace(); mainHandler.post(new Runnable() { @Override public void run() {// fgn_start.setVisibility(View.GONE);// fgn_sub.setVisibility(View.GONE);// lk_fgn_msg.setText("所选设备不是呼吸器,请确认后再试!"); //ToastUtils.toast(SettingActivity.this,"所选设备不是呼吸器,请确认后再试!"); System.out.println("所选设备不是呼吸器,请确认后再试!"); } }); } } //接受数据回调 @Override public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { byte[] value = characteristic.getValue(); //final String str = lk_hxq_bytesToHex(value); //System.out.println(str); //lk_hxq_resultValue.add(str); mainHandler.post(new Runnable() { @Override public void run() { //lk_hxq_fgn(); }// xyz.setText("spo2:" + new BigInteger(spo2, 16) + '%' + " pr:" + new BigInteger(pr, 16) + "次/分"); }); } //当连接能被被读的操作 @Override public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) { super.onDescriptorRead(gatt, descriptor, status); System.out.println(555555); } };
7.然后过程中,还用到一个实体类,用来封装蓝牙设备的,信号强度,蓝牙设备的名称,以及蓝牙设备的mac地址的.
DeviceInfo.java
package com.baidu.idl.main.facesdk.utils;public class DeviceInfo { private String name; private String address; private double signal; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public double getSignal() { return signal; } public void setSignal(double signal) { this.signal = signal; }}
放在这里了.