Android 低功耗蓝牙(BLE)开发(4)-- 蓝牙扫描和连接
2017-01-13 22:35
741 查看
在了解了API里面的常用类和方法后,现在来看蓝牙打开和扫描的实现
1.添加权限
2.判断设备是否支持BLE
3.判断蓝牙是否开启,如果未开启,则弹出开启窗口
4.开启后,开始进行蓝牙扫描
5.通过BluetoothAdapter.LeScanCallback获取扫描结果
下面具体来实现蓝牙的扫描过程
1.权限的添加
在AndroidManifest.xml文件里面添加:
除了蓝牙权限外,如果需要BLE feature则还需要声明uses-feature:
required为true时,则应用只能在支持BLE的Android设备上安装运行;required为false时,Android设备均可正常安装运行,需要在代码运行时判断设备是否支持BLE feature
2.判断设备是否支持BLE
因为在Api18(4.3)以下是不支持BLE的,如果系统版本小于4.3,则不会再进行下一步操作,在4.3以上的系统中,则去获取BluetoothAdapter, BluetoothAdapter是从系统服务获取到的,全系统就一个,获取到BluetoothAdapter,我们才能进行下一步操作,具体实现代码如下:
3.判断蓝牙是否开启
上面已经获取到了BluetoothAdapter,通过
就可以获取蓝牙是否开启,如果没开启,则开启蓝牙
整个判断过程如下:
此处,打开蓝牙提示窗可以使用系统开启蓝牙的Dialog ,或者采用自定义Dialog。
4.蓝牙扫描
完成上面步骤后,就可以开始进行蓝牙的扫描了,通过调用BluetoothAdapter的startLeScan()搜索BLE设备。调用此方法时需要传入BluetoothAdapter.LeScanCallback参数。
因此你需要实现 BluetoothAdapter.LeScanCallback接口,BLE设备的搜索结果将通过这个callback返回。
在这里先判断是否正在扫描,如果在扫描则返回,通过调用
开始进行扫描,扫描结果通过mLeScanCallback接口返回,SCAN_PERIOD为定义的一个扫描时间限制,到达设定时间都就会调用
来停止扫描。
由于搜索需要尽量减少功耗,因此在实际使用时需要注意:
1、当找到对应的设备后,立即停止扫描;
2、不要循环搜索设备,为每次搜索设置适合的时间限制。避免设备不在可用范围的时候持续不停扫描,消耗电量。
如果你只需要搜索指定UUID的外设,你可以调用 startLeScan(UUID[], BluetoothAdapter.LeScanCallback)方法。
其中UUID数组指定你的应用程序所支持的GATT Services的UUID。
注意:搜索时,你只能搜索传统蓝牙设备或者BLE设备,两者完全独立,不可同时被搜索。
5. 获取扫描结果
下面来看一下扫描回调mLeScanCallback的实现:
在onLeScan里面就可以获得到扫描到的结果.
这样,蓝牙的开启和扫描就这样简单的实现了。
整个实现代码如下:
函数返回BluetoothGatt对象,它是GATT profile的封装。通过这个对象,我们就能进行GATT Client端的相关操作
断开连接:
在回调里面有10个方法,用来处理蓝牙的各种状态,我们可以根据实际情况来实现其中部分方法。
蓝牙扫描
蓝牙扫描实现的基本步骤如下:1.添加权限
2.判断设备是否支持BLE
3.判断蓝牙是否开启,如果未开启,则弹出开启窗口
4.开启后,开始进行蓝牙扫描
5.通过BluetoothAdapter.LeScanCallback获取扫描结果
下面具体来实现蓝牙的扫描过程
1.权限的添加
在AndroidManifest.xml文件里面添加:
<uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
除了蓝牙权限外,如果需要BLE feature则还需要声明uses-feature:
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>
required为true时,则应用只能在支持BLE的Android设备上安装运行;required为false时,Android设备均可正常安装运行,需要在代码运行时判断设备是否支持BLE feature
2.判断设备是否支持BLE
因为在Api18(4.3)以下是不支持BLE的,如果系统版本小于4.3,则不会再进行下一步操作,在4.3以上的系统中,则去获取BluetoothAdapter, BluetoothAdapter是从系统服务获取到的,全系统就一个,获取到BluetoothAdapter,我们才能进行下一步操作,具体实现代码如下:
/** * 判断是否支持蓝牙设备 * @return */ public boolean isBluetoothValid(){ if(Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN_MR1 || !mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)){ return false; } BluetoothManager bluetoothManager = (BluetoothManager) mContext.getSystemService(Context.BLUETOOTH_SERVICE); mAdapter = bluetoothManager.getAdapter(); if(mAdapter == null){ return false ; } return true ; }
3.判断蓝牙是否开启
上面已经获取到了BluetoothAdapter,通过
/** * 判断蓝牙是否打开 * @return */ private boolean isBluetoothOpen() { // BluetoothManager bManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); // BluetoothAdapter mAdapter = bManager.getAdapter(); return mAdapter.isEnabled(); }
就可以获取蓝牙是否开启,如果没开启,则开启蓝牙
private void enableBluetooth(){ if(!mAdapter.isEnabled()){ mAdapter.enable(); } }
整个判断过程如下:
if(isBluetoothValid()){ //判断设备是否支持Ble蓝牙 if(isBluetoothOpen()){ //蓝牙已经打开,则开始进行蓝牙搜索 scanDevice(); }else{ //如果蓝牙没有打开,则弹出Dialog窗口提示用户进行打开,此处可以使用系统窗口或者自定义窗口 // showOpenBluetoothDialog(); startActivity(new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)); //打开蓝牙系统提示窗口 } }
此处,打开蓝牙提示窗可以使用系统开启蓝牙的Dialog ,或者采用自定义Dialog。
4.蓝牙扫描
完成上面步骤后,就可以开始进行蓝牙的扫描了,通过调用BluetoothAdapter的startLeScan()搜索BLE设备。调用此方法时需要传入BluetoothAdapter.LeScanCallback参数。
因此你需要实现 BluetoothAdapter.LeScanCallback接口,BLE设备的搜索结果将通过这个callback返回。
/** * 蓝牙扫描 */ public void scanDevice() { if(isScanning){ return; } mHandler.postDelayed(new Runnable() { @Override public void run() { // TODO Auto-generated method stub if(!isScanning){ return; } mAdapter.stopLeScan(mLeScanCallback); isScanning = false; } }, SCAN_PERIOD) ; // mac = ""; mAdapter.startLeScan(mLeScanCallback); isScanning = true; }
在这里先判断是否正在扫描,如果在扫描则返回,通过调用
mAdapter.startLeScan(mLeScanCallback);
开始进行扫描,扫描结果通过mLeScanCallback接口返回,SCAN_PERIOD为定义的一个扫描时间限制,到达设定时间都就会调用
mAdapter.stopLeScan(mLeScanCallback);
来停止扫描。
由于搜索需要尽量减少功耗,因此在实际使用时需要注意:
1、当找到对应的设备后,立即停止扫描;
2、不要循环搜索设备,为每次搜索设置适合的时间限制。避免设备不在可用范围的时候持续不停扫描,消耗电量。
如果你只需要搜索指定UUID的外设,你可以调用 startLeScan(UUID[], BluetoothAdapter.LeScanCallback)方法。
其中UUID数组指定你的应用程序所支持的GATT Services的UUID。
注意:搜索时,你只能搜索传统蓝牙设备或者BLE设备,两者完全独立,不可同时被搜索。
5. 获取扫描结果
下面来看一下扫描回调mLeScanCallback的实现:
BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() { @Override public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) { // TODO Auto-generated method stub String deviceName = device.getName(); Log.d(TAG,"扫描结果:"+deviceName); } };
在onLeScan里面就可以获得到扫描到的结果.
这样,蓝牙的开启和扫描就这样简单的实现了。
整个实现代码如下:
public class BleScanActivity extends AppCompatActivity {
private static final String TAG = "BLEScan";
private static final int SCAN_PERIOD = 8000;
private Context mContext;
private BluetoothAdapter mAdapter;
private boolean isScanning = false;
private Handler mHandler = new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mContext = BleScanActivity.this;
if(isBluetoothValid()){ //判断设备是否支持Ble蓝牙 if(isBluetoothOpen()){ //蓝牙已经打开,则开始进行蓝牙搜索 scanDevice(); }else{ //如果蓝牙没有打开,则弹出Dialog窗口提示用户进行打开,此处可以使用系统窗口或者自定义窗口 // showOpenBluetoothDialog(); startActivity(new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)); //打开蓝牙系统提示窗口 } }
}
/** * 判断是否支持蓝牙设备 * @return */ public boolean isBluetoothValid(){ if(Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN_MR1 || !mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)){ return false; } BluetoothManager bluetoothManager = (BluetoothManager) mContext.getSystemService(Context.BLUETOOTH_SERVICE); mAdapter = bluetoothManager.getAdapter(); if(mAdapter == null){ return false ; } return true ; }
/**
* 打开蓝牙
*/
private void enableBluetooth(){ if(!mAdapter.isEnabled()){ mAdapter.enable(); } }
/** * 判断蓝牙是否打开 * @return */ private boolean isBluetoothOpen() { // BluetoothManager bManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); // BluetoothAdapter mAdapter = bManager.getAdapter(); return mAdapter.isEnabled(); }
/**
* 打开蓝牙提示窗口
*/
private void showOpenBluetoothDialog(){
AlertDialog.Builder builder = new AlertDialog.Builder(BleScanActivity.this);
builder.setTitle("你确定要打开蓝牙?");
builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
enableBluetooth();
}
});
builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
});
builder.show();
}
/** * 蓝牙扫描 */ public void scanDevice() { if(isScanning){ return; } mHandler.postDelayed(new Runnable() { @Override public void run() { // TODO Auto-generated method stub if(!isScanning){ return; } mAdapter.stopLeScan(mLeScanCallback); isScanning = false; } }, SCAN_PERIOD) ; // mac = ""; mAdapter.startLeScan(mLeScanCallback); isScanning = true; }
BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() { @Override public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) { // TODO Auto-generated method stub String deviceName = device.getName(); Log.d(TAG,"扫描结果:"+deviceName); } };
}
蓝牙连接
两个设备通过BLE通信,首先需要建立GATT连接。这里Android设备作为Client端,连接GATT Server。连接GATT Server,需要调用BluetoothDevice的connectGatt()方法。此函数带三个参数:Context、autoConnect(boolean)和BluetoothGattCallback对象。调用示例:mBluetoothGatt = device.connectGatt(this, false, mGattCallback);函数返回BluetoothGatt对象,它是GATT profile的封装。通过这个对象,我们就能进行GATT Client端的相关操作
/** * 蓝牙连接 * @param device */ public void connect(BluetoothDevice device) { if (null == device || !mBluetoothAdapter.isEnabled()) { //设备为空或者蓝牙未开启,返回 return; } Log.d(TAG,"开始连接:"); mBluetoothGatt = device.connectGatt(mContext, false, mGattCallback); }
断开连接:
/** * 断开连接 */ public void disconnect() { if (null == mBluetoothGatt) { return; } mBluetoothGatt.disconnect(); }
在回调里面有10个方法,用来处理蓝牙的各种状态,我们可以根据实际情况来实现其中部分方法。
/** * 连接回调,结果处理 */ private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() { @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {//连接状态改变 Log.d(TAG,"连接状态:"+ newState); /** * 连接状态: * * The profile is in disconnected state *public static final int STATE_DISCONNECTED = 0; * * The profile is in connecting state *public static final int STATE_CONNECTING = 1; * * The profile is in connected state *public static final int STATE_CONNECTED = 2; * * The profile is in disconnecting state *public static final int STATE_DISCONNECTING = 3; * */ if (BluetoothGatt.STATE_CONNECTED == newState){ Log.d(TAG,"连接成功:"); } } @Override public void onServicesDiscovered(BluetoothGatt gatt, int status) {//发现服务,在蓝牙连接的时候会调用 Log.d(TAG,"onServicesDiscovered:"+ status); } @Override public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { } @Override public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {//发送数据时调用 } @Override public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {//descriptor读 } @Override public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {// Characteristic 改变,数据接收会调用 } @Override public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {//descriptor写 } @Override public void onReliableWriteCompleted(BluetoothGatt gatt, int status) { } @Override public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) { //读Rssi } @Override public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) { } };
相关文章推荐
- Android BLE低功耗蓝牙开发极简系列(一)之扫描与连接
- Android安卓蓝牙BLE 扫描连接接收数据 封装好的类
- Android BLE低功耗蓝牙开发
- 关于Android 5.x的低功耗蓝牙BLE开发简介
- 【Android应用开发】Android 蓝牙低功耗 (BLE) ( 第一篇 . 概述 . 蓝牙低功耗文档 翻译)
- Android低功耗蓝牙(BLE)开发的一点感受
- BLE 扫描及连接 android程序开发(一)
- 史上最强Android 的低功耗蓝牙BLE开发实践
- android 蓝牙ble app开发(二) -- 关键概念,连接参数,连接请求
- 基于Android 5.x的低功耗蓝牙BLE开发简介
- android 低功耗BLE蓝牙连接示例代码
- Android开发--蓝牙操作 经典蓝牙 扫描和连接
- 【android 蓝牙开发——BLE(低功耗)蓝牙】
- 使用BleLib的轻松搞定Android低功耗蓝牙Ble 4.0开发详解
- Android 低功耗蓝牙(BLE)开发(3)-- BluetoothDevice详解
- Android-低功耗蓝牙BLE(Bluetooth Low Energy)开发
- Android 低功耗蓝牙(BLE)开发(1)-- 基本概念
- Android低功耗蓝牙(蓝牙4.0)——BLE开发(上)
- 使用BleLib的轻松搞定Android低功耗蓝牙Ble 4.0开发具体解释
- Android 5.x的低功耗蓝牙BLE开发简介