zoukankan      html  css  js  c++  java
  • android5.0(Lollipop) BLE Peripheral牛刀小试

    转载请表明作者: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。代码如下:

    1. private void init(){  
    2.     if(!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)){  
    3.         Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_LONG).show();  
    4.         finish();  
    5.     }  
    6.       
    7.     final BluetoothManager mBluetoothManager = (BluetoothManager) getSystemService(BLUETOOTH_SERVICE);  
    8.     mBluetoothAdapter = mBluetoothManager.getAdapter();  
    9.       
    10.     if(mBluetoothAdapter ==  null){  
    11.         Toast.makeText(this, R.string.bluetooth_not_supported, Toast.LENGTH_LONG).show();  
    12.         finish();  
    13.     }  
    14.       
    15.     mBluetoothLeAdvertiser = mBluetoothAdapter.getBluetoothLeAdvertiser();  
    16.     if(mBluetoothLeAdvertiser == null){  
    17.         Toast.makeText(this, "the device not support peripheral", Toast.LENGTH_SHORT    ).show();  
    18.         Log.e(TAG, "the device not support peripheral");  
    19.         finish();  
    20.     }  
    21. }  

    前几段代码我就不说了,搞过BLE的基本都是通用的,但是你会发现在代码里多了一句

    1. mBluetoothLeAdvertiser = mBluetoothAdapter.getBluetoothLeAdvertiser();  

    这一句代码会直接判断你的设备到底支持不支持BLE Peripheral。假如此返回值非空,你才可以继续有机会开发,如果返回空,那说明你的设备搞不了BLE Peripheral(当然,我的代码里没有判断是否打开了蓝牙,这个为了节省时间,你们自己可以添加上)。

    支持不支持BLE Peripheral,你也可以用BluetoothAdapter类的isMultipleAdvertisementSupported()函数去check,实际上getBluetoothLeAdvetiser()也会执行上面的isMultipleAdvertisementSupported函数,所以我就直接一步到位了,但是原理大家要懂。

    第三,你的设备已经支持BLE Peripheral了,那么下一步就是要考虑我怎么发广播了。但是你在发广播之前,要先准备自己的数据,比如你自己是什么service,里面有什么data等等。

    我们先来看看发广播的函数长得什么样子:

    1. mBluetoothLeAdvertiser.startAdvertising(createAdvSettings(true, 0), createAdvertiseData(), mAdvertiseCallback);  

    从广播函数应该可以看到所需要的参数,一个是广播设置参数,一个是广播数据,还有一个是Callback。当然startAdvertising有两种格式,另外一种可以获得广播数据的response。

    下面我们来看一下AdvertiseSettings:

    1. /** create AdvertiseSettings */  
    2.  public static AdvertiseSettings createAdvSettings(boolean connectable, int timeoutMillis) {  
    3.      AdvertiseSettings.Builder mSettingsbuilder = new AdvertiseSettings.Builder();  
    4.      mSettingsbuilder.setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_BALANCED);  
    5.      mSettingsbuilder.setConnectable(connectable);  
    6.      mSettingsbuilder.setTimeout(timeoutMillis);  
    7.      mSettingsbuilder.setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH);  
    8.      AdvertiseSettings mAdvertiseSettings = mSettingsbuilder.build();  
    9.         if(mAdvertiseSettings == null){  
    10.             if(D){  
    11.                 Toast.makeText(mContext, "mAdvertiseSettings == null", Toast.LENGTH_LONG).show();  
    12.                 Log.e(TAG,"mAdvertiseSettings == null");  
    13.             }  
    14.         }  
    15.     return mAdvertiseSettings;  
    16.  }  

    这里面一共有四个参数,AdvertiseMode、Connectable、Timeout、TxPowerLevel。当然我们可以设置我们需要的,其他的参数会使用默认的值。

    再就是格式很重要,我们一定要是AdvertiseSettings.builder,不然你只能设置一个参数。

    再就是AdvertiseData:

    1. public static AdvertiseData createAdvertiseData(){         
    2.     AdvertiseData.Builder    mDataBuilder = new AdvertiseData.Builder();  
    3.     mDataBuilder.addServiceUuid(ParcelUuid.fromString(HEART_RATE_SERVICE));  
    4.     AdvertiseData mAdvertiseData = mDataBuilder.build();  
    5.     if(mAdvertiseData==null){  
    6.         if(D){  
    7.             Toast.makeText(mContext, "mAdvertiseSettings == null", Toast.LENGTH_LONG).show();  
    8.             Log.e(TAG,"mAdvertiseSettings == null");  
    9.         }  
    10.     }  
    11.       
    12.     return mAdvertiseData;  
    13. }  

    这里面就需要设置很多参数了,我这里为了简单,只广播心跳的UUID,但是没有数据。如果你们有自己的数据等等,可以再这里面去设置,自定义函数也在AdvertiseData类里。

    最后一步就是准备Callback函数:

    1. private AdvertiseCallback mAdvertiseCallback = new AdvertiseCallback() {  
    2.     @Override  
    3.       public void onStartSuccess(AdvertiseSettings settingsInEffect) {  
    4.         super.onStartSuccess(settingsInEffect);  
    5.          if (settingsInEffect != null) {  
    6.              Log.d(TAG, "onStartSuccess TxPowerLv=" + settingsInEffect.getTxPowerLevel()     + " mode=" + settingsInEffect.getMode()  
    7.              + " timeout=" + settingsInEffect.getTimeout());  
    8.              } else {  
    9.              Log.e(TAG, "onStartSuccess, settingInEffect is null");  
    10.              }  
    11.             Log.e(TAG,"onStartSuccess settingsInEffect" + settingsInEffect);  
    12.           
    13.         }  
    14.       
    15.     @Override  
    16.     public void onStartFailure(int errorCode) {  
    17.         super.onStartFailure(errorCode);  
    18.         if(D)   Log.e(TAG,"onStartFailure errorCode" + errorCode);  
    19.           
    20.         if(errorCode == ADVERTISE_FAILED_DATA_TOO_LARGE){  
    21.             if(D){  
    22.                 Toast.makeText(mContext, R.string.advertise_failed_data_too_large, Toast.LENGTH_LONG).show();  
    23.                 Log.e(TAG,"Failed to start advertising as the advertise data to be broadcasted is larger than 31 bytes.");  
    24.             }  
    25.         }else if(errorCode == ADVERTISE_FAILED_TOO_MANY_ADVERTISERS){  
    26.             if(D){  
    27.                 Toast.makeText(mContext, R.string.advertise_failed_too_many_advertises, Toast.LENGTH_LONG).show();  
    28.                 Log.e(TAG,"Failed to start advertising because no advertising instance is available.");  
    29.             }  
    30.         }else if(errorCode == ADVERTISE_FAILED_ALREADY_STARTED){  
    31.             if(D){  
    32.                 Toast.makeText(mContext, R.string.advertise_failed_already_started, Toast.LENGTH_LONG).show();  
    33.                 Log.e(TAG,"Failed to start advertising as the advertising is already started");  
    34.             }  
    35.         }else if(errorCode == ADVERTISE_FAILED_INTERNAL_ERROR){  
    36.             if(D){  
    37.                 Toast.makeText(mContext, R.string.advertise_failed_internal_error, Toast.LENGTH_LONG).show();  
    38.                 Log.e(TAG,"Operation failed due to an internal error");  
    39.             }  
    40.         }else if(errorCode == ADVERTISE_FAILED_FEATURE_UNSUPPORTED){  
    41.             if(D){  
    42.                 Toast.makeText(mContext, R.string.advertise_failed_feature_unsupported, Toast.LENGTH_LONG).show();  
    43.                 Log.e(TAG,"This feature is not supported on this platform");  
    44.             }  
    45.         }  
    46.     }  
    47. };  

    当你广播成功,会受到onStartSuccess的回调,回调的参数也是AdvertiseSettings设置的参数。如果你还有你自己想做的,可以再这里面去做。

    为了大家方便,我把errorcode可能遇到的问题,都做了判断,只有这五种错误情况。

    最后一步就是关闭了,开了广播要关闭,不然会造成未知问题:

    1. private void stopAdvertise() {  
    2.      if (mBluetoothLeAdvertiser != null) {  
    3.          mBluetoothLeAdvertiser.stopAdvertising(mAdvertiseCallback);  
    4.          mBluetoothLeAdvertiser = null;  
    5.      }  
    6.  }  

    ok,代码就是这么简单,只要熟悉流程就可以搞定。希望对大家有帮助。

    代码路径为:http://download.csdn.net/detail/lansefeiyang08/8799027

  • 相关阅读:
    XAF 有条件的对象访问权限
    XAF 顯示 UnInplace Report(設置自定義條件顯示報表,不是根據選擇ListView記錄條件顯示報表)
    XAF 如何自定义PivotGrid单元格显示文本?
    XAF 如何布局详细视图上的按钮
    XAF How to set size of a popup detail view
    XAF Delta Replication Module for Devexpress eXpressApp Framework
    XAF 帮助文档翻译 EasyTest Basics(基础)
    XAF 用户双击ListView记录时禁止显示DetailView
    XAF How to enable LayoutView mode in the GridControl in List Views
    XAF 如何实现ListView单元格批量更改?
  • 原文地址:https://www.cnblogs.com/Free-Thinker/p/8677982.html
Copyright © 2011-2022 走看看