Android完成BLE5.0低功耗蓝牙扫描界面与功能并读写数据
作者:互联网
写在前面
换工作之后新任务是做个Android的App,用Java写算是前期比较简单的一个工作了(现在突然被公司派去了图像处理也不多说了),目标是完成蓝牙扫描-连接-读写数据。
要求只是一个Demo,对于线程方面要求不高,而且我也是第一次写Android,因此参考的话也可以后期进行自己的修改和整理。
所有参考资料的网址都给了链接,在对于我逻辑阐述不到位的地方,可以点击参考链接参考前辈们的资料。
API
安卓入门:https://www.runoob.com/w3cnote/android-tutorial-toast.html
蓝牙API:https://www.php.cn/manual/view/15887.html ←点击该连接进入应该直接进入到Android的BlueDevice的相关参数
蓝牙基础配置:
App的使用需要开启一些蓝牙的基础配置,在各个参考资料中也提到了。
在项目包中找到AndroidManifest.xml,在里面直接添加蓝牙的基础配置。
注:我的配置是android版本>6.0的,<6.0的话要去掉几个配置,但是现在感觉市面上也没有<6.0的版本了,如果做<6.0的版本可以单独搜一搜(我下面的一些参考连接中也会提到。
<!-- 蓝牙权限 add by momo-->
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH" /> <!-- 基于地理位置 -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <!-- 不支持低功耗蓝牙的是否安装 -->
<uses-feature
android:name="android.hardware.bluetooth_le"
android:required="true" />
<!-- 读写文件的权限 add by momo -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
蓝牙扫描界面
参考链接:https://blog.csdn.net/qq_35270692/article/details/76359873
我的界面如图所示:
界面代码(activity_bluetooth.xml):
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
style="@style/layout_full"
android:orientation="vertical">
<LinearLayout
style="@style/layout_vertical"
android:layout_weight="12"
android:orientation="horizontal">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/startScale"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="开始扫描"
app:backgroundTint="@color/startScale" />
<Button
android:id="@+id/stopScale"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="停止扫描"
app:backgroundTint="@color/stopScale" />
<Button
android:id="@+id/startRead"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="开始读取"
app:backgroundTint="@color/startRead" />
<Button
android:id="@+id/stopRead"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="停止读取"
app:backgroundTint="@color/stopRead" />
<ProgressBar
android:id="@+id/progressbar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="stopScale" />
<ListView
android:id="@+id/listview"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</ListView>
</LinearLayout>
</LinearLayout>
</LinearLayout>
color等一些参数可以自行设置
创建界面内嵌的listview(layout_listview_item)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<TextView
android:id="@+id/device_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="蓝牙设备名字"
android:layout_margin="2dp"
/>
<TextView
android:id="@+id/device_address"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="蓝牙设备的名字"
android:layout_margin="5dp"
/>
<TextView
android:id="@+id/device_status"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="蓝牙设备的状态" />
</LinearLayout>
蓝牙扫描功能
参考连接1:https://blog.csdn.net/qq_39326574 ←这位前辈的博客里写了蓝牙的扫描和读写数据,是最为简单直白的,适合有较好基础的或者较为熟悉蓝牙的朋友学习。
参考链接2:https://www.cnblogs.com/littlecarry/p/11889982.html ←这位前辈是从原理出发详解BLE扫描的基础,可以认真研读一下明白蓝牙收发的机制。
知识点参考:获取当前链接的蓝牙设备
知识点参考:Android检查设备连接状态
知识点参考:Android : BluetoothAdapter.LeScanCallback
知识点参考:蓝牙扫描 LeScanCallback 方法 不回调
知识点参考:BLE的connect()和connectGatt的区别
-------------------------------------------------------------------------
以上是我学习过程中受益匪浅的前辈资料,当遇到问题也许可以通过这些链接找到答案。
接下来是蓝牙扫描功能的代码。
1.新建一个java class,定义蓝牙对象
public class BlueTooth_item_Bean {
String blueToothDevice_Name; //蓝牙设备的名字
String blueToothDevice_Adress; //蓝牙设备的mac地址
String blueToothDevice_ConectStatus; //连接状态
//判断内容是否相等
@Override
public boolean equals(Object obj) {
if(obj instanceof BlueTooth_item_Bean){
if(blueToothDevice_Adress.equals(((BlueTooth_item_Bean) obj).blueToothDevice_Adress)
/*&& blueToothDevice_Name.equals(((BlueTooth_item_Bean) obj).blueToothDevice_Name)*/
){
return true;
}
}else{
return false;
}
return super.equals(obj);
}
@Override
public int hashCode() {
return blueToothDevice_Adress.hashCode();
}
public String getBlueToothDevice_Name() {
return blueToothDevice_Name;
}
public void setBlueToothDevice_Name(String blueToothDevice_Name) {
this.blueToothDevice_Name = blueToothDevice_Name;
}
public String getBlueToothDevice_Adress() {
return blueToothDevice_Adress;
}
public void setBlueToothDevice_Adress(String blueToothDevice_Adress) {
this.blueToothDevice_Adress = blueToothDevice_Adress;
}
public String getBlueToothDevice_ConectStatus() {
return blueToothDevice_ConectStatus;
}
public void setBlueToothDevice_ConectStatus(String blueToothDevice_ConectStatus) {
this.blueToothDevice_ConectStatus = blueToothDevice_ConectStatus;
}
}
2.新建java class,定义显示文本
public class ListViewAdapter extends BaseAdapter {
private Context mcontext; //上下文
private List<BlueTooth_item_Bean> listDatas; //listview需要用到的信息包括蓝牙名字和蓝牙设备的mac地址;
private LayoutInflater layoutInflater;
ListViewAdapter(Context mcontext, List<BlueTooth_item_Bean> listDatas){
this.mcontext = mcontext;
this.listDatas = listDatas;
layoutInflater = LayoutInflater.from(mcontext);
}
@Override
public int getCount() {
return listDatas.size();
}
@Override
public Object getItem(int position) {
return listDatas.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View view, ViewGroup parent) {
ListviewHolder listviewHolder;
if(view ==null){
listviewHolder = new ListviewHolder();
view = layoutInflater.inflate(R.layout.layout_listview_item,null);
listviewHolder.device_Name = (TextView) view.findViewById(R.id.device_name);
listviewHolder.device_Address= (TextView) view.findViewById(R.id.device_address);
listviewHolder.device_ConectStatus = (TextView) view.findViewById(R.id.device_status);
view.setTag(listviewHolder);
}else{
listviewHolder = (ListviewHolder) view.getTag();
}
listviewHolder.device_Name.setText(listDatas.get(position).blueToothDevice_Name);
listviewHolder.device_Address.setText(listDatas.get(position).blueToothDevice_Adress);
listviewHolder.device_ConectStatus.setText(listDatas.get(position).blueToothDevice_ConectStatus);
return view;
}
static class ListviewHolder{
private TextView device_Name;
private TextView device_Address;
private TextView device_ConectStatus;
}
}
3.在activity里定义全局变量
private static final int REQUEST_CODE_LOCATION_SETTINGS = 2; //用于Gps打开
private BluetoothManager bluetoothManager; //蓝牙管理器
private BluetoothAdapter bluetoothAdapter; //蓝牙适配器
private static final int REQUEST_ENABLE_BLE = 1; //蓝牙请求
private static final long SCALE_PERIOD= 10*1000; //扫描时长 10秒
private static final String READ_SERVICE_UUID = "0000ffe0-0000-1000-8000-00805f9b34fb";
private static final String READ_CHARACTERISTICS_UUID = "0000ffe1-0000-1000-8000-00805f9b34fb"; //读的这个特征值的uuid
//布局中的控件
private Button startScaleButton; //开始扫描按钮
private Button stopScaleButton; //停止扫描按钮
private Button startReadButton; //开始读数据
private Button stopReadButtion; //停止读数据
private ListView listview; //展示扫描到的结果Listview;
private List<BlueTooth_item_Bean> BlueToothDevice_Info; //蓝牙设备的信息
private ListViewAdapter adapter; //这个是定义的ListView的内部Listview_item的
private ProgressBar progressbar;
private Handler handler;
private TextView noiseTextView;
private TextView attentionTextView;
private TextView meditationTextView;
private static final int REQUEST_CODE_ACCESS_COARSE_LOCATION = 1; //动态申请权限
private BluetoothGatt mGatt;//通讯协议
RunThread t1 = new RunThread(); //读写线程
private BottomNavigationView bottomNavigation;
private BlueTooth_item_Bean blueTooth_item_bean;
4.onCreate函数
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bluetooth); //设置连接界面
initView(); //初始化控件
initEvent(); //初始化事件
initData(); //初始化数据
adapter = new ListViewAdapter(Ble1Activity.this,BlueToothDevice_Info); //listView的适配器
listview.setAdapter(adapter); //将获取到的数据放入展示列表
checkPermission(); //判断SD卡是否存在
//检测当前设备是否支持蓝牙ble
if(!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)){
Toast.makeText(Ble1Activity.this, "当前蓝牙不支持蓝牙设备", Toast.LENGTH_SHORT).show();
finish();
}
//通过蓝牙管理器得到一个蓝牙适配器
bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
bluetoothAdapter = bluetoothManager.getAdapter();
if(bluetoothAdapter==null){
Toast.makeText(Ble1Activity.this,"该设备不支持蓝牙",Toast.LENGTH_SHORT).show();
}
//android6.0之后要求有定位权限才可以扫描到蓝牙
//动态申请权限
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.M){ //如果api版本大于23Android6.0的时候
//判断是否具有权限
if(ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)!= PackageManager.PERMISSION_GRANTED){
//判断是否需要向用户解释为什么需要申请权限
if(ActivityCompat.shouldShowRequestPermissionRationale(this,Manifest.permission.ACCESS_COARSE_LOCATION)){
Toast.makeText(Ble1Activity.this,"需要获取定位才可以使用BLE扫描",Toast.LENGTH_SHORT).show();
}
//请求权限
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},REQUEST_CODE_ACCESS_COARSE_LOCATION);//请求码
}
}
clickListView();
}
5.各类界面的初始化
//控件初始化
private void initData() {
//用于定时取消扫描
handler = new Handler();
//模拟蓝牙设备的信息
BlueToothDevice_Info = new ArrayList<>();
/* for(int i = 0 ;i<3;i++){
BlueTooth_item_Bean bluetooth_device_item_info = new BlueTooth_item_Bean();
bluetooth_device_item_info.blueToothDevice_Name = "蓝牙设备名字"+i;
bluetooth_device_item_info.blueToothDevice_Adress = "蓝牙设备mac地址"+i;
bluetooth_device_item_info.blueToothDevice_ConectStatus = "蓝牙设备状态"+i;
BlueToothDevice_Info.add(bluetooth_device_item_info);
}*/
}
private void initView() {
startScaleButton = (Button)findViewById(R.id.startScale); //初始化控件。开始扫描按钮
stopScaleButton= (Button)findViewById(R.id.stopScale); //初始化控件,停止扫描按钮
startReadButton = findViewById(R.id.startRead); //初始化控件,开始读数据
stopReadButtion = findViewById(R.id.stopRead); //初始化控件,停止读数据
listview = (ListView) findViewById(R.id.listview); //用于展示扫描到的设备信息,Listview
progressbar = (ProgressBar) findViewById(R.id.progressbar);
progressbar.setVisibility(View.GONE);
}
private void initEvent() {
startScaleButton.setOnClickListener(this); //开始扫描事件
stopScaleButton.setOnClickListener(this); //停止扫描
startReadButton.setOnClickListener(this); //开始读数据
stopReadButtion.setOnClickListener(this); //停止读数据
}
6.各类click事件的初始化
//蓝牙点击事件
private void clickListView() {
//请求到蓝牙后,点击搜索到的蓝牙进行连接
listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
blueTooth_item_bean = BlueToothDevice_Info.get(i); //获取当前click事件的蓝牙对象
if(blueTooth_item_bean.getBlueToothDevice_Adress()==null){
Toast.makeText(Ble1Activity.this,"请扫描蓝牙",Toast.LENGTH_SHORT).show();
return;
}
BluetoothDevice device = bluetoothAdapter.getRemoteDevice(blueTooth_item_bean.getBlueToothDevice_Adress()); //根据蓝牙地址获取设备信息
if(device != null && blueTooth_item_bean.getBlueToothDevice_ConectStatus() != "连接成功") { //判空校验
mGatt = device.connectGatt(Ble1Activity.this, true, mBluetoothGattCallback); //进行连接
//连接后改写状态
blueTooth_item_bean.blueToothDevice_ConectStatus = "连接中...";
for (int j = 0; j < BlueToothDevice_Info.size(); j++) {
if(BlueToothDevice_Info.get(j).getBlueToothDevice_Adress().equals(blueTooth_item_bean.getBlueToothDevice_Adress())){ //移除蓝牙设备重新添加
BlueToothDevice_Info.remove(j);
break;
}
}
BlueToothDevice_Info.add(blueTooth_item_bean);
adapter.notifyDataSetChanged();
}else{ //断开蓝牙连接
mGatt.disconnect();
mGatt.close();
//修改状态
blueTooth_item_bean = BlueToothDevice_Info.get(i); //获取当前click事件的蓝牙对象
//连接后改写状态
blueTooth_item_bean.blueToothDevice_ConectStatus = "尚未匹配";
for (int j = 0; j < BlueToothDevice_Info.size(); j++) {
if(BlueToothDevice_Info.get(j).getBlueToothDevice_Adress().equals(blueTooth_item_bean.getBlueToothDevice_Adress())){ //移除蓝牙设备重新添加
BlueToothDevice_Info.remove(j);
break;
}
}
BlueToothDevice_Info.add(blueTooth_item_bean);
adapter.notifyDataSetChanged();
}
}
});
}
//界面按钮点击事件
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
@Override
public void onClick(View view) {
switch (view.getId()){
case R.id.startScale: //扫描操作 (扫描一定的事件就自动关闭扫描)
//每次扫描之前都断开已经有的蓝牙连接
if(mGatt != null){
mGatt.disconnect();
mGatt.close();
}
BlueToothDevice_Info.clear();
progressbar.setVisibility(View.VISIBLE);
bluetoothAdapter.startLeScan(mLescaleCallback); //安卓5.0以上后用新的扫描API
/* bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.M) {
//LogUtil.e("系统版本:","<7.0");
bluetoothManager.getAdapter()
.startLeScan(mLescaleCallback);
} else {//安卓7.0及以上的方案
//LogUtil.e("系统版本:",">=7.0");
mBluetoothLeScanner = bluetoothManager.getAdapter().getBluetoothLeScanner();
mBluetoothLeScanner.startScan(scanCallback);
}*/
handler.postDelayed(new Runnable() {
@Override
public void run() {
bluetoothAdapter.stopLeScan(mLescaleCallback);
progressbar.setVisibility(View.GONE);
}
},SCALE_PERIOD);
break;
case R.id.stopScale: //停止扫描
progressbar.setVisibility(View.GONE);
bluetoothAdapter.stopLeScan(mLescaleCallback);
break;
case R.id.startRead:
checkStartRead = true;
//校验是否有设备连接
if(blueTooth_item_bean != null && blueTooth_item_bean.blueToothDevice_ConectStatus != null && blueTooth_item_bean.getBlueToothDevice_ConectStatus().equals("连接成功")){
//Toast.makeText(Ble1Activity.this,"已经连接到蓝牙",Toast.LENGTH_SHORT).show();
//return;
}else{
Toast.makeText(Ble1Activity.this,"尚未连接蓝牙",Toast.LENGTH_SHORT).show();
return;
}
BluetoothGattCharacteristic characteristic= mGatt.getService(UUID.fromString(READ_SERVICE_UUID))
.getCharacteristic(UUID.fromString(READ_CHARACTERISTICS_UUID));
mGatt.readCharacteristic(characteristic);
break;
case R.id.stopRead:
checkStartRead = false;
//校验是否有设备连接
if(blueTooth_item_bean != null && blueTooth_item_bean.blueToothDevice_ConectStatus != null && blueTooth_item_bean.getBlueToothDevice_ConectStatus().equals("连接成功")){
//Toast.makeText(Ble1Activity.this,"已经连接到蓝牙",Toast.LENGTH_SHORT).show();
//return;
}else{
Toast.makeText(Ble1Activity.this,"尚未连接蓝牙",Toast.LENGTH_SHORT).show();
return;
}
break;
}
}
7.权限处理
//请求权限之后的请求处理
// //执行完上面的请求权限后,系统会弹出提示框让用户选择是否允许改权限。选择的结果可以在回到接口中得知:
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if(requestCode==REQUEST_CODE_ACCESS_COARSE_LOCATION){
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//用户允许改权限,0表示允许,-1表示拒绝 PERMISSION_GRANTED = 0, PERMISSION_DENIED = -1
//permission was granted, yay! Do the contacts-related task you need to do.
//这里进行授权被允许的处理
} else {
//permission denied, boo! Disable the functionality that depends on this permission.
//这里进行权限被拒绝的处理
}
} else {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
//检测定位是否打开
public static final boolean isLocationEnable(Context context) {
LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
boolean networkProvider = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
boolean gpsProvider = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
if (networkProvider || gpsProvider) return true;
return false;
}
//如果没有打开,进入定位设置界面,让用户自己选择是否打开定位。选择的结果获取:
private void setLocationService() {
Intent locationIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
this.startActivityForResult(locationIntent, REQUEST_CODE_LOCATION_SETTINGS);
}
@Override
protected void onResume() {
super.onResume();
//确保蓝牙可以使用,如果不可以使用一个弹窗
if(!bluetoothAdapter.enable()){
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(intent,REQUEST_ENABLE_BLE);
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
//不同打开蓝牙
if(requestCode ==REQUEST_ENABLE_BLE && resultCode == RESULT_CANCELED){
finish();
return;
}
//定位
if (requestCode == REQUEST_CODE_LOCATION_SETTINGS) {
if (isLocationEnable(this)) {
//定位已打开的处理
} else {
//定位依然没有打开的处理
Toast.makeText(Ble1Activity.this,"请打开GPS",Toast.LENGTH_SHORT).show();
}
} else super.onActivityResult(requestCode, resultCode, data);
super.onActivityResult(requestCode, resultCode, data);
}
8.扫描的回调函数
//打开蓝牙后扫描的回调函数
//扫描到设备之后的回调方法 安卓5.0以下
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2) //这是一个因为版本号过高所以得进行控制的
private BluetoothAdapter.LeScanCallback mLescaleCallback = new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
if(device.getName()!=null && device.getAddress()!=null) {
runOnUiThread(new Runnable() {
@Override
public void run() {
final BlueTooth_item_Bean bean = new BlueTooth_item_Bean();
bean.blueToothDevice_Name = device.getName();
bean.blueToothDevice_Adress = device.getAddress();
int bondState = device.getBondState(); //对蓝牙状态进行判断
switch (bondState){
case BluetoothDevice.BOND_NONE:
bean.blueToothDevice_ConectStatus = "尚未匹配";
break;
case BluetoothDevice.BOND_BONDING:
bean.blueToothDevice_ConectStatus = "匹配中";
break;
case BluetoothDevice.BOND_BONDED:
bean.blueToothDevice_ConectStatus = "匹配成功";
}
if(BlueToothDevice_Info.contains(bean)) {
//如果集合中已经包含相同的对象,则不添加进去
}else{
BlueToothDevice_Info.add(bean);
adapter.notifyDataSetChanged();
}
}
});
}
}
};
9.蓝牙连接的回调函数
//连接的回调函数
/**
* @description 连接后的回调函数
* @param
* @return
* @author zhujialan
* @time 2021/3/4
*/
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2) //这是一个因为版本号过高所以得进行控制的
BluetoothGattCallback mBluetoothGattCallback=new BluetoothGattCallback() { //连接回调
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
super.onConnectionStateChange(gatt, status, newState);
if (newState == BluetoothProfile.STATE_CONNECTED) {
//System.out.println("连接成功");
gatt.discoverServices(); //跳转到发现蓝牙服务
}else if (newState == BluetoothProfile.STATE_DISCONNECTED) { //断开连接
//System.out.println("断开连接");
//连接后改写状态
blueTooth_item_bean.blueToothDevice_ConectStatus = "尚未连接";
for (int j = 0; j < BlueToothDevice_Info.size(); j++) {
if(BlueToothDevice_Info.get(j).getBlueToothDevice_Adress().equals(blueTooth_item_bean.getBlueToothDevice_Adress())){ //移除蓝牙设备重新添加
BlueToothDevice_Info.remove(j);
break;
}
}
BlueToothDevice_Info.add(blueTooth_item_bean);
/*adapter.notifyDataSetChanged();*/
//只有在线程中才可以进行修改
Ble1Activity.this.runOnUiThread(new Runnable() {
public void run() {
adapter.notifyDataSetChanged();
}
});
mGatt.close();
}
}
10.发现服务
/**
* @description 发现服务
* @param
* @return
* @author zhujialan
* @time 2021/3/4
*/
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
super.onServicesDiscovered(gatt, status);
//System.out.println("onServicesDiscovered: ======发现服务");
List<BluetoothGattService> services = gatt.getServices();
//System.out.println("onServicesDiscovered有几个服务:"+services.size());
//连接后改写状态
blueTooth_item_bean.blueToothDevice_ConectStatus = "连接成功";
for (int j = 0; j < BlueToothDevice_Info.size(); j++) {
if(BlueToothDevice_Info.get(j).getBlueToothDevice_Adress().equals(blueTooth_item_bean.getBlueToothDevice_Adress())){ //移除蓝牙设备重新添加
BlueToothDevice_Info.remove(j);
break;
}
}
BlueToothDevice_Info.add(blueTooth_item_bean);
/*adapter.notifyDataSetChanged();*/
//只有在线程中才可以进行修改
Ble1Activity.this.runOnUiThread(new Runnable() {
public void run() {
adapter.notifyDataSetChanged();
}
});
}
11.读写数据
/**
* @description 读数据
* @param
* @return
* @author zhujialan
* @time 2021/3/4
*/
@Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicRead(gatt, characteristic, status);
for (int i = 0; i < characteristic.getValue().length; i++) {
System.out.println("onCharacteristicRead:读出的值为 "+characteristic.getValue()[i]); //读出的应该是特征数量的数据
}
//直接有UUID写
System.out.println("写入...");
BluetoothGattCharacteristic characteristic = mGatt.getService(UUID.fromString(READ_SERVICE_UUID))
.getCharacteristic(UUID.fromString(READ_CHARACTERISTICS_UUID));
characteristic.setValue("AAAA123456789FFFF");
mGatt.writeCharacteristic(characteristic);
}
/**
* @description 写数据
* @param
* @return
* @author zhujialan
* @time 2021/3/4
*/
@Override
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicWrite(gatt, characteristic, status);
if (status==BluetoothGatt.GATT_SUCCESS){
System.out.println("onCharacteristicWrite: 写入成功");
//gatt.readCharacteristic(characteristic);
//onServicesDiscovered(gatt,status);
}else {
System.out.println("onCharacteristicWrite: 失败");
}
}
};
结尾
时间比较仓促只来得及简单贴上代码。有一些细小的bug等我有时间再慢慢调整。
关于读写那边是有些许问题的,相关的信息可以点击参考文档进行修改。
感谢大家阅读。
标签:blueToothDevice,低功耗,蓝牙,private,BLE5.0,item,bean,Android,public 来源: https://blog.csdn.net/qq_40649119/article/details/115691985