Anroid BLE蓝牙(手机分别作为中心设备和外围设备)

2024-09-07 16:48

本文主要是介绍Anroid BLE蓝牙(手机分别作为中心设备和外围设备),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

        蓝牙是一种短距的无线通讯技术,可实现固定设备、移动设备之间的数据交换。一般将蓝牙3.0之前的BR/EDR蓝牙称为传统蓝牙,而将蓝牙4.0规范下的LE蓝牙称为低功耗蓝牙。

 BLE蓝牙模块主要应用领域

    1、移动扩展设备

    2、汽车电子设备

    3、健康医疗用品:心跳带、血压计等

    4、定位应用:室内定位、井下定位等

    5、近距离数据采集:无线抄表、无线遥测等

    6、数据传输:智能家居室内控制、蓝牙调光、打印机等

   手机作为中心设备连接外围设备 蓝牙的操作流程

        1.声明蓝牙权限               

<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH_PRIVILEGED" />

   在 Android 6.0 及以上,还需要打开位置权限。如果应用没有位置权限,蓝牙扫描功能不能使用

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>

    2.判断设备是否支持BLE蓝牙

        

public boolean isSupportBle() {return mContext.getApplicationContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE);
}

   3.初始化蓝牙


public BleBluetooth(Context context) {this.context = context = context.getApplicationContext();
    bluetoothManager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);
    bluetoothAdapter = bluetoothManager.getAdapter();
}

4.是否开启蓝牙

public boolean isBlueEnable() {return bluetoothAdapter.isEnabled();
}

5.开启蓝牙

public void enableBluetooth() {bluetoothAdapter.enable();
}

6.扫描蓝牙

    6.0以上要动态设置权限

public void scanDevice(BluetoothAdapter.LeScanCallback callback, Activity activity) {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {// Android M Permission check
        if (activity.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) !=PackageManager.PERMISSION_GRANTED) {//TODO 权限适配 终止
            activity.requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, PERMISSION_REQUEST_COARSE_LOCATION);
        } else {
    mbluetoothAdapter.startLeScan(callBack);
} } else {
    mbluetoothAdapter.startLeScan(callBack);
}} @Override public void onRequestPermissionsResult( int requestCode , String[] permissions , int[] grantResults) { super.onRequestPermissionsResult(requestCode , permissions , grantResults) ; switch (requestCode) { case PERMISSION_REQUEST_COARSE_LOCATION: if (grantResults[ 0] == PackageManager. PERMISSION_GRANTED) {
        mbluetoothAdapter.startLeScan(callBack);
} break; }}
mbluetoothAdapter.startLeScan(callBack);
 
BluetoothAdapter.LeScanCallback callBack = new BluetoothAdapter.LeScanCallback() {@Override
    public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {//TODO 处理扫描到的结果
        Device = device;
    }
}; 

6.连接蓝牙

7.寻找服务,并打开

Device.connectGatt(this,false,coreGattCallback);
 
