Android Bluetooth Low Energy 基础

Android Bluetooth Low Energy 基础

1、关于Android平台的BLE

蓝牙4.0于2010年发布,相对于上个版本3.0,它的特点是更省电、成本低 延迟低等特点,现在最新的蓝牙协议是2013年底发布的蓝牙4.1,蓝牙4.1在4.0 基础上进行升级,使得可穿戴设备的批量数据传输速度更高。Android是从4.3 才开始提供BLE API,这也就限定了BLE的应用只能运行在Android 4.3及其以上 的系统。在Android平台上的蓝牙4.0主要有两种工作模式:经典蓝牙(classic bluetooth) 、低功耗蓝牙(bluetooth low energy,缩写为BLE)

2、角色与职责

当一个Android设备与一个BLE设备进行交互通信时,主要存在以下两种关系
中心设备与外围设备:中心设备扮演扫描的角色,寻找外围设备的广播消息。Android设备 作为中心设备,与之连接通信的设备作为外围设备。

GATT服务器与GATT客户端:这种关系决定了当连接建立后两个设备如何通信。

注:目前Android系统提供的API使得Android设备只能作为中心设备

3、组成部分

BLE分为三个部分Service、Characteristic、Descriptor,每个部分都拥有不同的 UUID来标识。一个BLE设备可以拥有多个Service,一个Service可以包含多个Characteristic, 一个Characteristic包含一个Value和多个Descriptor,一个Descriptor包含一个Value。 通信数据一般存储在Characteristic内,目前一个Characteristic中存储的数据最大为20 byte。 与Characteristic相关的权限字段主要有READ、WRITE、WRITE_NO_RESPONSE、NOTIFY。 Characteristic具有的权限属性可以有一个或者多个。

4、核心代码


private BluetoothAdapter mBtAdapter = null;
private BluetoothGatt mBtGatt = null;
private int mState = 0;
private Context mContext;
private BluetoothGattCharacteristic mWriteCharacteristic = null;
private BluetoothGattCharacteristic mReadCharacteristric = null;
 
private final String TAG = "BLE_Demo";
 
// 设备连接状态
private final int CONNECTED = 0x01;
private final int DISCONNECTED = 0x02;
private final int CONNECTTING = 0x03;
 
// 读写相关的Service、Characteristic的UUID
public static final UUID TRANSFER_SERVICE_READ = UUID.fromString("34567817-2432-5678-1235-3c1d5ab44e17");
public static final UUID TRANSFER_SERVICE_WRITE = UUID.fromString("34567817-2432-5678-1235-3c1d5ab44e18");
public static final UUID TRANSFER_CHARACTERISTIC_READ = UUID.fromString("23487654-5678-1235-2432-3c1d5ab44e94");
public static final UUID TRANSFER_CHARACTERISTIC_WRITE = UUID.fromString("23487654-5678-1235-2432-3c1d5ab44e93");
 
