国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

藍(lán)牙Ble4.0通訊的步驟及實(shí)現(xiàn)

2019-11-06 09:41:05
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

在一家偏硬件的一家公司從事穿戴式設(shè)備的開(kāi)發(fā),通過(guò)近幾個(gè)月學(xué)習(xí)與研究對(duì)于藍(lán)牙4.0的通訊還有有點(diǎn)自己的見(jiàn)解,有不足的地方大家可以一起討論,互相學(xué)習(xí),廢話不多說(shuō),那么如何進(jìn)行藍(lán)牙4.0的通訊與數(shù)據(jù)傳輸呢?本demo比較簡(jiǎn)單,大家應(yīng)該都可以很好理解與學(xué)習(xí)的!

有基本的幾個(gè)步驟,下面是一些代碼段,希望對(duì)大家有所幫助吧。

添加藍(lán)牙權(quán)限,

<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="true"/>
判斷手機(jī)手機(jī)是否支持藍(lán)牙ble
// 檢查當(dāng)前手機(jī)是否支持ble 藍(lán)牙,如果不支持退出程序if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {    Toast.makeText(this, "設(shè)備不支持BLE 藍(lán)牙", Toast.LENGTH_SHORT).show();    finish();}
//獲得藍(lán)牙適配器對(duì)象
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
對(duì)于藍(lán)牙的搜索過(guò)程采用廣播:
/** 因?yàn)樗{(lán)牙在搜索到設(shè)備和搜索完畢都是通過(guò)廣播發(fā)送的,這里我們需要注冊(cè)廣播接收器 */IntentFilter intentFilter = new IntentFilter(        BluetoothDevice.ACTION_FOUND);registerReceiver(receiver, intentFilter);intentFilter = new IntentFilter(        BluetoothAdapter.ACTION_DISCOVERY_FINISHED);registerReceiver(receiver, intentFilter);//注冊(cè)藍(lán)牙信號(hào)強(qiáng)度intentFilter = new IntentFilter(BluetoothDevice.ACTION_ACL_CONNECTED);registerReceiver(receiver, intentFilter);
廣播的注冊(cè):
 //注冊(cè)廣播    PRivate final BroadcastReceiver receiver = new BroadcastReceiver() {        @Override        public void onReceive(Context arg0, Intent intent) {            String action = intent.getAction();            // 判斷這個(gè)廣播是否是藍(lán)牙搜索到設(shè)備的廣播            if (action.equals(BluetoothDevice.ACTION_FOUND)) {                // 獲取到傳遞過(guò)來(lái)的設(shè)備信息                BluetoothDevice device = intent                        .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);                if (device.getBondState() != BluetoothDevice.BOND_BONDED) {                    //信號(hào)強(qiáng)度                    short rssi = intent.getExtras().getShort(                            BluetoothDevice.EXTRA_RSSI);                    String s = String.valueOf(rssi);                    mDeviceList.add(device.getName()  + "/n"                            + device.getAddress() + "/n" + "信號(hào)強(qiáng)度:" + s +"dbm");                    arrayAdapter.notifyDataSetChanged();                }                // 判斷是否為搜索完畢的廣播            } else if (action                    .equals(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)) {                /***///             setTitle("連接藍(lán)牙設(shè)備");                bt_search.setText("搜索完畢");            }        }    };
