轉載請表明作者:http://blog.csdn.net/lansefeiyang08/article/details/46468743
知道Android L對藍牙對了一些改進,包括添加A2dp sink、HFP client、BLE Peripheral功能等等。
我花了一天多時間對Android L BLE Peripheral SDK進行了研究,網上的資料很少,有一個介紹的還不夠清晰,所以就自己寫了一個測試應用,希望可以對理解BLE Peripheral有一定的幫助。
此貼主要以講解代碼為主,我會把項目代碼也傳到CSDN中,幫助大家測試。
首先說明一點,并不是Android L的系統就可以支持BLE Peripheral,這個和硬件也是有關系的(以前有人告訴我支持BLE Peripheral是純軟件的東西,要不就是扯淡,要不就是我測得有問題)。我用我手上的Pad(支持BLE central,android5.0)發現直接不支持,Android5.0 SDK已經開始支持check手機是否支持BLE Peripheral,后面代碼會提到。
好了,下面我就直接上代碼了。為了代碼簡單整潔,我用一個Activity來完成最基本的功能,如果還有其他需求,只要稍微改一下就可以了。
我在寫這個代碼的時候,第一個困惑是BLE Peripheral操作流程是什么?代碼流程怎么寫?我相信大家和我應該是一樣的困惑。所以我不全部貼代碼(我上傳后,代碼直接下載好了)。我按照流程給大家說一下我寫的思路。
首先,我去查SDK的接口,我發現在android L SDK中多了一個package:android.bluetooth.le;里面多了Peripheral和Scanner,Scanner我會后面更新。
第二步開始寫代碼,代碼里首先檢查是否支持BLE、BLE Peripheral。代碼如下:
[java] view plain
copy private?void?init(){??????if(!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)){??????????Toast.makeText(this,?R.string.ble_not_supported,?Toast.LENGTH_LONG).show();??????????finish();??????}????????????final?BluetoothManager?mBluetoothManager?=?(BluetoothManager)?getSystemService(BLUETOOTH_SERVICE);??????mBluetoothAdapter?=?mBluetoothManager.getAdapter();????????????if(mBluetoothAdapter?==??null){??????????Toast.makeText(this,?R.string.bluetooth_not_supported,?Toast.LENGTH_LONG).show();??????????finish();??????}????????????mBluetoothLeAdvertiser?=?mBluetoothAdapter.getBluetoothLeAdvertiser();??????if(mBluetoothLeAdvertiser?==?null){??????????Toast.makeText(this,?"the?device?not?support?peripheral",?Toast.LENGTH_SHORT????).show();??????????Log.e(TAG,?"the?device?not?support?peripheral");??????????finish();??????}??}?? 前幾段代碼我就不說了,搞過BLE的基本都是通用的,但是你會發現在代碼里多了一句
[java] view plain
copy mBluetoothLeAdvertiser?=?mBluetoothAdapter.getBluetoothLeAdvertiser();?? 這一句代碼會直接判斷你的設備到底支持不支持BLE Peripheral。假如此返回值非空,你才可以繼續有機會開發,如果返回空,那說明你的設備搞不了BLE Peripheral(當然,我的代碼里沒有判斷是否打開了藍牙,這個為了節省時間,你們自己可以添加上)。
支持不支持BLE Peripheral,你也可以用BluetoothAdapter類的isMultipleAdvertisementSupported()函數去check,實際上getBluetoothLeAdvetiser()也會執行上面的isMultipleAdvertisementSupported函數,所以我就直接一步到位了,但是原理大家要懂。
第三,你的設備已經支持BLE Peripheral了,那么下一步就是要考慮我怎么發廣播了。但是你在發廣播之前,要先準備自己的數據,比如你自己是什么service,里面有什么data等等。
我們先來看看發廣播的函數長得什么樣子:
?
[java] view plain
copy mBluetoothLeAdvertiser.startAdvertising(createAdvSettings(true,?0),?createAdvertiseData(),?mAdvertiseCallback);?? 從廣播函數應該可以看到所需要的參數,一個是廣播設置參數,一個是廣播數據,還有一個是Callback。當然startAdvertising有兩種格式,另外一種可以獲得廣播數據的response。
下面我們來看一下AdvertiseSettings:
?
[java] view plain
copy ?public?static?AdvertiseSettings?createAdvSettings(boolean?connectable,?int?timeoutMillis)?{???????AdvertiseSettings.Builder?mSettingsbuilder?=?new?AdvertiseSettings.Builder();???????mSettingsbuilder.setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_BALANCED);???????mSettingsbuilder.setConnectable(connectable);???????mSettingsbuilder.setTimeout(timeoutMillis);???????mSettingsbuilder.setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH);???????AdvertiseSettings?mAdvertiseSettings?=?mSettingsbuilder.build();??????????if(mAdvertiseSettings?==?null){??????????????if(D){??????????????????Toast.makeText(mContext,?"mAdvertiseSettings?==?null",?Toast.LENGTH_LONG).show();??????????????????Log.e(TAG,"mAdvertiseSettings?==?null");??????????????}??????????}??????return?mAdvertiseSettings;???}?? 這里面一共有四個參數,AdvertiseMode、Connectable、Timeout、TxPowerLevel。當然我們可以設置我們需要的,其他的參數會使用默認的值。
再就是格式很重要,我們一定要是AdvertiseSettings.builder,不然你只能設置一個參數。
再就是AdvertiseData:
?
[java] view plain
copy public?static?AdvertiseData?createAdvertiseData(){?????????????AdvertiseData.Builder????mDataBuilder?=?new?AdvertiseData.Builder();??????mDataBuilder.addServiceUuid(ParcelUuid.fromString(HEART_RATE_SERVICE));??????AdvertiseData?mAdvertiseData?=?mDataBuilder.build();??????if(mAdvertiseData==null){??????????if(D){??????????????Toast.makeText(mContext,?"mAdvertiseSettings?==?null",?Toast.LENGTH_LONG).show();??????????????Log.e(TAG,"mAdvertiseSettings?==?null");??????????}??????}????????????return?mAdvertiseData;??}?? 這里面就需要設置很多參數了,我這里為了簡單,只廣播心跳的UUID,但是沒有數據。如果你們有自己的數據等等,可以再這里面去設置,自定義函數也在AdvertiseData類里。
最后一步就是準備Callback函數:
?
[java] view plain
copy private?AdvertiseCallback?mAdvertiseCallback?=?new?AdvertiseCallback()?{??????@Override????????public?void?onStartSuccess(AdvertiseSettings?settingsInEffect)?{??????????super.onStartSuccess(settingsInEffect);???????????if?(settingsInEffect?!=?null)?{???????????????Log.d(TAG,?"onStartSuccess?TxPowerLv="?+?settingsInEffect.getTxPowerLevel()?????+?"?mode="?+?settingsInEffect.getMode()???????????????+?"?timeout="?+?settingsInEffect.getTimeout());???????????????}?else?{???????????????Log.e(TAG,?"onStartSuccess,?settingInEffect?is?null");???????????????}??????????????Log.e(TAG,"onStartSuccess?settingsInEffect"?+?settingsInEffect);????????????????????}????????????@Override??????public?void?onStartFailure(int?errorCode)?{??????????super.onStartFailure(errorCode);??????????if(D)???Log.e(TAG,"onStartFailure?errorCode"?+?errorCode);????????????????????if(errorCode?==?ADVERTISE_FAILED_DATA_TOO_LARGE){??????????????if(D){??????????????????Toast.makeText(mContext,?R.string.advertise_failed_data_too_large,?Toast.LENGTH_LONG).show();??????????????????Log.e(TAG,"Failed?to?start?advertising?as?the?advertise?data?to?be?broadcasted?is?larger?than?31?bytes.");??????????????}??????????}else?if(errorCode?==?ADVERTISE_FAILED_TOO_MANY_ADVERTISERS){??????????????if(D){??????????????????Toast.makeText(mContext,?R.string.advertise_failed_too_many_advertises,?Toast.LENGTH_LONG).show();??????????????????Log.e(TAG,"Failed?to?start?advertising?because?no?advertising?instance?is?available.");??????????????}??????????}else?if(errorCode?==?ADVERTISE_FAILED_ALREADY_STARTED){??????????????if(D){??????????????????Toast.makeText(mContext,?R.string.advertise_failed_already_started,?Toast.LENGTH_LONG).show();??????????????????Log.e(TAG,"Failed?to?start?advertising?as?the?advertising?is?already?started");??????????????}??????????}else?if(errorCode?==?ADVERTISE_FAILED_INTERNAL_ERROR){??????????????if(D){??????????????????Toast.makeText(mContext,?R.string.advertise_failed_internal_error,?Toast.LENGTH_LONG).show();??????????????????Log.e(TAG,"Operation?failed?due?to?an?internal?error");??????????????}??????????}else?if(errorCode?==?ADVERTISE_FAILED_FEATURE_UNSUPPORTED){??????????????if(D){??????????????????Toast.makeText(mContext,?R.string.advertise_failed_feature_unsupported,?Toast.LENGTH_LONG).show();??????????????????Log.e(TAG,"This?feature?is?not?supported?on?this?platform");??????????????}??????????}??????}??};?? 當你廣播成功,會受到onStartSuccess的回調,回調的參數也是AdvertiseSettings設置的參數。如果你還有你自己想做的,可以再這里面去做。
為了大家方便,我把errorcode可能遇到的問題,都做了判斷,只有這五種錯誤情況。
最后一步就是關閉了,開了廣播要關閉,不然會造成未知問題:
?
[java] view plain
copy private?void?stopAdvertise()?{???????if?(mBluetoothLeAdvertiser?!=?null)?{???????????mBluetoothLeAdvertiser.stopAdvertising(mAdvertiseCallback);???????????mBluetoothLeAdvertiser?=?null;???????}???}?? ok,代碼就是這么簡單,只要熟悉流程就可以搞定。希望對大家有幫助。
代碼路徑為:http://download.csdn.net/detail/lansefeiyang08/8799027
轉載于:https://www.cnblogs.com/Free-Thinker/p/8677982.html
總結
以上是生活随笔為你收集整理的android5.0(Lollipop) BLE Peripheral牛刀小试的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。