BluetoothGattCallback connectCallback = new BluetoothGattCallback() {@Override
    public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {super.onConnectionStateChange(gatt, status, newState);
       //TODO 蓝牙连接状态的回调,在这里根据newState判断蓝牙是否连接成功
        if (newState == BluetoothGatt.STATE_CONNECTED) {mbluetoothGatt = gatt;
        } else if (newState == BluetoothGatt.STATE_DISCONNECTED) {} else if (newState == BluetoothGatt.STATE_CONNECTING) {}}@Override
    public void onServicesDiscovered(BluetoothGatt gatt, int status) {super.onServicesDiscovered(gatt, status);
       //TODO 在发方法中找服务并找到可通知的特征值
        BluetoothGattService bleService = gatt.getService(UUID.fromString("0000fee7-0000-1000-8000-00805f9b34fb"));
        List<BluetoothGattCharacteristic> characteristics = bleService.getCharacteristics();
        for (BluetoothGattCharacteristic characteristic :characteristics) {int charaProp = characteristic.getProperties();
            //找到可通知的特征
            UUID_NOFITY = characteristic.getUuid();
            if ((charaProp & BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) {//使所有的描述可通知
                for (BluetoothGattDescriptor descripter : characteristic.getDescriptors()){descripter.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
                    gatt.writeDescriptor(descripter);
                }}else if((charaProp & BluetoothGattCharacteristic.PROPERTY_INDICATE) > 0){//使所有的描述可通知
                UUID_INDICATE = characteristic.getUuid();
                for (BluetoothGattDescriptor descripter : characteristic.getDescriptors()){descripter.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
                    gatt.writeDescriptor(descripter);
                }}}//根据notify还是indicate来设置可写的描述
        for (BluetoothGattCharacteristic characteristic :characteristics) {int charaProp = characteristic.getProperties();
            if((charaProp & BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) > 0
                    || (charaProp & BluetoothGattCharacteristic.PROPERTY_WRITE) > 0){UUID_WRITE = characteristic.getUuid();

                //使所有的描述可通知
                for (BluetoothGattDescriptor descripter : characteristic.getDescriptors()){if(UUID_NOFITY != null && UUID_INDICATE == null){descripter.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
                    }else if(UUID_INDICATE != null && UUID_NOFITY == null){descripter.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
                    }gatt.writeDescriptor(descripter);
                }}}}@Override
    public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {super.onCharacteristicRead(gatt, characteristic, status);
    }@Override
    public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {super.onCharacteristicWrite(gatt, characteristic, status);
        //TODO 在这里判断想设备是否写数据成功
    }@Override
    public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {super.onCharacteristicChanged(gatt, characteristic);
        //TODO 接受设备上发是数据
    }@Override
    public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {super.onDescriptorRead(gatt, descriptor, status);
    }@Override
    public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {super.onDescriptorWrite(gatt, descriptor, status);
 
 } 
@Override 
  
public void  
onReliableWriteCompleted(BluetoothGatt gatt 
, int status) { 
super.onReliableWriteCompleted(gatt 
, status) 
; 
 } 
@Override 
  
public void  
onReadRemoteRssi(BluetoothGatt gatt 
, int rssi 
, int status) { 
super.onReadRemoteRssi(gatt 
, rssi 
, status) 
; 
 } 
@Override 
  
public void  
onMtuChanged(BluetoothGatt gatt 
, int mtu 
, int status) { 
super.onMtuChanged(gatt 
, mtu 
, status) 
; 
 }} 
; 

8.断开蓝牙

mbluetoothGatt.close();

手机作为外围设备,发送广播供中心设备连接

1.获取BluetoothLeAdvertiser实例

private void initialize(){if(mBluetoothLeAdvertiser==null){mBluetoothManager=(BluetoothManager)getSystemService(Context.BLUETOOTH_SERVICE);
        if(mBluetoothManager!=null){BluetoothAdapter bluetoothAdapter=mBluetoothManager.getAdapter();
            if(bluetoothAdapter!=null){mBluetoothLeAdvertiser=bluetoothAdapter.getBluetoothLeAdvertiser();
            }else{Toast.makeText(this,"设备不支持蓝牙广播",Toast.LENGTH_SHORT).show();
            }}else{Toast.makeText(this,"不支持蓝牙",Toast.LENGTH_SHORT).show();
        }}
}
2.设置参数
private AdvertiseSettings buildAdvertiseSettings(){AdvertiseSettings.Builder settingsBuilder=new AdvertiseSettings.Builder();
    settingsBuilder.setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_POWER);
    settingsBuilder.setTimeout(0);

    return settingsBuilder.build();
}
private AdvertiseData buildAdvertiseData(){AdvertiseData.Builder dataBuilder=new AdvertiseData.Builder();
    dataBuilder.setIncludeDeviceName(true);

    return dataBuilder.build();
}
3.开始广播
private void startAdvertising(){Log.d(TAG,"服务开始广播");
    if(mAdertiseCallback==null){AdvertiseSettings settings=buildAdvertiseSettings();
        AdvertiseData data=buildAdvertiseData();
        mAdertiseCallback=new SampleAdvertiseCallback();

        if(mBluetoothLeAdvertiser!=null){mBluetoothLeAdvertiser.startAdvertising(settings,data,mAdertiseCallback);
        }}
}
4.广播回调
private class SampleAdvertiseCallback extends AdvertiseCallback{@Override
    public void onStartFailure(int errorCode){super.onStartFailure(errorCode);

        Log.d(TAG,"广播失败");
        sendFailureIntent(errorCode);
        stopSelf();
    }@Override
    public void onStartSuccess(AdvertiseSettings settingsInEffect){super.onStartSuccess(settingsInEffect);
        Log.d(TAG,"服务端的广播成功开启");
        initServices(getContext());//该方法是添加一个服务,在此处调用即将服务广播出去
    }
}
5. 为设备添加服务
 private void initServices(Context context){
//        获取BluetoothGattServer的实例
        mBluetoothGattServer=mBluetoothManager.openGattServer(context,bluetoothGattServerCallback);
        BluetoothGattService service=new BluetoothGattService(UUID_SERVER,BluetoothGattService.SERVICE_TYPE_PRIMARY);

        characteristicRead=new BluetoothGattCharacteristic(UUID_CHARREAD,BluetoothGattCharacteristic.PROPERTY_READ,BluetoothGattCharacteristic.PERMISSION_READ);
        service.addCharacteristic(characteristicRead);

         characteristicWrite=new BluetoothGattCharacteristic(UUID_CHARWRITE,
                BluetoothGattCharacteristic.PROPERTY_WRITE ,
                BluetoothGattCharacteristic.PERMISSION_WRITE);
        service.addCharacteristic(characteristicWrite);


        characteristicIndicate = new BluetoothGattCharacteristic(UUID_INDICATE,
                BluetoothGattCharacteristic.PROPERTY_INDICATE,
                BluetoothGattCharacteristic.PERMISSION_WRITE);
        BluetoothGattDescriptor descriptor=new BluetoothGattDescriptor(UUID_DESCRIPTOR,BluetoothGattCharacteristic.PERMISSION_WRITE);
        characteristicIndicate.addDescriptor(descriptor);
        service.addCharacteristic(characteristicIndicate);

        mBluetoothGattServer.addService(service);
    }
