成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

Android 4.0低功耗藍(lán)牙開(kāi)發(fā)!

justCoding / 1966人閱讀

摘要:連接回調(diào)連接成功連接斷開(kāi)改變當(dāng)前狀態(tài)當(dāng)服務(wù)發(fā)現(xiàn)之后回調(diào)這里四發(fā)現(xiàn)服務(wù)一個(gè)低功耗藍(lán)牙設(shè)備是有很多種服務(wù)的,就比如該設(shè)備的電量信息,設(shè)備的當(dāng)前狀態(tài)比如血壓計(jì)是正在測(cè)量還是在等待測(cè)量有的設(shè)備支持歷史數(shù)據(jù)等等。

????公司開(kāi)發(fā)任務(wù)是,將醫(yī)療設(shè)備通過(guò)藍(lán)牙集成到app中,在這開(kāi)發(fā)中遇到了數(shù)不盡的坑.在此記錄一下做一個(gè)記錄,如果其他開(kāi)發(fā)人員看見(jiàn)或許能提供一些幫助,如有不對(duì),盡情指正,不勝感激!

??剛開(kāi)始接觸的時(shí)候,被各種超長(zhǎng)的API嚇到了,像:BluetoothGatt , BluetoothGattCharacteristic , BluetoothGattDescriptor 等等.而且還要做多連接,上位機(jī)一對(duì)多下位機(jī).網(wǎng)上例子也是雜七雜八.看的頭暈.后來(lái)在老大的幫助下,漸漸明白許多,在此感謝老大.廢話到此結(jié)束,下面進(jìn)入正題.

一、檢測(cè)本機(jī)是否支持藍(lán)牙

1. 判斷當(dāng)前設(shè)備是否支持藍(lán)牙

BluetoothManager mBluetoothManager = (BluetoothManager) activity.getSystemService(Context.BLUETOOTH_SERVICE);
BluetoothAdapter adapter = mBluetoothManager.getAdapter();
if(adapter==null){    
   //系統(tǒng)不支持藍(lán)牙。
} 

2. 判斷當(dāng)前設(shè)備是否支持低功耗藍(lán)牙BLE

boolean isSupportBle = activity.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE);

3. 判斷藍(lán)牙是否開(kāi)啟,開(kāi)啟藍(lán)牙!

BluetoothManager mBluetoothManager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);
BluetoothAdapter adapter = mBluetoothManager.getAdapter();

if(!adapter.isEnable){  //未開(kāi)啟藍(lán)牙
    //申請(qǐng)開(kāi)啟藍(lán)牙
    Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
    startActivityForResult(intent , request);
}
二、開(kāi)始掃描周圍的藍(lán)牙設(shè)備
BluetoothAdapter adapter = mBluetoothManager.getAdapter();
adapter.startLeScan(callback); //掃描需要一個(gè)回調(diào)。

注意,掃描周圍藍(lán)牙是一個(gè)很耗電的過(guò)程,最好加上一個(gè)掃描時(shí)間。自動(dòng)停止。

handler.postDelayed(new Runnable() {
    @Override
    public void run() {
         adapter.stopLeScan(callback); //停止掃描
    }
},10000);//設(shè)置10秒鐘結(jié)束掃描
public BluetoothAdapter.LeScanCallback scanCallBack = new BluetoothAdapter.LeScanCallback() {
     @Override
     public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
           //這里注意,本人在開(kāi)發(fā)中遇到的是 經(jīng)常有的藍(lán)牙設(shè)備是沒(méi)有名字的, (device.getName == null)
           //不知道這是什么原因引起的,后來(lái)跟很多藍(lán)牙高手討論的是結(jié)果初步懷疑應(yīng)該是芯片的問(wèn)題
           //尤其是MTK的芯片經(jīng)常出現(xiàn)這種問(wèn)題,換了搭載高通和華為的芯片的設(shè)備就沒(méi)問(wèn)題了。
           
     }
};
三、連接藍(lán)牙設(shè)備
BluetoothDevice remoteDevice = adapter.getRemoteDevice(address);
remoteDevice.connectGatt(context, true, mGattCallback);//參數(shù)1:上下文。
                                                       //參數(shù)2:是否自動(dòng)連接(當(dāng)設(shè)備可以用時(shí))
                                                       //參數(shù)3:連接回調(diào)。