項(xiàng)目創(chuàng)建時(shí)需要打開(kāi)藍(lán)牙,詳細(xì)代碼片段
// 為了確保設(shè)備上藍(lán)牙能使用, 如果當(dāng)前藍(lán)牙設(shè)備沒(méi)啟用,彈出對(duì)話框向用戶要求授予權(quán)限來(lái)啟用if (!mBluetoothAdapter.isEnabled()) {    Intent enabletIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);    startActivityForResult(enabletIntent, REQUEST_CODE);}
@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {    super.onActivityResult(requestCode, resultCode, data);    if (requestCode == REQUEST_CODE && resultCode == Activity.RESULT_CANCELED) {        finish();        return;    }}
基本工作有了這些后,我們建立一個(gè)listview來(lái)顯示搜索到的藍(lán)牙設(shè)備,
//適配器 + Listview顯示arrayAdapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,mDeviceList);listView.setAdapter(arrayAdapter);
2.如何進(jìn)行掃描呢?這里采用的是按鈕觸發(fā):
bt_search.setText("正在搜索藍(lán)牙設(shè)備...");if(mBluetoothAdapter.isDiscovering()){    mBluetoothAdapter.cancelDiscovery();}mBluetoothAdapter.startDiscovery();其實(shí)這個(gè)時(shí)候點(diǎn)擊按鈕,并沒(méi)有任何顯示,因?yàn)槲覀兊糜靡粋€(gè)集合加載搜索到的設(shè)備,前面采用MVC的模式進(jìn)行適配,將搜索到的設(shè)備加載到鏈表里面
//數(shù)據(jù)源存放藍(lán)牙設(shè)備----------------獲取已綁定的設(shè)備,將其存放于set集合Set<BluetoothDevice> devices = mBluetoothAdapter.getBondedDevices();if(devices.size() > 0){    for (BluetoothDevice device:devices) {        mDeviceList.add(device.getName()  + "/n"                + device.getAddress());    }}
將搜索到的設(shè)備顯示到listview上后對(duì)其item項(xiàng)進(jìn)行進(jìn)一步的連接,并進(jìn)行通信、
因?yàn)橐B接設(shè)備的地址,這里進(jìn)行字符串的截取
        String s = mDeviceList.get(position);        String a[] = s.split("/n");        String name = a[0];        String address = a[1];        Log.i(TAG, "address =" + address);        if (mBluetoothAdapter == null || address == null) {            Log.w(TAG, "藍(lán)牙適配器為空或者地址為空.");            return;        }        //根據(jù)地址取得設(shè)備        device = mBluetoothAdapter.getRemoteDevice(address);        //獲取鏈接 這個(gè)時(shí)候需要實(shí)現(xiàn)BluetoothGattCallback        bluetoothGatt = device.connectGatt(this, false, bluetoothGattCallback);接下來(lái)執(zhí)行回調(diào)方法,回調(diào)方法主要有