6.服务回调
//服务事件的回调
private BluetoothGattServerCallback bluetoothGattServerCallback=new BluetoothGattServerCallback() {//1、首先是连接状态的回调
    @Override
    public void onConnectionStateChange(BluetoothDevice device, int status, int newState) {super.onConnectionStateChange(device, status, newState);
        Log.e(TAG,"连接状态发生改变,安卓系统回调onConnectionStateChange:device name="+device.getName()+"address="+device.getAddress()+"status="+status+"newstate="+newState);
    }@Override
    public void onCharacteristicReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattCharacteristic characteristic) {super.onCharacteristicReadRequest(device, requestId, offset, characteristic);
        Log.e(TAG,"客户端有读的请求,安卓系统回调该onCharacteristicReadRequest()方法");

        mBluetoothGattServer.sendResponse(device,requestId, BluetoothGatt.GATT_SUCCESS,offset,characteristic.getValue());
    }//接受具体字节,当有特征被写入时,回调该方法,写入的数据为参数中的value
    @Override
    public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId, BluetoothGattCharacteristic characteristic, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) {super.onCharacteristicWriteRequest(device, requestId, characteristic, preparedWrite, responseNeeded, offset, value);
        Log.e(TAG,"客户端有写的请求,安卓系统回调该onCharacteristicWriteRequest()方法");

        //特征被读取,在该回调方法中回复客户端响应成功
        mBluetoothGattServer.sendResponse(device,requestId,BluetoothGatt.GATT_SUCCESS,offset,value);

        //处理响应内容
        //value:客户端发送过来的数据
        onResponseToClient(value,device,requestId,characteristic);
    }//特征被读取。当回复相应成功后,客户端胡读取然后触发本方法
    @Override
    public void onDescriptorReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattDescriptor descriptor) {super.onDescriptorReadRequest(device, requestId, offset, descriptor);

        mBluetoothGattServer.sendResponse(device,requestId,BluetoothGatt.GATT_SUCCESS,offset,null);
    }//2、其次,当有描述请求被写入时,回调该方法,
    @Override
    public void onDescriptorWriteRequest(BluetoothDevice device, int requestId, BluetoothGattDescriptor descriptor, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) {super.onDescriptorWriteRequest(device, requestId, descriptor, preparedWrite, responseNeeded, offset, value);

        mBluetoothGattServer.sendResponse(device,requestId,BluetoothGatt.GATT_SUCCESS,offset,value);
       // onResponseToClient(value,device,requestId,descriptor.getCharacteristic());
    }@Override
    public void onServiceAdded(int status,BluetoothGattService service){super.onServiceAdded(status,service);
        Log.e(TAG,"添加服务成功,安卓系统回调该onServiceAdded()方法");
    }
};

参考连接
BLE源码