這里可能有些疑問(wèn)就是,明明已經(jīng)掃描到了,在回調(diào)中已經(jīng)有了 BluetoothDevice 為何還要去 getRemoteDevice(address)?
那是因?yàn)?,很多低功耗的設(shè)備開(kāi)機(jī)時(shí)間是很少的,就拿我們公司開(kāi)發(fā)的那個(gè)血壓計(jì),他是開(kāi)機(jī)才開(kāi)啟藍(lán)牙,而測(cè)量完了之后過(guò)一段時(shí)間就會(huì)自動(dòng)關(guān)閉。所以防止去連接設(shè)備的時(shí)候設(shè)備已經(jīng)關(guān)機(jī)的情況。

連接回調(diào)

private BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
    @Override
    public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
       if (newState == BluetoothProfile.STATE_CONNECTED) {
                //連接成功
        } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                //連接斷開(kāi)
        }
        changeStatus(newState);//改變當(dāng)前狀態(tài)
    }

    @Override
    public void onServicesDiscovered(BluetoothGatt gatt, int status) {
         //當(dāng)服務(wù)發(fā)現(xiàn)之后回調(diào)這里
    }

    @Override
    public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, 
    int status) {
    
    }

    @Override
    public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
    
    }

    @Override
    public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
    
    }
};
四、發(fā)現(xiàn)服務(wù)

一個(gè)低功耗藍(lán)牙設(shè)備是有很多種服務(wù)的,就比如該設(shè)備的電量信息,設(shè)備的當(dāng)前狀態(tài)(比如血壓計(jì),是正在測(cè)量還是在等待測(cè)量)
有的設(shè)備支持歷史數(shù)據(jù)等等。這些都是在藍(lán)牙的服務(wù)當(dāng)中。我們要去發(fā)現(xiàn)藍(lán)牙的服務(wù)!

這里很簡(jiǎn)單就是一句話,在連接成功的回調(diào)中調(diào)用:

public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
    if (newState == BluetoothProfile.STATE_CONNECTED) {
          //連接成功
          gatt.discoverServices();//開(kāi)始發(fā)現(xiàn)設(shè)備的服務(wù)
    } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
          //連接斷開(kāi)
    }
    changeStatus(newState);//改變當(dāng)前狀態(tài)
}

調(diào)用了之后會(huì)在 另一個(gè)回調(diào)中 回調(diào)回來(lái)。

     @Override
     public void onServicesDiscovered(BluetoothGatt gatt, int status) {
         //當(dāng)服務(wù)發(fā)現(xiàn)之后回調(diào)這里
     }
五、數(shù)據(jù)交互

這里是比較重要的地方,注意,每一個(gè)藍(lán)牙的通訊協(xié)議不通,有的設(shè)備是連接了之后不需要任何操作就等待藍(lán)牙設(shè)備上傳數(shù)據(jù)的,而有的設(shè)備是需要手動(dòng)打開(kāi)數(shù)據(jù)通道!或者發(fā)送指令給藍(lán)牙設(shè)備,每一個(gè)Gatt協(xié)議中有多個(gè)BluetoothGattService,而每個(gè)BluetoothGattService中又有多個(gè)BluetoothGattCharacteristic (我把它看做一個(gè)數(shù)據(jù)通道-_-!),而每一個(gè)BluetoothGattCharacteristic 的屬性是不同的,有的是可讀,有的是可寫,有的是可訂閱,所以一定不要搞混了,可以用UUID區(qū)分他們,這里大多數(shù)設(shè)備廠家都會(huì)給一份設(shè)備的通訊協(xié)議其中就有 哪一個(gè)UUID 代表什么。都會(huì)有說(shuō)明。通過(guò)UUID 獲取到了對(duì)應(yīng)的BluetoothGattCharacteristic 之后就可以判斷他的屬性是什么。

開(kāi)啟數(shù)據(jù)通道

