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。代码例如以下:

    	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的基本都是通用的,可是你会发如今代码里多了一句
    mBluetoothLeAdvertiser = mBluetoothAdapter.getBluetoothLeAdvertiser();

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

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

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

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

    mBluetoothLeAdvertiser.startAdvertising(createAdvSettings(true, 0), createAdvertiseData(), mAdvertiseCallback);
    从广播函数应该能够看到所须要的參数,一个是广播设置參数,一个是广播数据。另一个是Callback。当然startAdvertising有两种格式,第二种能够获得广播数据的response。

    以下我们来看一下AdvertiseSettings:

    	 /** create AdvertiseSettings */
    		 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:

    	 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函数:

    	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可能遇到的问题,都做了推断,仅仅有这五种错误情况。

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

    	 private void stopAdvertise() {
    			 if (mBluetoothLeAdvertiser != null) {
    				 mBluetoothLeAdvertiser.stopAdvertising(mAdvertiseCallback);
    				 mBluetoothLeAdvertiser = null;
    			 }
    		 }
    ok,代码就是这么简单。仅仅要熟悉流程就能够搞定。希望对大家有帮助。

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









  • 相关阅读:
    Laxcus集群操作系统的分布计算模型
    LAXCUS集群操作系统能不能防止DDOS攻击
    elasticsearch安装启动过程遇到的问题
    Centos7安装snort可视化IDS平台
    网络与信息安全 -国际学术会议和期刊目录
    包的概念、导入与可见性---Go
    Encrypted Traffic Analytics 加密流量分析功能
    商务谈判技巧
    东南大学《数字图像处理》课程作业 8
    东南大学《数字图像处理》课程作业 7
  • 原文地址:https://www.cnblogs.com/lxjshuju/p/7171924.html
Copyright © 2011-2022 走看看