Android编程之低功耗蓝牙的那点事
安安 2017-11-16 来源 :网络 阅读 595 评论 0

摘要:本篇Android编程教程将为大家讲解Android编程的知识点,看完这篇文章会让你对Android编程的知识点有更加清晰的理解和运用。

本篇Android编程教程将为大家讲解Android编程的知识点,看完这篇文章会让你对Android编程的知识点有更加清晰的理解和运用。

 

近期项目使用到了蓝牙技术,菜鸟一枚,网上各种找资料,发现不是不全就是过时,要么就是抄袭转载,真实醉了,现在将这一块的东西整理出来,供大家参考。

基本概念

Android中的蓝牙分两种:经典蓝牙、低功耗蓝牙。

1. 二者本质上没有太多区别,可以理解为后者是前者的升级优化版本。对于API上的实现区别还是很大的。

2. 工作流程:发现设备->配对/绑定设备->建立连接->数据通信。
至于底层如何工作,本人不了解,也不是本文关注的重点。

3. 官方文档:https://developer.android.com/guide/topics/connectivity/bluetooth.html?hl=zh-cn

重要实例

1. 经典蓝牙聊天实例:https://github.com/googlesamples/android-BluetoothChat

2. 低功耗蓝牙:https://github.com/googlesamples/android-BluetoothLeGatt

3. 作为外设(API>=21):https://github.com/googlesamples/android-BluetoothAdvertisements

4. 基础概念讲解://blog.csdn.net/qinxiandiqi/article/details/40741269

5. 深入理论://www.race604.com/android-ble-in-action/

注意事项

1. 低功耗蓝牙(BLE)Android 4.3(API 18)以上才支持

2. 使用蓝牙需要权限

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

3. 

4. Android 5.0(API 21) 扫描蓝牙需要定位权限,否则扫描不到设备,实际使用时候发现 5.0不需要也可以扫描,Android 6.0(API 23)以上必须(不知道什么原因,测试机器:MI 2,知道原因的可告知)

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

5. 

官方文档:https://developer.android.com/guide/topics/connectivity/bluetooth-le.html?hl=zh-cn

6. 

7. 低功耗蓝牙要声明特征,或者代码判断

// 如果为true表示只能在支持低功耗蓝牙的设备上使用,如果不支持的设备也可以使用,采用代码判断

<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>// 代码判断if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {

    Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show();

    finish();

}

8. 

9. 经典蓝牙连接成功后获取一个socket连接得到输入输出流进行通信,低功耗通过特征(具体实现不知道是什么)

10. Android 5.0(API 21)之前不能当成外设(蓝牙耳机、音响等)来使用,只能作为中心即主机

低功耗蓝牙

现在蓝牙开发基本上都是低功耗蓝牙,比如心率设备、耳机设备、手环,所以我们先从重要的开始,讲讲低功耗蓝牙的使用,后面在完善经典蓝牙。

声明权限

创建项目在AndroidManifest.xml中声明权限:

<manifest xmlns:android="//schemas.android.com/apk/res/android"

          package="com.lowett.android">

  // 定位权限第二个包含第一个,所以这里就声明了一个,两个都声明也可以

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

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

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

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

  // 是否必须支持低功耗蓝牙,此处不必须

   <uses-feature

      android:name="android.hardware.bluetooth_le"

      android:required="false"/>

   // 是有gps硬件,这个现在的智能手机没有不支持的吧

  <uses-feature android:name="android.hardware.location.gps"/>

 

  </manifest>

如果manifest中声明的蓝牙特性为false,那么在代码中监测是否支持BLE特性,

// 使用此检查确定BLE是否支持在设备上,然后你可以有选择性禁用BLE相关的功能if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {

    Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show();

    finish();

}

BluetoothAdapter

获取BluetoothManager得到蓝牙适配器BluetoothAdapter,注意这两个类都是系统级别,只有一个,代表了你手机上的蓝牙模块

final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);BluetoothAdapter bluetoothAdapter = bluetoothManager.getAdapter();

如果获取到的Adapter为空说明不支持蓝牙,或者没有蓝牙模块

开启蓝牙

前面获取到了BluetoothAdapter,可以通过调用isEnabled()函数去检测是否开启了蓝牙,false表示没有开启,如果没有开启需要去启用,

Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);

activity.startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);

代码执行完后,会有弹框提示用户是否启用,我们需要在onActivityResult()中判断返回

