您的位置:首页 > 移动开发 > Android开发

Android 低功耗蓝牙(BLE)开发(4)-- 蓝牙扫描和连接

2017-01-13 22:35 741 查看
在了解了API里面的常用类和方法后,现在来看蓝牙打开和扫描的实现

蓝牙扫描

蓝牙扫描实现的基本步骤如下:

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