onConnectionStateChange, // 返回鏈接狀態(tài)
onServicesDiscovered,   //發(fā)現(xiàn)服務(wù)時(shí)調(diào)用此方法
onCharacteristicRead      //字段讀
onCharacteristicWrite   //字段寫(xiě)
onCharacteristicChanged   //藍(lán)牙通信內(nèi)容寫(xiě)入寫(xiě)出時(shí)調(diào)用此方法
onDescriptorRead       // 字段讀
onDescriptorWrite    //字段寫(xiě)
 //回調(diào)方法    private BluetoothGattCallback bluetoothGattCallback = new BluetoothGattCallback() {        // 返回鏈接狀態(tài)        @Override        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {            super.onConnectionStateChange(gatt, status, newState);            Log.i(TAG,"onConnectionStateChange");            if (newState == BluetoothProfile.STATE_CONNECTED) {                //連接成功  因?yàn)槭钱惒秸{(diào)用的 所以刷新UI的操作要放在主線程中,當(dāng)然也可以使用hanlder  Eventbus等 隨便                runOnUiThread(new Runnable() {                    @Override                    public void run() {                        link = 1;                        tv_address.setText("連接成功" + device.getAddress());                    }                });                //發(fā)現(xiàn)服務(wù),連接成功                gatt.discoverServices();            } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {                //斷開(kāi)連接                link = 2;                runOnUiThread(new Runnable() {                    @Override                    public void run() {                        tv_address.setText("連接斷開(kāi)");                    }                });            }        }        @Override        public void onServicesDiscovered(BluetoothGatt gatt, int status) {            super.onServicesDiscovered(gatt, status);            Log.i(TAG,"onServicesDiscovered");            if (status == BluetoothGatt.GATT_SUCCESS) {                bluetoothGattServiceList = bluetoothGatt.getServices();                for (int i = 0; i < bluetoothGattServiceList.size(); i++) {                    BluetoothGattService bluetoothGattService = bluetoothGattServiceList                            .get(i);                    if (bluetoothGattService.getUuid().equals(BleConstants.TEMP_SERVICE_UUID)) {                        BleConstants.type = 1;                        break;                    } else if (bluetoothGattService.getUuid().equals(BleConstants.TEMP_SERVICE_UUID_G)) {                        BleConstants.type = 0;                        break;                    }                }                //-------------------------                for (int i = 0; i < bluetoothGattServiceList.size(); i++) {                    BluetoothGattService bluetoothGattService = bluetoothGattServiceList                            .get(i);                    Log.i(TAG,"Service UUID-" + i + ":" + bluetoothGattService.getUuid());                    List<BluetoothGattCharacteristic> bluetoothGattCharacteristicList = bluetoothGattService                            .getCharacteristics();                    for (int j = 0; j < bluetoothGattCharacteristicList.size(); j++) {                        BluetoothGattCharacteristic bluetoothGattCharacteristic = bluetoothGattCharacteristicList                                .get(j);                        Log.i(TAG,"Characteristic UUID-" + i + "-" + j + ":"                                + bluetoothGattCharacteristic.getUuid());                        if (bluetoothGattCharacteristic.getUuid().equals(BleConstants.TEMP_CHAR_UUID)) {                            Log.i(TAG, "TEMP_CHAR_UUID");                         } else if (bluetoothGattCharacteristic.getUuid().equals(BleConstants.TEMP_BATTERY_CHAR_UUID)) {                            Log.i(TAG, "BATTERY_CHAR_UUID" + bluetoothGattCharacteristic.getUuid().toString());                        } else if (bluetoothGattCharacteristic.getUuid()                                .equals(BleConstants.TEMP_UART_WRITE_CHAR_UUID)) {                        } else if (bluetoothGattCharacteristic.getUuid()                                .equals(BleConstants.TEMP_UART_READ_CHAR_UUID)) {                        }                    }                }                read();                Log.i(TAG, "BluetoothGatt.GATT_SUCCESS");            }        }        @Override        public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {            super.onCharacteristicRead(gatt, characteristic, status);            Log.i(TAG,"onCharacteristicRead");        }        /**         * write成功(發(fā)送值成功) 寫(xiě)入Characteristic成功與否的回調(diào) 可以根據(jù)         * characteristic.getValue()來(lái)判斷是哪個(gè)值發(fā)送成功了,比如 連接上設(shè)備之后你有一大串命令需要下發(fā),你調(diào)用多次寫(xiě)命令,         * 這樣你需要判斷是不是所有命令都成功了,因?yàn)閍ndroid不太穩(wěn)定,有必要來(lái)check命令是否成功,否則你會(huì)發(fā)現(xiàn)你明明調(diào)用         * 寫(xiě)命令,但是設(shè)備那邊不響應(yīng)         */        @Override        public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {            super.onCharacteristicWrite(gatt, characteristic, status);            Log.i(TAG,"onCharacteristicWrite");        }        @Override        public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {            super.onCharacteristicChanged(gatt, characteristic);            Log.i(TAG,"onCharacteristicChanged");            byte[] read_data = characteristic.getValue();            String as = byteToHexString(read_data);            Log.i(TAG, "as = " + as);              float abcd = 0;               if(read_data[1] == 0x01){                //溫度                       abcd = (float) ((read_data[2]) * 256 + (0x000000FF & read_data[3])) / 10;            }                      string1 = String.valueOf(abcd);            Log.i(TAG, "string1 =" + string1);        }        @Override        public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {            super.onDescriptorRead(gatt, descriptor, status);            Log.i(TAG,"onDescriptorRead");        }        @Override        public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {            super.onDescriptorWrite(gatt, descriptor, status);            Log.i(TAG,"onDescriptorWrite");        }    };