@Overridepublic void onActivityResult(int requestCode, int resultCode, Intent data) {

    super.onActivityResult(requestCode, resultCode, data);

    if (requestCode == BluetoothLeManager.REQUEST_ENABLE_BT) {

        if (resultCode == Activity.RESULT_OK) {

           // something, 去扫描设备

            startScan();

        } else {

            new AlertDialog.Builder(this)

                    .setMessage("请开启蓝牙,连接设备")

                    .setPositiveButton(R.string.confirm, new DialogInterface.OnClickListener() {

                        @Override

                        public void onClick(DialogInterface dialog, int which) {

                            dialog.dismiss();

                           // something

                        }

                    })

                    .create()

                    .show();

        }

    }

}

扫描设备

低功耗蓝牙和经典蓝牙的扫描方式不同,如果熟悉经典蓝牙,那就要可能掉进坑了起不来了,哈哈。蓝牙扫描耗电比较严重,所以此处一定要记得在合适的实际停止扫描,比如定时停止、扫描到目标设备就停止(奇怪的是API为何不提供扫描时长的接口呢?)扫描时调用Adapter的startLeScan()方法,然而这个被标记为过时,API>=21被另一个取代。然后通过回掉得到扫描结果(经典蓝牙是广播)

public void startScan() {

    // 初始化一个handler

        initHandler();

        if (!mScanning) {

            if (scanRunnable == null) {

                scanRunnable = new Runnable() {

                    @Override

                    public void run() {

                        stopScan();

                    }

                };

            }

 

          // SCAN_PERIOD = 3 * 10 * 1000, 30s后停止扫面

            mHandler.postDelayed(scanRunnable, SCAN_PERIOD);// 新API//            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {//                mBluetoothAdapter.getBluetoothLeScanner().startScan(this);//            }else {

          // this 实现了BluetoothAdapter.LeScanCallback,即扫描结果回掉

                mBluetoothAdapter.startLeScan(this);//            }

            mScanning = true;

            Log.i(TAG, "开始扫描,蓝牙设备");

        }

    }

回调函数

@Overridepublic void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {

 // 得到扫描结果

    Log.i(TAG, "扫描到的设备, name=" + device.getName() + ",address=" + device.toString());

}

注意:device:代表外设即目标设备 rssi:设一个强度值,但是时负值,利用这个值通过公式可以算出离你的距离

scanRecord:广播数据,附加的数据,没用到

停止扫描

扫描完成务必停止,因为扫描不仅耗电,还影响连接速度,所以当要连接的时候,先停止扫描时必须的

public void stopScan() {

    initHandler();

    Log.i(TAG, "停止扫描,蓝牙设备");

    if (mScanning) {

        mScanning = false;

        // 开始扫描的接口,要一样的不然停止不了

        mBluetoothAdapter.stopLeScan(this);

    }

 

    if (scanRunnable != null) {

        mHandler.removeCallbacks(scanRunnable);

        scanRunnable = null;

    }

}

连接设备

通常连接设备速度还是很快的,连接理论上来说也是无状态的,所以也需要一个定式任务来,保证超时停止。

public boolean connect(Context context, String address) {

    if (mConnectionState == STATE_CONNECTED) {

        return false;

    }

    if (mBluetoothAdapter == null || TextUtils.isEmpty(address)) {

        return false;

    }

    initHandler();

    if (connectRunnable == null) {

        connectRunnable = new Runnable() {

            @Override

            public void run() {

                mConnectionState = STATE_DISCONNECTING;

                disconnect();

            }

        };

    }

  // 30s没反应停止连接

    mHandler.postDelayed(connectRunnable, 30 * 1000);

    stopScan();// 获取到远程设备,

    final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);

    if (device == null) {

        return false;

    }

    // 开始连接,第二个参数表示是否需要自动连接,true设备靠近自动连接,第三个表示连接回调

    mBluetoothGatt = device.connectGatt(context, false, mGattCallback);

    mBluetoothDeviceAddress = address;

    mConnectionState = STATE_CONNECTING;

    return true;

}

监听连接回调