1、蓝牙Bluetooth BR/EDR 和 Bluetooth Smart 必需要知道的十个不同点 
2、BLE简介和Android BLE编程 

3、BLE广播数据解析

4、BLE学习

5 Android Bluetooth api

这篇关于Anroid BLE蓝牙(手机分别作为中心设备和外围设备)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/1145599

相关文章

Nacos注册中心和配置中心的底层原理全面解读

《Nacos注册中心和配置中心的底层原理全面解读》:本文主要介绍Nacos注册中心和配置中心的底层原理的全面解读,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录临时实例和永久实例为什么 Nacos 要将服务实例分为临时实例和永久实例?1.x 版本和2.x版本的区别

SpringCloud使用Nacos 配置中心实现配置自动刷新功能使用

《SpringCloud使用Nacos配置中心实现配置自动刷新功能使用》SpringCloud项目中使用Nacos作为配置中心可以方便开发及运维人员随时查看配置信息,及配置共享,并且Nacos支持配... 目录前言一、Nacos中集中配置方式?二、使用步骤1.使用$Value 注解2.使用@Configur

电脑蓝牙连不上怎么办? 5 招教你轻松修复Mac蓝牙连接问题的技巧

《电脑蓝牙连不上怎么办?5招教你轻松修复Mac蓝牙连接问题的技巧》蓝牙连接问题是一些Mac用户经常遇到的常见问题之一,在本文章中,我们将提供一些有用的提示和技巧,帮助您解决可能出现的蓝牙连接问... 蓝牙作为一种流行的无线技术,已经成为我们连接各种设备的重要工具。在 MAC 上,你可以根据自己的需求,轻松地

Android与iOS设备MAC地址生成原理及Java实现详解

《Android与iOS设备MAC地址生成原理及Java实现详解》在无线网络通信中,MAC(MediaAccessControl)地址是设备的唯一网络标识符,本文主要介绍了Android与iOS设备M... 目录引言1. MAC地址基础1.1 MAC地址的组成1.2 MAC地址的分类2. android与I

嵌入式Linux之使用设备树驱动GPIO的实现方式

《嵌入式Linux之使用设备树驱动GPIO的实现方式》:本文主要介绍嵌入式Linux之使用设备树驱动GPIO的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录一、设备树配置1.1 添加 pinctrl 节点1.2 添加 LED 设备节点二、编写驱动程序2.1

Android实现两台手机屏幕共享和远程控制功能

《Android实现两台手机屏幕共享和远程控制功能》在远程协助、在线教学、技术支持等多种场景下,实时获得另一部移动设备的屏幕画面,并对其进行操作,具有极高的应用价值,本项目旨在实现两台Android手... 目录一、项目概述二、相关知识2.1 MediaProjection API2.2 Socket 网络

使用Python实现全能手机虚拟键盘的示例代码

《使用Python实现全能手机虚拟键盘的示例代码》在数字化办公时代,你是否遇到过这样的场景:会议室投影电脑突然键盘失灵、躺在沙发上想远程控制书房电脑、或者需要给长辈远程协助操作?今天我要分享的Pyth... 目录一、项目概述:不止于键盘的远程控制方案1.1 创新价值1.2 技术栈全景二、需求实现步骤一、需求

Python实现自动化接收与处理手机验证码

《Python实现自动化接收与处理手机验证码》在移动互联网时代,短信验证码已成为身份验证、账号注册等环节的重要安全手段,本文将介绍如何利用Python实现验证码的自动接收,识别与转发,需要的可以参考下... 目录引言一、准备工作1.1 硬件与软件需求1.2 环境配置二、核心功能实现2.1 短信监听与获取2.

Spring Cloud之注册中心Nacos的使用详解

《SpringCloud之注册中心Nacos的使用详解》本文介绍SpringCloudAlibaba中的Nacos组件,对比了Nacos与Eureka的区别,展示了如何在项目中引入SpringClo... 目录Naacos服务注册/服务发现引⼊Spring Cloud Alibaba依赖引入Naco编程s依

Python自动化处理手机验证码

《Python自动化处理手机验证码》手机验证码是一种常见的身份验证手段,广泛应用于用户注册、登录、交易确认等场景,下面我们来看看如何使用Python自动化处理手机验证码吧... 目录一、获取手机验证码1.1 通过短信接收验证码1.2 使用第三方短信接收服务1.3 使用ADB读取手机短信1.4 通过API获取