android L BLE Peripheral牛刀小试

知道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了,那么下一步就是要考虑我怎么发广播了。但是你在发广播之前,要先准备自己的数据,比如你自己是什么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

时间: 2024-10-02 12:00:38

android L BLE Peripheral牛刀小试的相关文章

android L BLE Central(Scanner)牛刀小试

转载请表明作者:http://blog.csdn.net/lansefeiyang08/article/details/46482073 昨天写了android L BLE Peripheral的简单使用,今天讲一下BLE Central的更新. 搞过android4.4的人肯定对BluetoothAdapter的startLeScan函数不会陌生,但是在android L已经弃用此接口,但是为了兼容以前的版本,这个接口还是可以使用的.但是谷歌已经单独拿出来android.bluetooth.l

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有一定的帮助. 此贴主要以解说代

android5.0(Lollipop) BLE Central牛刀小试

转载请表明作者:http://blog.csdn.net/lansefeiyang08/article/details/46482073 昨天写了android L BLE Peripheral的简单使用,今天讲一下BLE Central的更新. 搞过android4.4的人肯定对BluetoothAdapter的startLeScan函数不会陌生,但是在android L已经弃用此接口,但是为了兼容以前的版本,这个接口还是可以使用的.但是谷歌已经单独拿出来android.bluetooth.l

android BLE Peripheral 做外设模拟设备,供ios、android 连接通讯。

为了能让其它设备可以发现其设备,先启动特定广播.看自己需要什么广播格式. android 对外发出广播,都一样,只是更改其中的方法: android BLE Peripheral 模拟 ibeacon 发出ble 广播 开始广播: 增加使用BluetoothGattServer 1 public void startAdvertising(MockServerCallBack callBack) { 2 //获取BluetoothLeAdvertiser,BLE发送BLE广播用的一个API 3

android BLE Peripheral 手机模拟设备发出BLE广播 BluetoothLeAdvertiser

android 从4.3系统开始可以连接BLE设备,这个大家都知道了.iOS是从7.0版本开始支持BLE. android 进入5.0时代时,开放了一个新功能,手机可以模拟设备发出BLE广播, 这个新功能其实是 对标于 iOS系统的手机模拟iBeacon设备. 先介绍一下BLE的广播, BLE设备之所以能被手机扫描到,是因为 BLE设备一直在每隔 一段时间广播一次,这个广播里面包含很多数据. 手机扫描BLE设备代码如下: public void startScan(){ bluetoothAda

ANDROID L——Material Design具体解释(主题和布局)

转载请注明本文出自大苞米的博客(http://blog.csdn.net/a396901990).谢谢支持! Android L: Google已经确认Android L就是Android Lollipop(5.0). Google之前就已经提前推出了Android L Developer Preview(开发人员预览版)来帮助开发人员更快的了解Android特性.而不久前也推出了64位的模拟器镜像.并且首次搭载Android L系统的Nexus 6和 Nexus 9也即将上市. 相信Andro

[Android L]SEAndroid开放设备文件结点权限(读或写)方法(涵盖常用操作:sys/xxx、proc/xxx、SystemProperties)

温馨提示 建议你先了解一下上一篇博文([Android L]SEAndroid增强Androd安全性背景概要及带来的影响)所讲的内容,先对SEAndroid窥个全貌,然后再继续本节内容. 1 现象描述 基于Android L版本源码环境进行开发时,根据项目需求,APP层需要操作sys/xxx 或 proc/xxx下面的文件结点,但是会报出以下权限异常,无法直接操作这些结点 LedLightFileUtil( 4671): java.io.FileNotFoundException: /sys/c

Android L 漫游浅析

这篇文章主要是分析在Android L 源代码中对手机漫游的处理.当然我这里所说的漫游指的是国际漫游.通常我们判断手机是否在国际漫游,第一个想法就是比较网络上获取的MCC+MNC是否与手机中的IMSI相同,如果不同就判断为漫游了.如果是漫游的话,手机上最直观的可以看到就是两个地方了: a . 手机的屏幕的状态拦上手机信号角标的左下方是否有"R"显示. b . Setting --->About phone --->Status --->Roming 当然这是最粗略的比

Android L Camera2 API 使用实例程序汇总

在网上发现几个使用Camera API2开发的实例程序,总结一下方便后续参考: 1.Camera2 Basic : https://github.com/googlesamples/android-Camera2Basic This sample demonstrates how to use basic functionalities of Camera2 API. You can learn how to iterate through characteristics of all the