您的位置:首页 > 其它

有关蓝牙Ble连接的一些开发探讨

2016-12-28 14:33 274 查看
最近在做手机连接蓝牙血压计、血氧仪和血糖仪的开发,一般这样在设备端是不做任何操作的,只需在手机客户端发送指令达到数据传输。

一、蓝牙的连接

1.首先得判断手机是否支持蓝牙或者打开蓝牙吧,代码如下:

private BluetoothAdapter mBluetoothAdapter;
private BluetoothGatt mBluetoothGatt;
private List<BluetoothGattService> mGattServiceList;
……………………

BluetoothManager manager = (BluetoothManager) getSystemService("bluetooth");
mBluetoothAdapter = manager.getAdapter();

//判断蓝牙是否可用与是否打开了蓝牙
if(mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
tv_status.setText("please open your bluetooth first");
showOpenBtDialog(); //选择打开蓝牙对话框
}


2.打开系统蓝牙设置

/**
* 打开蓝牙对话框
*/
private void showOpenBtDialog() {

new AlertDialog.Builder(this)
.setMessage("please open your bluetooth")
.setPositiveButton("Yes", newDialogInterface.OnClickListener() {

@Override
public void onClick(DialogInterface dialog, int arg1) {
// TODO Auto-generated method stub
dialog.cancel();
Intent intent = new Inteny(Settings.ACTION_BLUETOOTH_SETTINGS);
startActivity(intent);
}

}).show();
}


3.开启蓝牙后,启动扫描

/**
* 开始扫描
*/
private void startScan() {
if(!isScanning && !ifSucc && mBluetoothAdapter != null) {
tv_status.setText("Scanning...");
mBluetoothAdapter.startLeScan(mLeScanCallback);
isScanning = true;
}
}

/**
* 结束扫描
*/
private void stopScan() {
if(mBluetoothAdapter != null) {
mBluetoothAdapter.stopLeScan(mLeScanCallback);
isScanning = false;
}
}

/**
* 扫描设备回调
*/
private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {

@Override
public void onLeScan(final BluetoothDevice device, int paramAnonymousInt, byte[] paramAnonymousArrayOfByte) {
// TODO Auto-generated method stub
runOnUiThread(new Runnable() {

@Override
public void run() {
// TODO Auto-generated method stub
Log.i("wsjInfo", "device name= " + device.getName());
if(device.getName() != null && device.getName().equals("MEDXING-BGM")) { //我这里的设备名称是这个
stopScan(); //找到设备停止扫描
mBluetoothGatt = device.connectGatt(BloodSugarActivity.this, false, mBluetoothGattCallback);
tv_status.setText("Connecting...");
}
}
});
}
};


4.蓝牙连接成功后,回调这个最重要了。

/**
* 蓝牙中央回调
*/
private BluetoothGattCallback mBluetoothGattCallback = new BluetoothGattCallback() {

@Override //接发数据
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
//          Log.e("onCharacteristicChanged", "onDataChanged");

//获取到蓝牙设备发送的字节数组数据过来
byte[] res = characteristic.getValue();
for(int i=0; i < res.length; i++) {
Log.e("wsjInfo", "byte[" + i + "]=" + res[i]);
}

//具体的处理就看设备通讯协议
Message msg = mHandler.obtainMessage();
msg.what = WHAT_DATACHANGED;
msg.obj = res;
mHandler.sendMessage(msg);
}

@Override //连接状态改变
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
//          Log.e("onConnectionStateChange", "status=" + status + ",newState=" + newState);

if(newState == BluetoothGatt.STATE_CONNECTED) { //已建立连接
do {
ifSucc = mBluetoothGatt.discoverServices(); //discoverServices为异步操作,回调方法为onServicesDiscovered

try {
Thread.sleep(CONN_AGAIN);
} catch (InterruptedException e) {
e.printStackTrace();
Log.e("Thread.sleep", "Thread");
}
} while(!ifSucc); //没连接成功循环连接

} else if(newState == BluetoothGatt.STATE_DISCONNECTED) { //已断开
mHandler.sendEmptyMessage(WHAT_DISCONNECTED);
}
}

@Override //发现周边服务
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
//          Log.e("onServicesDiscovered", "status=" + status);
if(status == 0) {

mHandler.sendEmptyMessage(WHAT_CONNECTED);

mGattServiceList = gatt.getServices();
Iterator<BluetoothGattService> iteratorServices = mGattServiceList.iterator();
while(iteratorServices.hasNext()) {
BluetoothGattService service = iteratorServices.next();
Iterator<BluetoothGattCharacteristic> itChars = service.getCharacteristics().iterator();

while(itChars.hasNext()) {
BluetoothGattCharacteristic characteristic = itChars.next();
String uuid = characteristic.getUuid().toString();
//这里很重要,要找到对应的该设备UUID,然后发指令
if(uuid.equals(UUID5)) {
Log.e("wsjInfo", "uuid=" + uuid);

characteristic.setValue("C2H"); //可以发字符串指令,可以发byte[]指令,要看每个设备协议
gatt.writeCharacteristic(characteristic);
gatt.setCharacteristicNotification(characteristic, true);
}
}
}
}
}
};