private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {// 连接状态变化

    @Override

    public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {

        if (newState == BluetoothProfile.STATE_CONNECTED) { // 连接上

            mConnectionState = STATE_CONNECTED;

            boolean success = mBluetoothGatt.discoverServices(); // 去发现服务

            Log.i(TAG, "Attempting to start service discovery:" +

                    success);

        } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { // 连接断开

            mConnectionState = STATE_DISCONNECTED;       

        }

    }

// 发现服务

    @Override

    public void onServicesDiscovered(BluetoothGatt gatt, int status) {

        if (status == BluetoothGatt.GATT_SUCCESS) {

            Log.i(TAG,"发现服务");

            // 解析服务

            discoverService();

        }

    }

// 特征读取变化

    @Override

    public void onCharacteristicRead(BluetoothGatt gatt,

                                     BluetoothGattCharacteristic characteristic,

                                     int status) {

        if (status == BluetoothGatt.GATT_SUCCESS) {

 

        }

    }

// 收到数据

    @Override

    public void onCharacteristicChanged(BluetoothGatt gatt,

                                        BluetoothGattCharacteristic characteristic) {

        mConnectionState = STATE_CONNECTED;

 

    }

};

断开连接

public void disconnect() {

    if (mBluetoothAdapter == null || mBluetoothGatt == null) {

        mConnectionState = STATE_DISCONNECTED;

        return;

    }

    // 连接成功的GATT

    mBluetoothGatt.disconnect();

    mBluetoothGatt.close();

}

多设备连接

蓝牙适配器没有听过连接多个设备的接口,需要我们自己实现,即获取到目标设备的address后调用连接方法,自己维护多个BluetoothGatt即可(代码稍后放出)。

完整代码示例

正在做心率相关的蓝牙设备,此处代码发出来。

代码还在完善中,仅供参考,稳定代码将会发在Github中

package com.lowett.android.ble;

import android.app.Activity;import android.bluetooth.BluetoothAdapter;import android.bluetooth.BluetoothDevice;import android.bluetooth.BluetoothGatt;import android.bluetooth.BluetoothGattCallback;import android.bluetooth.BluetoothGattCharacteristic;import android.bluetooth.BluetoothGattDescriptor;import android.bluetooth.BluetoothGattService;import android.bluetooth.BluetoothManager;import android.bluetooth.BluetoothProfile;import android.content.Context;import android.content.Intent;import android.content.pm.PackageManager;import android.os.Handler;import android.os.Looper;import android.support.annotation.IntDef;import android.text.TextUtils;

import com.fit.android.utils.Logger;

import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.util.List;import java.util.Locale;import java.util.UUID;