read()方法如下:
public void read() {    if (BleConstants.type == 1) {        BluetoothGattService bluetoothGattServic = bluetoothGatt                .getService(BleConstants.TEMP_UART_SERVICE_UUID);        BluetoothGattCharacteristic bluetoothGattCharacteristic = bluetoothGattServic                .getCharacteristic(BleConstants.TEMP_UART_READ_CHAR_UUID);        for (int k = 0; k < bluetoothGattCharacteristic.getDescriptors().size(); k++) {            BluetoothGattDescriptor descriptor = bluetoothGattCharacteristic                    .getDescriptors().get(k);            descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);            bluetoothGatt.writeDescriptor(descriptor);        }        //發(fā)送通知        bluetoothGatt.setCharacteristicNotification(                bluetoothGattCharacteristic, true);    } else if (BleConstants.type == 0) {        BluetoothGattService bluetoothGattServic = bluetoothGatt                .getService(BleConstants.TEMP_SERVICE_UUID_G);        BluetoothGattCharacteristic bluetoothGattCharacteristic = bluetoothGattServic                .getCharacteristic(BleConstants.TEMP_READ_CHAR_UUID_G);        for (int k = 0; k < bluetoothGattCharacteristic.getDescriptors().size(); k++) {            BluetoothGattDescriptor descriptor = bluetoothGattCharacteristic.getDescriptors().get(k);            //ENABLE_NOTIFICATION_VALUE            descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);            bluetoothGatt.writeDescriptor(descriptor);        }        bluetoothGatt.setCharacteristicNotification(                bluetoothGattCharacteristic, true);    }}
進(jìn)制轉(zhuǎn)換的方法:
    public String byteToHexString(byte[] bArray) {        StringBuffer sb = new StringBuffer(bArray.length);        Log.i(TAG, "bArray.length = " + bArray.length);    //長(zhǎng)度為5        String sTemp;        for (int i = 0; i < bArray.length; i++) {            Log.i(TAG, "bArray = " + bArray[i]);    // 5, 1, 0, -2, -6            //將整數(shù)變?yōu)樽址?/em>            // 0xff是十六進(jìn)制FF的表示方法,因?yàn)橐粋€(gè)十六進(jìn)制數(shù)字轉(zhuǎn)換成二進(jìn)制是四位,即F=1111,            // 所以0xff占用一個(gè)字節(jié) 。也就是說(shuō)是1B,1KB是1024B。            //另外你表達(dá)不太清楚,如果你問(wèn)FF KB是多少,十六進(jìn)制FF=15*16+15*1=255,即255KB            sTemp = Integer.toHexString(0xFF & bArray[i]);//            Log.i(TAG, "sTemp" + sTemp);            //Log: sTemp 5, sTemp 1, sTemp 0, sTemp fc, sTemp f8     ---as: 05 01 00F6 F2            if (sTemp.length() < 2)                sb.append(0);            sb.append(sTemp.toUpperCase());        }        return sb.toString();    }

藍(lán)牙通信需要用到的UUID,關(guān)于uuid不懂的就自己百度了。

// 溫度值藍(lán)牙特征服務(wù)UUIDpublic static final UUID TEMP_SERVICE_UUID = UUID.fromString("00001809-0000-1000-8000-00805f9b34fb");// 溫度值藍(lán)牙特征值UUIDpublic static final UUID TEMP_CHAR_UUID = UUID.fromString("00002A1C-0000-1000-8000-00805f9b34fb");

那為了保證數(shù)據(jù)傳輸并顯示,這里主要測(cè)試了溫度的顯示。

// handler類接收數(shù)據(jù)    Handler handler = new Handler() {        public void handleMessage(Message msg) {            if (msg.what == 1) {                tv_display.setText(string1 + "℃");            }        };    };    // 線程類    class ThreadShow implements Runnable {        @Override        public void run() {            while (true) {                try {                    Thread.sleep(300);                    Message msg = new Message();                    msg.what = 1;                    handler.sendMessage(msg);                                 } catch (Exception e) {                    e.printStackTrace();                }            }        }    }

以上就是關(guān)于藍(lán)牙如何連接以及通信數(shù)據(jù)的自己的一點(diǎn)學(xué)習(xí)經(jīng)驗(yàn),目前還在深圳找工作,期待找到一家適合自己的工作吧!


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 城步| 桃江县| 新源县| 涟水县| 潜江市| 泾源县| 邹平县| 潮州市| 资溪县| 德昌县| 黄梅县| 松阳县| 哈巴河县| 夏河县| 紫云| 西充县| 钟山县| 大连市| 灵川县| 桦甸市| 荣昌县| 花莲市| 寿光市| 洛川县| 宁城县| 江都市| 黔江区| 舟曲县| 仪陇县| 台州市| 都兰县| 房产| 边坝县| 容城县| 措美县| 甘德县| 海原县| 汉寿县| 靖宇县| 弥渡县| 靖西县|