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

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

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


private BluetoothAdapter mBluetoothAdapter;
private BluetoothGatt mBluetoothGatt;
private List 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 iteratorServices = mGattServiceList.iterator();
                while(iteratorServices.hasNext()) {
                    BluetoothGattService service = iteratorServices.next();
                    Iterator 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 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 iteratorServices = mGattServiceList.iterator();
                while(iteratorServices.hasNext()) {
                    BluetoothGattService service = iteratorServices.next();
                    Iterator 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));
    }
}

你可能感兴趣的:(应用,蓝牙,蓝牙,蓝牙Ble,蓝牙血糖仪,蓝牙发指令)