@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
//服務(wù)發(fā)現(xiàn)方法回調(diào)。
  if (status == BluetoothGatt.GATT_SUCCESS) {
      BluetoothGattService service = gatt.getService(SERVICE_UUID); //通過(guò)廠家給的UUID獲取BluetoothGattService 
       if (service != null) {
           BluetoothGattCharacteristic characteristic = service.getCharacteristic(CHARACTERISTIC_UUID);//同上
            if (characteristic != null &&
                 (characteristic.getProperties() | BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) {
                   //通過(guò)判斷,打開(kāi)Notification 通知,提醒。一般是設(shè)備測(cè)量完成了之后會(huì)發(fā)送對(duì)應(yīng)的數(shù)據(jù)上來(lái)。
                   gatt.setCharacteristicNotification(characteristic, true);
                   
                   //在通過(guò)上面的設(shè)置返回為true之后還要進(jìn)行下面的操作,才能訂閱到數(shù)據(jù)的上傳。下面是完整的訂閱數(shù)據(jù)代碼!
                   if(gatt.setCharacteristicNotification(characteristic, true)){
                            for(BluetoothGattDescriptor dp: characteristic.getDescriptors()){
                                if (dp != null) {
                                    if ((characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_NOTIFY) != 0) {
                                        dp.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
                                    } else if ((characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_INDICATE) != 0) {
                                        dp.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
                                    }
                                    gatt.writeDescriptor(dp);
                                }
                            }
                        }
            }
       }
   }
 }

像設(shè)備發(fā)送指令
??一般向設(shè)備發(fā)送什么指令在通訊協(xié)議上面也是有的,都是發(fā)送一個(gè)byte[]數(shù)組,每一位代表什么協(xié)議里面都是不同的。例如:一個(gè)測(cè)量溫度的設(shè)備,他當(dāng)前是華氏度的單位,我們可以給他發(fā)送一個(gè)指令讓他把單位更換成攝氏度:

private void changeMonitorMod(BluetoothGatt gatt, byte[] buffer) {
   if (gatt != null && gatt != null) {
       BluetoothGattService writeService = gatt.getService(MYUUID);
       if (writeService == null) {
              return;
       }
   }

    BluetoothGattCharacteristic writeCharacteristic = writeService.getCharacteristic(MYWRITECHARACTERISTIC);
    if (writeCharacteristic == null) {
          return;
    }
    
    writeCharacteristic.setValue(buffer);
    //上面的buffer數(shù)組中裝的就是指令,多長(zhǎng)? 每一位上面的數(shù)字代表什么意思在協(xié)議中查看!
    gatt.writeCharacteristic(writeCharacteristic);//像設(shè)備寫入指令。
          
}

不要忘了,要在清單文件中AndroidManifest.xml 聲明權(quán)限哦。



關(guān)于一些坑:

很多廠家很坑爹,給的文檔水的要命,第一時(shí)間要看看文檔詳細(xì)不詳細(xì),如果沒(méi)有文檔至少也要給個(gè)Demo.

注意設(shè)備的開(kāi)機(jī)時(shí)間,自動(dòng)關(guān)機(jī)時(shí)間,對(duì)狀態(tài)的保存。

很多設(shè)備在自動(dòng)關(guān)機(jī)之后的回調(diào)是很慢的,甚至設(shè)備關(guān)機(jī)10秒之后才會(huì)回調(diào)到連接狀態(tài)的回調(diào)方法中。

關(guān)于手動(dòng)設(shè)置斷開(kāi) gatt.disConnect() 這個(gè)方法,我試過(guò)了,調(diào)用之后確實(shí)會(huì)立即回調(diào)到對(duì)應(yīng)的狀態(tài)方法中,但是實(shí)際上物理上的連接是還沒(méi)有斷開(kāi)的。物理上的連接斷開(kāi)之后還會(huì)再次回調(diào)到方法中。這是一個(gè)比較漫長(zhǎng)的回調(diào),區(qū)別與設(shè)備,不通設(shè)備的機(jī)制不一樣,有的快,有的慢。

??好了,差不多就這么多,寫的匆忙,如果有哪里不對(duì),輕噴,還請(qǐng)大佬們指正。謝啦!

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/66441.html

相關(guān)文章

  • 2017年云巴產(chǎn)品更新合集

    摘要:更新修正協(xié)議下默認(rèn)關(guān)閉時(shí)會(huì)取消訂閱本次訂閱的所有物聯(lián)網(wǎng)整體方案篇年,云巴利用實(shí)時(shí)跨平臺(tái)雙向物聯(lián)網(wǎng)云端系統(tǒng)的產(chǎn)品優(yōu)勢(shì),積極迎接物聯(lián)網(wǎng)新時(shí)代,為客戶定制物聯(lián)網(wǎng)整體解決方案。 SDK 篇 Android SDK 更新 ·Android Release 1.8.5在demo中去除掉小米、華為平臺(tái)的jar包,讓用戶自行下載 ·Android SDK 1.8.6對(duì)新版華為推送做了適配。 JavaS...

    Airmusic 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<