// BLE设备连接通信过程中回调
private BluetoothGattCallback mBtGattCallback = new BluetoothGattCallback() {
 
    // 连接状态发生改变时的回调
    @Override
    public void onConnectionStateChange(BluetoothGatt gatt, int status,
                int newState) {
 
        if (status == BluetoothGatt.GATT_SUCCESS) {
            mState = CONNECTED;
            Log.d(TAG, "connected OK");
            mBtGatt.discoverServices();
        } else if (newState == BluetoothGatt.GATT_FAILURE) {
            mState = DISCONNECTED;
            Log.d(TAG, "connect failed");
        }
    }
 
    // 远端设备中的服务可用时的回调
    @Override
    public void onServicesDiscovered(BluetoothGatt gatt, int status) {
 
        if (status == BluetoothGatt.GATT_SUCCESS) {
            BluetoothGattService btGattWriteService = mBtGatt
                    .getService(TRANSFER_SERVICE_WRITE);
            BluetoothGattService btGattReadService = mBtGatt
                    .getService(TRANSFER_SERVICE_READ);
            if (btGattWriteService != null) {
                mWriteCharacteristic = btGattWriteService
                        .getCharacteristic(TRANSFER_CHARACTERISTIC_WRITE);
            }
            if (btGattReadService != null) {
                mReadCharacteristric = btGattReadService
                        .getCharacteristic(TRANSFER_CHARACTERISTIC_READ);
                if (mReadCharacteristric != null) {
                    mBtGatt.readCharacteristic(mReadCharacteristric);
                }
            }
        }
    }
 
    // 某Characteristic的状态为可读时的回调
    @Override
    public void onCharacteristicRead(BluetoothGatt gatt,
            BluetoothGattCharacteristic characteristic, int status) {
 
        if (status == BluetoothGatt.GATT_SUCCESS) {
            readCharacterisricValue(characteristic);
 
            // 订阅远端设备的characteristic,
            // 当此characteristic发生改变时当回调mBtGattCallback中的onCharacteristicChanged方法
            mBtGatt.setCharacteristicNotification(mReadCharacteristric,
                    true);
            BluetoothGattDescriptor descriptor = mReadCharacteristric
                    .getDescriptor(UUID
                            .fromString("00002902-0000-1000-8000-00805f9b34fb"));
            if (descriptor != null) {
                byte[] val = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE;
                descriptor.setValue(val);
                mBtGatt.writeDescriptor(descriptor);
            }
        }
    }
 
    // 写入Characteristic成功与否的回调
    @Override
    public void onCharacteristicWrite(BluetoothGatt gatt,
            BluetoothGattCharacteristic characteristic, int status) {
 
        switch (status) {
        case BluetoothGatt.GATT_SUCCESS:
            Log.d(TAG, "write data success");
            break;// 写入成功
        case BluetoothGatt.GATT_FAILURE:
            Log.d(TAG, "write data failed");
            break;// 写入失败
        case BluetoothGatt.GATT_WRITE_NOT_PERMITTED:
            Log.d(TAG, "write not permitted");
            break;// 没有写入的权限
        }
    }
 
    // 订阅了远端设备的Characteristic信息后,
    // 当远端设备的Characteristic信息发生改变后,回调此方法
    @Override
    public void onCharacteristicChanged(BluetoothGatt gatt,
            BluetoothGattCharacteristic characteristic) {
        readCharacterisricValue(characteristic);
    }
 
};
 
/**
 * 读取BluetoothGattCharacteristic中的数据
 * 
 * @param characteristic
 */
private void readCharacterisricValue(
        BluetoothGattCharacteristic characteristic) {
    byte[] data = characteristic.getValue();
    StringBuffer buffer = new StringBuffer("0x");
    int i;
    for (byte b : data) {
        i = b & 0xff;
        buffer.append(Integer.toHexString(i));
    }
    Log.d(TAG, "read data:" + buffer.toString());
}
 
/**
 * 与指定的设备建立连接
 * 
 * @param device
 */
public void connect(BluetoothDevice device) {
 
    mBtGatt = device.connectGatt(mContext, false, mBtGattCallback);
    mState = CONNECTTING;
}
 
/**
 * 初始化
 * 
 * @param context
 * @return 如果初始化成功则返回true
 */
public boolean init(Context context) {
    BluetoothManager btMrg = (BluetoothManager) context
            .getSystemService(Context.BLUETOOTH_SERVICE);
    if (btMrg == null)
        return false;
    mBtAdapter = btMrg.getAdapter();
    if (mBtAdapter == null)
        return false;
    mContext = context;
    return true;
}
 
// BLE设备搜索过程中的回调,在此可以根据外围设备广播的消息来对设备进行过滤
private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {
     
    @Override
    public void onLeScan(final BluetoothDevice device, int rssi,
            byte[] scanRecord) {
         
        ArrayUtils.reverse(scanRecord);// 数组反转
        // 将Byte数组的数据以十六进制表示并拼接成字符串
        StringBuffer str = new StringBuffer();
        int i = 0;
        for (byte b : scanRecord) {
            i = (b & 0xff);
            str.append(Integer.toHexString(i));
        }
        String discoveryServceID = str.toString();
        Log.d(TAG, device.getName() + " scanRecord:\n" + discoveryServceID);
         
        // 查询是否含有指定的Service UUID信息
        if (discoveryServceID.indexOf(TRANSFER_SERVICE_WRITE.toString()
                .replace("-", "")) != -1) {
 
            Log.d(TAG, device.getName() + " has available service UUID");
 
            // 在这是处理匹配的设备……
 
        }
 
    }
 
};
 
/**
 * 开始BLE设备扫描
 */
public void startScan() {
    mBtAdapter.startLeScan(mLeScanCallback);
}
 
/**
 * 停止BLE设备扫描
 */
public void stopScan() {
    mBtAdapter.stopLeScan(mLeScanCallback);
}
 
/**
 * 发送数据
 * 
 * @param data
 *            待发送的数据,最大长度为20
 */
private void sendData(byte[] data) {
 
    if (data != null && data.length > 0 && data.length < 21) {
        if (mWriteCharacteristic.setValue(data)
                && mBtGatt.writeCharacteristic(mWriteCharacteristic)) {
            Log.d(TAG, "send data OK");
        }
    }
}

Android Bluetooth Low Energy 数据的写入与读取 第一天

1 、启动ble设备连接的方法首先要得到一个BluetoothDevice, 这个可以通过,android搜索一配对或者为配对的蓝牙设备获取得到BluetoothDevice的对象,也可以通过搜索ble设备去得到一个BluetoothDevice的对象(下面会仔细说索搜ble设备)需要注意的是,当一个ble设备作为一个蓝牙设备连接到了android 设备上的话,我们通过搜索ble设备的api是搜索不到的。

2、得到一个蓝牙已配对设备

mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
mBluetoothAdapter.startDiscovery();
 
Set<BluetoothDevice> bledevices = mBluetoothAdapter.getBondedDevices();
if (bledevices.size() > 0)
{
    for (BluetoothDevice bluetoothDevice : bledevices)
    {
        if (bluetoothDevice.getAddress().toString()
                .equals(BLUETOOTH_DEVICE_MAC))
        {
            Log.v(TAG, "find with old: " + bluetoothDevice.getAddress());
            bluetoothDevice.connectGatt(getActivity(), false,
                    mGattCallback);
        }
    }
}

3、如何索搜ble设备 :

使用BluetoothAdapter 的 startLeScan 方法, 

startLeScan 的参数是一个回调。

private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback()
{
 
    @Override
    public void onLeScan(final BluetoothDevice device, int rssi,
            byte[] scanRecord)
    {
        Log.v(TAG, "device: " + device);   
    }
};

在这个回调里可以索搜到BLE设备

4、使用索搜到的设备连接:

当我们搜索到设备的时候, 可以使用

device.connectGatt(getActivity(), false, mGattCallback);

进行连接,其中 mGattCallback 也是个回调方法

 private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback()
    {
 
        // 设备发生读操作时的回调
        @Override
        public void onCharacteristicRead(BluetoothGatt gatt,
                BluetoothGattCharacteristic characteristic, int status)
        {
            Log.v(TAG, "onCharacteristicRead: " + characteristic.getUuid());
        }
                  
        // 设备发生写操作是的回调
        @Override
        public void onCharacteristicWrite(BluetoothGatt gatt,
                BluetoothGattCharacteristic characteristic, int status)
        {
            if (BluetoothGatt.GATT_SUCCESS == status)
            {
                Log.v(TAG, "onCharacteristicWrite: " + characteristic.getUuid());
            }
            super.onCharacteristicWrite(gatt, characteristic, status);
        }
 
        // 设备连接状态发生更改时的回调
        // 我们要在这里进行discoverServices()
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status,
                int newState)
        {
            gatt.discoverServices();
            super.onConnectionStateChange(gatt, status, newState);
        }
 
        // 当BLE设备中的服务被找到时,回调如下方法
        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status)
        {
            Log.v(TAG, "onServicesDiscovered: " + gatt.getServices().size());
 
            super.onServicesDiscovered(gatt, status);
        }
 
    };

5、重点:数据的IO
无论数据或是写,都需要

BluetoothGattService mSVC = gatt.getService(UUID
                    .fromString("0000dfb0-0000-1000-8000-00805f9b34fb"));
BluetoothGattCharacteristic mCH = mSVC.getCharacteristic(UUID
                    .fromString("0000dfb1-0000-1000-8000-00805f9b34fb"));

得到一个BluetoothGattCharacteristic , 如上, 我们同过一个指定uuid的方式,在

public
void
onServicesDiscovered() 方法中

得到gatt ,调用gatt的读操作

gatt.readCharacteristic(mCH);

执行这部操作之后, 我们会在 onCharacteristicRead 方法回掉这个 Characteristic 的所带有的value

写操作则是

mCH.setValue(GAME_MODE);
gatt.writeCharacteristic(mCH);

同理,在 onCharacteristicWrite 方法中可以获得操作的提示。

20151120 , 目前我可以读到 

Characteristic 里的数据,结果也正确, 但是无法语言写入是否正确,目前执行了write的操作,系统显示写入正常, 但是看不到相应的变化,

指环的模式并没有变化。ps:我在提供的demo中执行写操作,指环的状态也为改变(之前改过机会,目前不知道情况)

Android Bluetooth Low Energy 数据的写入与读取 第二天

1、使用
writeCharacteristic 读写数据,(顺便说一句,今天反复的调试之后,公司这边的蓝牙设备终于可以切换模式了,不知道为什么之前尝试的总是不行),今天做下总结。

2、由于android ble 的接口都是异步的, 所以我们所调用的方法都要在回掉函数中进行,写一个简单的流程图, 方便理解:(图画的不专业, 凑合看看)

Paste_Image.png

3、写数据的时候将值这样写 ch.setValue(new byte[] { (byte) 0x00, (byte) 0xff });

package youten.redo.ble.readwrite;
 
import java.util.Set;
import java.util.UUID;
 
import youten.redo.ble.util.BleUtil;
import youten.redo.ble.util.BleUuid;
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.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.widget.Button;
import android.widget.Toast;
 
public class DeviceActivity extends Activity implements View.OnClickListener
{
    private static final String TAG = "BLEDevice";
 
    public static final String EXTRA_BLUETOOTH_DEVICE = "BT_DEVICE";
    private BluetoothAdapter mBTAdapter;
    private BluetoothDevice mDevice;
    private BluetoothGatt mConnGatt;
    private int mStatus;
 
    private Button mReadManufacturerNameButton;
    private Button mReadSerialNumberButton;
    private Button mWriteAlertLevelButton;
 
    private final BluetoothGattCallback mGattcallback = new BluetoothGattCallback()
    {
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status,
                int newState)
        {
            if (newState == BluetoothProfile.STATE_CONNECTED)
            {
                mStatus = newState;
                Log.v(TAG, "connected and discoverServices");
                mConnGatt.discoverServices();
            } else if (newState == BluetoothProfile.STATE_DISCONNECTED)
            {
                mStatus = newState;
                runOnUiThread(new Runnable()
                {
                    public void run()
                    {
                        mReadManufacturerNameButton.setEnabled(false);
                        mReadSerialNumberButton.setEnabled(false);
                        mWriteAlertLevelButton.setEnabled(false);
                    };
                });
            }
        };
 
        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status)
        {
            Log.v(TAG, "is have services");
            for (BluetoothGattService service : gatt.getServices())
            {
                if ((service == null) || (service.getUuid() == null))
                {
                    continue;
                }
                if (BleUuid.SERVICE_DEVICE_INFORMATION.equalsIgnoreCase(service
                        .getUuid().toString()))
                {
                    mReadManufacturerNameButton
                            .setTag(service.getCharacteristic(UUID
                                    .fromString(BleUuid.CHAR_MANUFACTURER_NAME_STRING)));
                    mReadSerialNumberButton
                            .setTag(service.getCharacteristic(UUID
                                    .fromString(BleUuid.CHAR_SERIAL_NUMBEAR_STRING)));
                    runOnUiThread(new Runnable()
                    {
                        public void run()
                        {
                            mReadManufacturerNameButton.setEnabled(true);
                            mReadSerialNumberButton.setEnabled(true);
                        };
                    });
                }
                if (BleUuid.SERVICE_IMMEDIATE_ALERT.equalsIgnoreCase(service
                        .getUuid().toString()))
                {
                    runOnUiThread(new Runnable()
                    {
                        public void run()
                        {
                            mWriteAlertLevelButton.setEnabled(true);
                        };
                    });
                    mWriteAlertLevelButton.setTag(service
                            .getCharacteristic(UUID
                                    .fromString(BleUuid.CHAR_ALERT_LEVEL)));
                }
            }
 
            runOnUiThread(new Runnable()
            {
                public void run()
                {
                    setProgressBarIndeterminateVisibility(false);
                };
            });
        };
 
        @Override
        public void onCharacteristicRead(BluetoothGatt gatt,
                BluetoothGattCharacteristic characteristic, int status)
        {
            if (status == BluetoothGatt.GATT_SUCCESS)
            {
 
                byte[] bytes = characteristic.getValue();
                for (byte b : bytes)
                {
                    Log.v("", "------characteristic------" + b);
                }
 
                if (BleUuid.CHAR_MANUFACTURER_NAME_STRING
                        .equalsIgnoreCase(characteristic.getUuid().toString()))
                {
                    final String name = characteristic.getStringValue(0);
 
                    runOnUiThread(new Runnable()
                    {
                        public void run()
                        {
                            mReadManufacturerNameButton.setText(name);
                            setProgressBarIndeterminateVisibility(false);
                        };
                    });
                } else if (BleUuid.CHAR_SERIAL_NUMBEAR_STRING
                        .equalsIgnoreCase(characteristic.getUuid().toString()))
                {
                    final String name = characteristic.getStringValue(0);
 
                    runOnUiThread(new Runnable()
                    {
                        public void run()
                        {
                            mReadSerialNumberButton.setText(name);
                            setProgressBarIndeterminateVisibility(false);
                        };
                    });
                }
 
            }
        }
 
        @Override
        public void onCharacteristicWrite(BluetoothGatt gatt,
                BluetoothGattCharacteristic characteristic, int status)
        {
 
            if (BluetoothGatt.GATT_SUCCESS == status)
            {
                Log.v(TAG,
                        "write - characteristic: " + characteristic.getUuid());
                Log.v(TAG, "write - service "
                        + characteristic.getService().getUuid());
            }
 
            // 再读取一次, 验证一下值是不是对的
            gatt.readCharacteristic(characteristic);
 
            runOnUiThread(new Runnable()
            {
                public void run()
                {
                    setProgressBarIndeterminateVisibility(false);
                };
            });
        };
    };
 
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
        setContentView(R.layout.activity_device);
 
        // state
        mStatus = BluetoothProfile.STATE_DISCONNECTED;
        mReadManufacturerNameButton = (Button) findViewById(R.id.read_manufacturer_name_button);
        mReadManufacturerNameButton.setOnClickListener(this);
        mReadSerialNumberButton = (Button) findViewById(R.id.read_serial_number_button);
        mReadSerialNumberButton.setOnClickListener(this);
        mWriteAlertLevelButton = (Button) findViewById(R.id.write_alert_level_button);
        mWriteAlertLevelButton.setOnClickListener(this);
    }
 
    @Override
    protected void onResume()
    {
        super.onResume();
 
        init();
    }
 
    @Override
    protected void onDestroy()
    {
        super.onDestroy();
        if (mConnGatt != null)
        {
            if ((mStatus != BluetoothProfile.STATE_DISCONNECTING)
                    && (mStatus != BluetoothProfile.STATE_DISCONNECTED))
            {
                mConnGatt.disconnect();
            }
            mConnGatt.close();
            mConnGatt = null;
        }
    }
 
    @Override
    public void onClick(View v)
    {
        if (v.getId() == R.id.read_manufacturer_name_button)
        {
            if ((v.getTag() != null)
                    && (v.getTag() instanceof BluetoothGattCharacteristic))
            {
                BluetoothGattCharacteristic ch = (BluetoothGattCharacteristic) v
                        .getTag();
                if (mConnGatt.readCharacteristic(ch))
                {
                    setProgressBarIndeterminateVisibility(true);
                }
            }
        } else if (v.getId() == R.id.read_serial_number_button)
        {
            if ((v.getTag() != null)
                    && (v.getTag() instanceof BluetoothGattCharacteristic))
            {
                BluetoothGattCharacteristic ch = (BluetoothGattCharacteristic) v
                        .getTag();
                if (mConnGatt.readCharacteristic(ch))
                {
                    setProgressBarIndeterminateVisibility(true);
                }
            }
 
        } else if (v.getId() == R.id.write_alert_level_button)
        {
            if ((v.getTag() != null)
                    && (v.getTag() instanceof BluetoothGattCharacteristic))
            {
                BluetoothGattCharacteristic ch = (BluetoothGattCharacteristic) v
                        .getTag();
                ch.setValue(new byte[] { (byte) 0x00, (byte) 0xff });
                if (mConnGatt.writeCharacteristic(ch))
                {
                    Log.v(TAG, "1st wirte had readly");
                    setProgressBarIndeterminateVisibility(true);
                }
            }
        }
    }
 
    private void init()
    {
        // BLE check
        if (!BleUtil.isBLESupported(this))
        {
            Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT)
                    .show();
            finish();
            return;
        }
 
        // BT check
        BluetoothManager manager = BleUtil.getManager(this);
        if (manager != null)
        {
            mBTAdapter = manager.getAdapter();
        }
        if (mBTAdapter == null)
        {
            Toast.makeText(this, R.string.bt_unavailable, Toast.LENGTH_SHORT)
                    .show();
            finish();
            return;
        }
 
        // check BluetoothDevice
        if (mDevice == null)
        {
            mDevice = getBTDeviceExtra();
            if (mDevice == null)
            {
                finish();
                return;
            }
        }
 
        // button disable
        mReadManufacturerNameButton.setEnabled(false);
        mReadSerialNumberButton.setEnabled(false);
        mWriteAlertLevelButton.setEnabled(false);
 
        // connect to Gatt
        if ((mConnGatt == null)
                && (mStatus == BluetoothProfile.STATE_DISCONNECTED))
        {
            Log.v(TAG, "try to connect with connectGatt");
            // try to connect
            mConnGatt = mDevice.connectGatt(this, false, mGattcallback);
            mStatus = BluetoothProfile.STATE_CONNECTING;
        } else
        {
            if (mConnGatt != null)
            {
                // re-connect and re-discover Services
                Log.v(TAG, "try to connect with connect...");
                mConnGatt.connect();
                mConnGatt.discoverServices();
            } else
            {
                Log.e(TAG, "state error");
                finish();
                return;
            }
        }
        setProgressBarIndeterminateVisibility(true);
    }
 
    private BluetoothAdapter mBluetoothAdapter;
     
    // 读取一个固定的mac 地址, 进行验证
    private static final String BLUETOOTH_DEVICE_MAC = "D0:06:8E:75:56:16";
 
    private BluetoothDevice getBTDeviceExtra()
    {
        BluetoothDevice bleDevice = null;
        Intent intent = getIntent();
        if (intent == null)
        {
            return null;
        }
 
        Bundle extras = intent.getExtras();
        if (extras == null)
        {
            return null;
        }
 
        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        mBluetoothAdapter.startDiscovery();
 
        Set<BluetoothDevice> bledevices = mBluetoothAdapter.getBondedDevices();
        if (bledevices.size() > 0)
        {
            for (BluetoothDevice bluetoothDevice : bledevices)
            {
                Log.v(TAG,
                        "bletoothdevice mac address: "
                                + bluetoothDevice.getAddress());
                if (bluetoothDevice.getAddress().toString()
                        .equals(BLUETOOTH_DEVICE_MAC))
                {
                    bleDevice = bluetoothDevice;
                }
            }
        }
 
        return bleDevice;
    }
 
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,026评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,655评论 1 296
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,726评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,204评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,558评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,731评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,944评论 2 314
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,698评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,438评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,633评论 2 247
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,125评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,444评论 3 255
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,137评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,103评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,888评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,772评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,669评论 2 271

推荐阅读更多精彩内容