/**

 * Email: fvaryu@qq.com

 */public class BluetoothLeManager implements BluetoothAdapter.LeScanCallback {

    public static final int REQUEST_ENABLE_BT = 1;

    private static final int SCAN_PERIOD = 3 * 10 * 1000;

 

    static final int STATE_DISCONNECTED = 1;

    public static final int STATE_CONNECTING = 2;

    public static final int STATE_DISCONNECTING = 3;

    public static final int STATE_CONNECTED = 4;

    public static final int STATE_DISCOVER_SERVICES = 5;

 

    @IntDef(value = {STATE_DISCONNECTED, STATE_CONNECTING, STATE_CONNECTED, STATE_DISCONNECTING, STATE_DISCOVER_SERVICES})

    @Retention(RetentionPolicy.SOURCE)

    public @interface State {

    }

 

    public final static UUID UUID_HEART_RATE_MEASUREMENT =

            UUID.fromString(SampleGattAttributes.HEART_RATE_MEASUREMENT);

 

    private static BluetoothLeManager ourInstance = new BluetoothLeManager();

 

    //    private Context mContext;

    private boolean is_inited = false;

 

    private android.bluetooth.BluetoothManager mBluetoothManager;

    private BluetoothAdapter mBluetoothAdapter;

    private String mBluetoothDeviceAddress;

    private int mConnectionState;

    private BluetoothGatt mBluetoothGatt;

 

    private boolean mScanning;

    private Runnable scanRunnable;

    private Handler mHandler;

 

    private Runnable connectRunnable;

 

    private OnDataReceivedListener mOnDataReceivedListener;

    // 记得清掉监听 泄漏

    private OnLeScanListener mOnLeScanListener;

    private OnConnectionStateChangeListener mOnConnectionStateChangeListener;

 

    private int retryCount;

 

    public static BluetoothLeManager getInstance() {

        return ourInstance;

    }

 

    private BluetoothLeManager() {

    }

 

    public void setOnDataReceivedListener(OnDataReceivedListener onDataReceivedListener) {

        mOnDataReceivedListener = onDataReceivedListener;

    }

 

    public interface OnConnectionStateChangeListener {

        void onConnectionStateChange(BluetoothGatt gatt, int status, int newState);

 

        void onConnectTimeout();

    }

 

    public void setOnConnectionStateChangeListener(OnConnectionStateChangeListener onConnectionStateChangeListener) {

        mOnConnectionStateChangeListener = onConnectionStateChangeListener;

    }

 

    public interface OnLeScanListener {

        void onLeScan(BluetoothDevice device);

    }

 

    public interface OnDataReceivedListener {

        void onDataReceived(int heart);

    }

 

    private void init() {

        if (!is_inited) {

            is_inited = true;

        }

    }

 

    private boolean initialize(Context context) {

        init();

        if (!is_inited) {

            throw new RuntimeException("请先调用init");

        }

 

        if (mBluetoothAdapter != null) {

            return true;

        }

        // For API level 18 and above, get a reference to BluetoothAdapter through

        // BluetoothLeManager.

        if (mBluetoothManager == null) {

            mBluetoothManager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);

            if (mBluetoothManager == null) {

                return false;

            }

        }

 

        mBluetoothAdapter = mBluetoothManager.getAdapter();

        return mBluetoothAdapter != null;

    }

 

    public boolean isSupportBluetoothLe(Activity activity) {

        return activity.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE);

    }

 

    public boolean isSupportBluetooth(Context context) {

        return initialize(context);

    }

 

    public void enableBluetooth(Activity activity) {

        if (!initialize(activity)) {

            return;

        }

        if (!mBluetoothAdapter.isEnabled()) {

            Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);

            activity.startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);

        }

    }

 

    public boolean isEnabled(Context context) {

        return initialize(context) && mBluetoothAdapter.isEnabled();

    }

 

    private void initHandler() {

        if (mHandler == null) {

            mHandler = new Handler(Looper.getMainLooper());

        }

    }

 

    public void startScan(OnLeScanListener onLeScanListener) {

        initHandler();

        if (!mScanning) {

            if (scanRunnable == null) {

                scanRunnable = new Runnable() {

                    @Override

                    public void run() {

                        stopScan();

                    }

                };

            }

 

            mHandler.postDelayed(scanRunnable, SCAN_PERIOD);

//            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {//                mBluetoothAdapter.getBluetoothLeScanner().startScan(this);//            }else {

            mBluetoothAdapter.startLeScan(this);//            }

 

            mScanning = true;

 

            this.mOnLeScanListener = onLeScanListener;

 

            Logger.i("开始扫描,蓝牙设备");

        }

    }

 

    @Override

    public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {

        final BluetoothDevice tmp = device;

        Logger.i("扫描到的设备, name=" + device.getName() + ",address=" + device.toString());

        if (mOnLeScanListener != null) {

            mHandler.post(new Runnable() {

                @Override

                public void run() {

                    mOnLeScanListener.onLeScan(tmp);

                }

            });

        }

    }

 

    public void stopScan() {

        initHandler();

        mOnLeScanListener = null;

        Logger.i("停止扫描,蓝牙设备");

        if (mScanning) {

            mScanning = false;

            mBluetoothAdapter.stopLeScan(this);

        }

 

        if (scanRunnable != null) {

            mHandler.removeCallbacks(scanRunnable);

            scanRunnable = null;

        }

    }

 

    private void removeConnectRunnable() {

        if (connectRunnable != null) {

            mHandler.removeCallbacks(connectRunnable);

            connectRunnable = null;

        }

    }

 

    private void retry() {

        if (TextUtils.isEmpty(mBluetoothDeviceAddress)) {

            return;

        }

        mHandler.postDelayed(new Runnable() {

            @Override

            public void run() {

                if (++retryCount < 11 && mConnectionState < STATE_CONNECTED) {

                    reconnect(retryCount);

                    mHandler.postDelayed(this, retryCount * 5 * 1000);

                    Logger.i("蓝牙重试次数=" + retryCount);

                }

 

            }

        }, 2000);

    }

 

    private void reconnect(int count) {

        if ((mConnectionState >= STATE_CONNECTING)) {

            return;

        }

 

        if (connectRunnable == null) {

            connectRunnable = new Runnable() {

                @Override

                public void run() {

                    mConnectionState = STATE_DISCONNECTING;

                    disconnect();

                }

            };

        }

        mHandler.postDelayed(connectRunnable, count * 3 * 1000);

 

        if (mBluetoothDeviceAddress != null

                && mBluetoothGatt != null) {

            mBluetoothGatt.connect();

            mConnectionState = STATE_CONNECTING;

        }

    }

 

    public boolean connect(Context context, String address) {

        if (mConnectionState == STATE_CONNECTED) {

            return false;

        }

        if (mBluetoothAdapter == null || TextUtils.isEmpty(address)) {

            return false;

        }

        initHandler();

        if (connectRunnable == null) {

            connectRunnable = new Runnable() {

                @Override

                public void run() {

                    mConnectionState = STATE_DISCONNECTING;

                    disconnect();

 

                    if (mOnConnectionStateChangeListener != null) {

                        mOnConnectionStateChangeListener.onConnectTimeout();

                    }

                }

            };

        }

        mHandler.postDelayed(connectRunnable, 30 * 1000);

 

        stopScan();

 

        // Previously connected device.  Try to reconnect.

        if (mBluetoothDeviceAddress != null && address.equals(mBluetoothDeviceAddress)

                && mBluetoothGatt != null) {

            if (mBluetoothGatt.connect()) {

                mConnectionState = STATE_CONNECTING;

                return true;

            } else {

                return false;

            }

        }

 

        final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);

        if (device == null) {

            return false;

        }

        // We want to directly connect to the device, so we are setting the autoConnect

        // parameter to false.

        mBluetoothGatt = device.connectGatt(context, false, mGattCallback);

        mBluetoothDeviceAddress = address;

        mConnectionState = STATE_CONNECTING;

        return true;

    }

 

    public void disconnect() {

        if (mBluetoothAdapter == null || mBluetoothGatt == null) {

            Logger.i("BluetoothAdapter not initialized");

            mConnectionState = STATE_DISCONNECTED;

            return;

        }

 

        mBluetoothGatt.disconnect();

 

    }

 

    public void close() {

        disconnect();

        if (mBluetoothGatt == null) {

            return;

        }

        mBluetoothGatt.close();

        mBluetoothGatt = null;

    }

 

    public void disconnectNoRetry() {

        mBluetoothDeviceAddress = null;

        close();

    }

 

    private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {

 

        @Override

        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {

            if (newState == BluetoothProfile.STATE_CONNECTED) {

                mConnectionState = STATE_CONNECTED;

                boolean success = mBluetoothGatt.discoverServices();

                Logger.i("Attempting to start service discovery:" +

                        success);

                removeConnectRunnable();

 

                Logger.i("链接上");

            } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {

                mConnectionState = STATE_DISCONNECTED;

                Logger.i("断开链接");

 

                retry();

            }

 

            if (mOnConnectionStateChangeListener != null) {

                mOnConnectionStateChangeListener.onConnectionStateChange(gatt, status, newState);

            }

        }

 

        @Override

        public void onServicesDiscovered(BluetoothGatt gatt, int status) {

            if (status == BluetoothGatt.GATT_SUCCESS) {

                Logger.i("发现服务");

                discoverService();

            }

 

        }

 

        @Override

        public void onCharacteristicRead(BluetoothGatt gatt,

                                         BluetoothGattCharacteristic characteristic,

                                         int status) {

            if (status == BluetoothGatt.GATT_SUCCESS) {

                broadcastUpdate(characteristic);

            }

        }

 

        @Override

        public void onCharacteristicChanged(BluetoothGatt gatt,

                                            BluetoothGattCharacteristic characteristic) {

            mConnectionState = STATE_CONNECTED;

            broadcastUpdate(characteristic);

        }

    };

 

    /**

     * Retrieves a list of supported GATT services on the connected device. This should be

     * invoked only after {@code BluetoothGatt#discoverServices()} completes successfully.

     *

     * @return A {@code List} of supported services.

     */

    private List<BluetoothGattService> getSupportedGattServices() {

        if (mBluetoothGatt == null) return null;

        return mBluetoothGatt.getServices();

    }

 

    private void discoverService() {

        if (mConnectionState == STATE_DISCOVER_SERVICES) {

            return;

        }

        mConnectionState = STATE_DISCOVER_SERVICES;

        List<BluetoothGattService> list = getSupportedGattServices();

        /**

         *  BluetoothGattService = 00001800-0000-1000-8000-00805f9b34fb

         BluetoothGattCharacteristic = 00002a00-0000-1000-8000-00805f9b34fb

         BluetoothGattCharacteristic = 00002a01-0000-1000-8000-00805f9b34fb

         BluetoothGattCharacteristic = 00002a04-0000-1000-8000-00805f9b34fb

 

         BluetoothGattService = 00001801-0000-1000-8000-00805f9b34fb

         BluetoothGattCharacteristic = 00002a05-0000-1000-8000-00805f9b34fb

 

         心跳服务

         BluetoothGattService = 0000180d-0000-1000-8000-00805f9b34fb

         心跳特征

         BluetoothGattCharacteristic = 00002a37-0000-1000-8000-00805f9b34fb

         BluetoothGattCharacteristic = 00002a38-0000-1000-8000-00805f9b34fb

 

         BluetoothGattService = 0000180f-0000-1000-8000-00805f9b34fb

         BluetoothGattCharacteristic = 00002a19-0000-1000-8000-00805f9b34fb

 

         // 设备名字

         BluetoothGattService = 0000180a-0000-1000-8000-00805f9b34fb

         BluetoothGattCharacteristic = 00002a28-0000-1000-8000-00805f9b34fb

         */

        for (BluetoothGattService s : list) {

            if (!SampleGattAttributes.HEART_RATE_SERVICES.equals(s.getUuid().toString())) {

                continue;

            }

            final List<BluetoothGattCharacteristic> l = s.getCharacteristics();

            for (final BluetoothGattCharacteristic bc : l) {

                if (!SampleGattAttributes.HEART_RATE_MEASUREMENT.equals(bc.getUuid().toString())) {

                    continue;

                }

                Logger.i("连接蓝牙 服务成功");

                setCharacteristicNotification(bc, true);

                return;

            }

        }

    }

 

    private void broadcastUpdate(final BluetoothGattCharacteristic characteristic) {

 

        // This is special handling for the Heart Rate Measurement profile.  Data parsing is

        // carried out as per profile specifications:

        // //developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.heart_rate_measurement.xml

        if (UUID_HEART_RATE_MEASUREMENT.equals(characteristic.getUuid())) {

            int flag = characteristic.getProperties();

            int format = -1;

            if ((flag & 0x01) != 0) {

                format = BluetoothGattCharacteristic.FORMAT_UINT16;

            } else {

                format = BluetoothGattCharacteristic.FORMAT_UINT8;

            }

            int heartRate = characteristic.getIntValue(format, 1);

            Logger.i(String.format(Locale.getDefault(), "Received heart rate: %d", heartRate));

            if (mOnDataReceivedListener != null) {

                mOnDataReceivedListener.onDataReceived(heartRate);

            }

        }//        else {

        // For all other profiles, writes the data formatted in HEX.//            final byte[] data = characteristic.getValue();//            if (data != null && data.length > 0) {//                final StringBuilder stringBuilder = new StringBuilder(data.length);//                for (byte byteChar : data)//                    stringBuilder.append(String.format("%02X ", byteChar));//                intent.putExtra(EXTRA_DATA, new String(data) + "\n" + stringBuilder.toString());//            }//        }

        /**

         * 2、

         *///        sendBroadcast(intent);

    }

 

    public boolean isConnected() {

        return mConnectionState == STATE_CONNECTED;

    }

 

    public String getConnectedAddress() {

        if (!isConnected()) {

            return null;

        }

        return mBluetoothDeviceAddress;

    }

 

    public void readCharacteristic(BluetoothGattCharacteristic characteristic) {

        if (mBluetoothAdapter == null || mBluetoothGatt == null) {

            Logger.i("BluetoothAdapter not initialized");

            return;

        }

        mBluetoothGatt.readCharacteristic(characteristic);

 

    }

 

    private void setCharacteristicNotification(BluetoothGattCharacteristic characteristic,

                                               boolean enabled) {

        if (mBluetoothAdapter == null || mBluetoothGatt == null) {

            Logger.i("BluetoothAdapter not initialized");

            return;

        }

        mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);

 

        // This is specific to Heart Rate Measurement.

        if (UUID_HEART_RATE_MEASUREMENT.equals(characteristic.getUuid())) {

            BluetoothGattDescriptor descriptor = characteristic.getDescriptor(

                    UUID.fromString(SampleGattAttributes.CLIENT_CHARACTERISTIC_CONFIG));

            descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);

            mBluetoothGatt.writeDescriptor(descriptor);

        }

    }

 

    public void clear() {

        mOnLeScanListener = null;

        mOnConnectionStateChangeListener = null;

    }

 

    public void release() {//        connectRunnable = null;//        mHandler = null;//         ourInstance = null;

    }

}

总结

项目还在进行中,遇到的问题将会持续抛出,完善此文档。

 

希望这篇文章可以帮助到你。总之,同学们,你想要的职坐标Android频道都能找到!

本文由 @安安 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程