二、加权限

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

<!-- 蓝牙低功耗设备 -->
<uses-feature android:name="android.hardware.bluetooth_le" />


三、附完整代码(我这里做的是美的蓝牙血糖仪的连接)

package com.chainway.nursestation.bluetooth;

import java.util.Iterator;
import java.util.List;

import com.chainway.nursestation.R;

import android.app.Activity;
import android.app.AlertDialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.provider.Settings;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

public class BloodSugarActivity extends Activity implements OnClickListener {

private static final long CONN_AGAIN = 3000L; // 重连(3s)

/**
* 因为开发文档和协议有些没有,UUID是我一个一个Log打印出来尝试
* 发现那个设备后,可以获取它的所有UUID,每个试着匹配发指令
*/
//  private static final String UUID1 = "00002a00-0000-1000-8000-00805f9b34fb";
//  private static final String UUID2 = "00002a01-0000-1000-8000-00805f9b34fb";
//  private static final String UUID3 = "00002a05-0000-1000-8000-00805f9b34fb";
//  private static final String UUID4 = "0000ffb1-0000-1000-8000-00805f9b34fb";
private static final String UUID5 = "0000ffb2-0000-1000-8000-00805f9b34fb"; //
//  private static final String UUID6 = "00002a24-0000-1000-8000-00805f9b34fb";
//  private static final String UUID7 = "00002a25-0000-1000-8000-00805f9b34fb";
//  private static final String UUID8 = "00002a27-0000-1000-8000-00805f9b34fb";
//  private static final String UUID9 = "00002a28-0000-1000-8000-00805f9b34fb";
//  private static final String UUID10 = "00002a29-0000-1000-8000-00805f9b34fb";

private BluetoothAdapter mBluetoothAdapter;
private BluetoothGatt mBluetoothGatt;
private List<BluetoothGattService> mGattServiceList;
private boolean ifSucc; //是否连接成功
private boolean isScanning; //正在扫描

private TextView tv_status, tv_tips, tv_result;
private TextView tv_back, tv_reconnect, tv_upload;

private static final int WHAT_DISCONNECTED = 0; //连接断开
private static final int WHAT_CONNECTED = 1; //已连接
private static final int WHAT_DATACHANGED = 2; //数据获取

private Handler mHandler = new Handler() {
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case WHAT_CONNECTED: //已连接
tv_status.setText("Connected(MEDXING-BGM)");
break;
case WHAT_DISCONNECTED: //连接断开
tv_status.setText("Disconnected");
tv_tips.setText(R.string.text_disconn);
tv_result.setText("--");
ifSucc = false;
break;
case WHAT_DATACHANGED: //获取数据

byte[] res = (byte[]) msg.obj;

if(res.length == 6 && res[3] == -102 && res[5] == 113) { //还没插入测试纸
tv_tips.setText(R.string.text_tips1);
tv_result.setText("--");
} else if(res.length == 6 && res[3] == -99 && res[5] == 116) { //测试纸有误
tv_tips.setText(R.string.text_tips2);
tv_result.setText("--");
} else if(res.length == 12) { //已插入测试纸
tv_tips.setText(R.string.text_tips3);
tv_result.setText("--");
} else if(res.length == 7) { //测量中,倒计时5,4,3,2,1
tv_tips.setText(R.string.text_tips4);
tv_result.setText(String.valueOf(res[6]));
} else if(res.length == 9) { //测量结果
if(res[6] == 0 && res[7] == 0) {
tv_tips.setText(R.string.text_tips5);
tv_result.setText("--");
} else {
tv_tips.setText(R.string.text_tips6);
tv_result.setText((res[6] * 256.0 + res[7] / 10.0) + " mmol/L");
}
}
break;

default:
break;
}
}
};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_blood_sugar);

init(); //初始化
}

private void init() {
tv_status = (TextView) findViewById(R.id.tv_status);
tv_tips = (TextView) findViewById(R.id.tv_tips);
tv_result = (TextView) findViewById(R.id.tv_result);
tv_back = (TextView) findViewById(R.id.tv_back);
tv_back.setOnClickListener(this);

tv_reconnect = (TextView) findViewById(R.id.tv_reconnect);
tv_reconnect.setOnClickListener(this);
tv_upload = (TextView) findViewById(R.id.tv_upload);
tv_upload.setOnClickListener(this);

BluetoothManager manager = (BluetoothManager) getSystemService("bluetooth");
mBluetoothAdapter = manager.getAdapter();
}

@Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
if(mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
tv_status.setText("please open your bluetooth first");
showOpenBtDialog();
} else {
startScan(); //开始扫描
}
}

@Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
stopScan();
}

/**
* 打开蓝牙对话框
*/
private void showOpenBtDialog() {

new AlertDialog.Builder(this)
.setMessage("please open your bluetooth")
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {

@Override
public void onClick(DialogInterface dialog,
int arg1) {
// TODO Auto-generated method stub
dialog.cancel();
Intent intent = new Intent(Settings.ACTION_BLUETOOTH_SETTINGS);
startActivity(intent);
}

}).show();
}

/**
* 开始扫描
*/
private void startScan() {
if(!isScanning && !ifSucc && mBluetoothAdapter != null) {
tv_status.setText("Scanning...");
mBluetoothAdapter.startLeScan(mLeScanCallback);
isScanning = true;
}
}

/**
* 结束扫描
*/
private void stopScan() {
if(mBluetoothAdapter != null) {
mBluetoothAdapter.stopLeScan(mLeScanCallback);
isScanning = false;
}
}

private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {

@Override
public void onLeScan(final BluetoothDevice device, int paramAnonymousInt, byte[] paramAnonymousArrayOfByte) {
// TODO Auto-generated method stub
runOnUiThread(new Runnable() {

@Override
public void run() {
// TODO Auto-generated method stub
Log.e("wsjInfo", "device name= " + device.getName());
if(device.getName() != null && device.getName().equals("MEDXING-BGM")) {
stopScan(); //找到设备停止扫描
mBluetoothGatt = device.connectGatt(BloodSugarActivity.this, false, mBluetoothGattCallback);
tv_status.setText("Connecting...");
}
}
});
}
};

/**
* 蓝牙中央回调
*/
private BluetoothGattCallback mBluetoothGattCallback = new BluetoothGattCallback() {

@Override //接发数据
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
//          Log.e("onCharacteristicChanged", "onDataChanged");
byte[] res = characteristic.getValue();
for(int i=0; i < res.length; i++) {
Log.e("wsjInfo", "byte[" + i + "]=" + res[i]);
}

Message msg = mHandler.obtainMessage();
msg.what = WHAT_DATACHANGED;
msg.obj = res;
mHandler.sendMessage(msg);
}

@Override //连接状态改变
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
//          Log.e("onConnectionStateChange", "status=" + status + ",newState=" + newState);

if(newState == BluetoothGatt.STATE_CONNECTED) { //已建立连接
do {
ifSucc = mBluetoothGatt.discoverServices(); //discoverServices为异步操作,回调方法为onServicesDiscovered

try {
Thread.sleep(CONN_AGAIN);
} catch (InterruptedException e) {
e.printStackTrace();
Log.e("Thread.sleep", "Thread");
}
} while(!ifSucc); //没连接成功循环连接

} else if(newState == BluetoothGatt.STATE_DISCONNECTED) { //已断开
mHandler.sendEmptyMessage(WHAT_DISCONNECTED);
}
}

@Override //发现周边服务
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
//          Log.e("onServicesDiscovered", "status=" + status);
if(status == 0) {

mHandler.sendEmptyMessage(WHAT_CONNECTED);

mGattServiceList = gatt.getServices();
Iterator<BluetoothGattService> iteratorServices = mGattServiceList.iterator();
while(iteratorServices.hasNext()) {
BluetoothGattService service = iteratorServices.next();
Iterator<BluetoothGattCharacteristic> itChars = service.getCharacteristics().iterator();

while(itChars.hasNext()) {
BluetoothGattCharacteristic characteristic = itChars.next();
String uuid = characteristic.getUuid().toString();
if(uuid.equals(UUID5)) {
Log.e("wsjInfo", "uuid=" + uuid);

characteristic.setValue("C2H");
gatt.writeCharacteristic(characteristic);
gatt.setCharacteristicNotification(characteristic, true);
}
}
}
}
}
};

@Override
public void onClick(View v) {
// TODO Auto-generated method stub
switch (v.getId()) {
case R.id.tv_back: //返回
finish();
break;
case R.id.tv_reconnect: //重新连接
if(!isScanning && !ifSucc) {
startScan();
} else {
toastMsg(R.string.msg_conned);
}
break;
case R.id.tv_upload: //上传
if(tv_result.getText().toString().contains("mmol/L")) {
toastMsg(R.string.msg_upload_succ);
} else {
toastMsg(R.string.msg_noresult);
}
break;

default:
break;
}
}

@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
stopScan();
ifSucc = true;
if(mBluetoothGatt != null) {
mBluetoothGatt.disconnect();
mBluetoothGatt.close();
}
}

private Toast toast;
private void toastMsg(String msg) {
if(toast != null) {
toast.cancel();
}

toast = Toast.makeText(this, msg, Toast.LENGTH_SHORT);
toast.show();
}

private void toastMsg(int resId) {
toastMsg(getString(resId));
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: