Android Bluetooth Low Energy 基礎(chǔ)

Android Bluetooth Low Energy 基礎(chǔ)

1谣辞、關(guān)于Android平臺(tái)的BLE

藍(lán)牙4.0于2010年發(fā)布虱颗,相對(duì)于上個(gè)版本3.0赋访,它的特點(diǎn)是更省電逝淹、成本低 延遲低等特點(diǎn)律罢,現(xiàn)在最新的藍(lán)牙協(xié)議是2013年底發(fā)布的藍(lán)牙4.1膀值,藍(lán)牙4.1在4.0 基礎(chǔ)上進(jìn)行升級(jí),使得可穿戴設(shè)備的批量數(shù)據(jù)傳輸速度更高误辑。Android是從4.3 才開始提供BLE API,這也就限定了BLE的應(yīng)用只能運(yùn)行在Android 4.3及其以上 的系統(tǒng)沧踏。在Android平臺(tái)上的藍(lán)牙4.0主要有兩種工作模式:經(jīng)典藍(lán)牙(classic bluetooth) 、低功耗藍(lán)牙(bluetooth low energy,縮寫為BLE)

2巾钉、角色與職責(zé)

當(dāng)一個(gè)Android設(shè)備與一個(gè)BLE設(shè)備進(jìn)行交互通信時(shí)翘狱,主要存在以下兩種關(guān)系
中心設(shè)備與外圍設(shè)備:中心設(shè)備扮演掃描的角色,尋找外圍設(shè)備的廣播消息砰苍。Android設(shè)備 作為中心設(shè)備潦匈,與之連接通信的設(shè)備作為外圍設(shè)備。

GATT服務(wù)器與GATT客戶端:這種關(guān)系決定了當(dāng)連接建立后兩個(gè)設(shè)備如何通信赚导。

注:目前Android系統(tǒng)提供的API使得Android設(shè)備只能作為中心設(shè)備

3茬缩、組成部分

BLE分為三個(gè)部分Service、Characteristic吼旧、Descriptor凰锡,每個(gè)部分都擁有不同的 UUID來標(biāo)識(shí)。一個(gè)BLE設(shè)備可以擁有多個(gè)Service,一個(gè)Service可以包含多個(gè)Characteristic掂为, 一個(gè)Characteristic包含一個(gè)Value和多個(gè)Descriptor裕膀,一個(gè)Descriptor包含一個(gè)Value。 通信數(shù)據(jù)一般存儲(chǔ)在Characteristic內(nèi)勇哗,目前一個(gè)Characteristic中存儲(chǔ)的數(shù)據(jù)最大為20 byte昼扛。 與Characteristic相關(guān)的權(quán)限字段主要有READ、WRITE智绸、WRITE_NO_RESPONSE野揪、NOTIFY。 Characteristic具有的權(quán)限屬性可以有一個(gè)或者多個(gè)瞧栗。

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";
 
// 設(shè)備連接狀態(tài)
private final int CONNECTED = 0x01;
private final int DISCONNECTED = 0x02;
private final int CONNECTTING = 0x03;
 
// 讀寫相關(guān)的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設(shè)備連接通信過程中回調(diào)
private BluetoothGattCallback mBtGattCallback = new BluetoothGattCallback() {
 
    // 連接狀態(tài)發(fā)生改變時(shí)的回調(diào)
    @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");
        }
    }
 
    // 遠(yuǎn)端設(shè)備中的服務(wù)可用時(shí)的回調(diào)
    @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的狀態(tài)為可讀時(shí)的回調(diào)
    @Override
    public void onCharacteristicRead(BluetoothGatt gatt,
            BluetoothGattCharacteristic characteristic, int status) {
 
        if (status == BluetoothGatt.GATT_SUCCESS) {
            readCharacterisricValue(characteristic);
 
            // 訂閱遠(yuǎn)端設(shè)備的characteristic迹恐,
            // 當(dāng)此characteristic發(fā)生改變時(shí)當(dāng)回調(diào)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成功與否的回調(diào)
    @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;// 沒有寫入的權(quán)限
        }
    }
 
    // 訂閱了遠(yuǎn)端設(shè)備的Characteristic信息后挣惰,
    // 當(dāng)遠(yuǎn)端設(shè)備的Characteristic信息發(fā)生改變后,回調(diào)此方法
    @Override
    public void onCharacteristicChanged(BluetoothGatt gatt,
            BluetoothGattCharacteristic characteristic) {
        readCharacterisricValue(characteristic);
    }
 
};
 
/**
 * 讀取BluetoothGattCharacteristic中的數(shù)據(jù)
 * 
 * @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());
}
 
/**
 * 與指定的設(shè)備建立連接
 * 
 * @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設(shè)備搜索過程中的回調(diào),在此可以根據(jù)外圍設(shè)備廣播的消息來對(duì)設(shè)備進(jìn)行過濾
private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {
     
    @Override
    public void onLeScan(final BluetoothDevice device, int rssi,
            byte[] scanRecord) {
         
        ArrayUtils.reverse(scanRecord);// 數(shù)組反轉(zhuǎn)
        // 將Byte數(shù)組的數(shù)據(jù)以十六進(jìn)制表示并拼接成字符串
        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");
 
            // 在這是處理匹配的設(shè)備……
 
        }
 
    }
 
};
 
/**
 * 開始BLE設(shè)備掃描
 */
public void startScan() {
    mBtAdapter.startLeScan(mLeScanCallback);
}
 
/**
 * 停止BLE設(shè)備掃描
 */
public void stopScan() {
    mBtAdapter.stopLeScan(mLeScanCallback);
}
 
/**
 * 發(fā)送數(shù)據(jù)
 * 
 * @param data
 *            待發(fā)送的數(shù)據(jù),最大長(zhǎng)度為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 數(shù)據(jù)的寫入與讀取 第一天

1 殴边、啟動(dòng)ble設(shè)備連接的方法首先要得到一個(gè)BluetoothDevice憎茂, 這個(gè)可以通過,android搜索一配對(duì)或者為配對(duì)的藍(lán)牙設(shè)備獲取得到BluetoothDevice的對(duì)象锤岸,也可以通過搜索ble設(shè)備去得到一個(gè)BluetoothDevice的對(duì)象(下面會(huì)仔細(xì)說索搜ble設(shè)備)需要注意的是竖幔,當(dāng)一個(gè)ble設(shè)備作為一個(gè)藍(lán)牙設(shè)備連接到了android 設(shè)備上的話,我們通過搜索ble設(shè)備的api是搜索不到的是偷。

2拳氢、得到一個(gè)藍(lán)牙已配對(duì)設(shè)備

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設(shè)備 :

使用BluetoothAdapter 的 startLeScan 方法蛋铆, 

startLeScan 的參數(shù)是一個(gè)回調(diào)馋评。

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

在這個(gè)回調(diào)里可以索搜到BLE設(shè)備

4、使用索搜到的設(shè)備連接:

當(dāng)我們搜索到設(shè)備的時(shí)候刺啦, 可以使用

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

進(jìn)行連接留特,其中 mGattCallback 也是個(gè)回調(diào)方法

 private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback()
    {
 
        // 設(shè)備發(fā)生讀操作時(shí)的回調(diào)
        @Override
        public void onCharacteristicRead(BluetoothGatt gatt,
                BluetoothGattCharacteristic characteristic, int status)
        {
            Log.v(TAG, "onCharacteristicRead: " + characteristic.getUuid());
        }
                  
        // 設(shè)備發(fā)生寫操作是的回調(diào)
        @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);
        }
 
        // 設(shè)備連接狀態(tài)發(fā)生更改時(shí)的回調(diào)
        // 我們要在這里進(jìn)行discoverServices()
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status,
                int newState)
        {
            gatt.discoverServices();
            super.onConnectionStateChange(gatt, status, newState);
        }
 
        // 當(dāng)BLE設(shè)備中的服務(wù)被找到時(shí),回調(diào)如下方法
        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status)
        {
            Log.v(TAG, "onServicesDiscovered: " + gatt.getServices().size());
 
            super.onServicesDiscovered(gatt, status);
        }
 
    };

5玛瘸、重點(diǎn):數(shù)據(jù)的IO
無論數(shù)據(jù)或是寫蜕青,都需要

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

得到一個(gè)BluetoothGattCharacteristic , 如上捧韵, 我們同過一個(gè)指定uuid的方式市咆,在

public
void
onServicesDiscovered() 方法中

得到gatt ,調(diào)用gatt的讀操作

gatt.readCharacteristic(mCH);

執(zhí)行這部操作之后再来, 我們會(huì)在 onCharacteristicRead 方法回掉這個(gè) Characteristic 的所帶有的value

寫操作則是

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

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

20151120 芒篷, 目前我可以讀到 

Characteristic 里的數(shù)據(jù)搜变,結(jié)果也正確, 但是無法語言寫入是否正確针炉,目前執(zhí)行了write的操作挠他,系統(tǒng)顯示寫入正常, 但是看不到相應(yīng)的變化篡帕,

指環(huán)的模式并沒有變化殖侵。ps:我在提供的demo中執(zhí)行寫操作,指環(huán)的狀態(tài)也為改變(之前改過機(jī)會(huì)镰烧,目前不知道情況)

Android Bluetooth Low Energy 數(shù)據(jù)的寫入與讀取 第二天

1拢军、使用
writeCharacteristic 讀寫數(shù)據(jù),(順便說一句怔鳖,今天反復(fù)的調(diào)試之后茉唉,公司這邊的藍(lán)牙設(shè)備終于可以切換模式了,不知道為什么之前嘗試的總是不行)结执,今天做下總結(jié)度陆。

2、由于android ble 的接口都是異步的献幔, 所以我們所調(diào)用的方法都要在回掉函數(shù)中進(jìn)行懂傀,寫一個(gè)簡(jiǎn)單的流程圖, 方便理解:(圖畫的不專業(yè)蜡感, 湊合看看)

Paste_Image.png

3蹬蚁、寫數(shù)據(jù)的時(shí)候?qū)⒅颠@樣寫 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());
            }
 
            // 再讀取一次, 驗(yàn)證一下值是不是對(duì)的
            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;
     
    // 讀取一個(gè)固定的mac 地址铸敏, 進(jìn)行驗(yàn)證
    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;
    }
 
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末缚忧,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子杈笔,更是在濱河造成了極大的恐慌闪水,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,183評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蒙具,死亡現(xiàn)場(chǎng)離奇詭異球榆,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)禁筏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門持钉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人篱昔,你說我怎么就攤上這事每强∈继冢” “怎么了?”我有些...
    開封第一講書人閱讀 168,766評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵空执,是天一觀的道長(zhǎng)浪箭。 經(jīng)常有香客問我,道長(zhǎng)辨绊,這世上最難降的妖魔是什么奶栖? 我笑而不...
    開封第一講書人閱讀 59,854評(píng)論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮门坷,結(jié)果婚禮上宣鄙,老公的妹妹穿的比我還像新娘。我一直安慰自己默蚌,他們只是感情好冻晤,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,871評(píng)論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著敏簿,像睡著了一般明也。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上惯裕,一...
    開封第一講書人閱讀 52,457評(píng)論 1 311
  • 那天温数,我揣著相機(jī)與錄音,去河邊找鬼蜻势。 笑死撑刺,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的握玛。 我是一名探鬼主播够傍,決...
    沈念sama閱讀 40,999評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼挠铲!你這毒婦竟也來了冕屯?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,914評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤拂苹,失蹤者是張志新(化名)和其女友劉穎安聘,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體瓢棒,經(jīng)...
    沈念sama閱讀 46,465評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡浴韭,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,543評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了脯宿。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片念颈。...
    茶點(diǎn)故事閱讀 40,675評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖连霉,靈堂內(nèi)的尸體忽然破棺而出榴芳,到底是詐尸還是另有隱情嗡靡,我是刑警寧澤,帶...
    沈念sama閱讀 36,354評(píng)論 5 351
  • 正文 年R本政府宣布翠语,位于F島的核電站叽躯,受9級(jí)特大地震影響财边,放射性物質(zhì)發(fā)生泄漏肌括。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,029評(píng)論 3 335
  • 文/蒙蒙 一酣难、第九天 我趴在偏房一處隱蔽的房頂上張望谍夭。 院中可真熱鬧,春花似錦憨募、人聲如沸紧索。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽珠漂。三九已至,卻和暖如春尾膊,著一層夾襖步出監(jiān)牢的瞬間媳危,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評(píng)論 1 274
  • 我被黑心中介騙來泰國打工冈敛, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留待笑,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,091評(píng)論 3 378
  • 正文 我出身青樓抓谴,卻偏偏與公主長(zhǎng)得像暮蹂,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子癌压,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,685評(píng)論 2 360

推薦閱讀更多精彩內(nèi)容