转载请表明作者: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

android5.0(Lollipop) BLE Peripheral牛刀小试的更多相关文章

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

    转载请表明作者:http://blog.csdn.net/lansefeiyang08/article/details/46482073 昨天写了android L BLE Peripheral的简单 ...

  2. android5.0(Lollipop) BLE Peripheral深入理解系统篇之提高篇

    上一篇文章讲到了广播之前系统需要进行的准备工作,那接下来我们就来真正的启动广播. 首先还是先看一下上一篇文章结束的地方: @Override public void onClientRegistere ...

  3. Android5.0(Lollipop) BLE蓝牙4.0+浅析code(二)

    作者:Bgwan链接:https://zhuanlan.zhihu.com/p/23347612来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. Android5.0(L ...

  4. Android5.0(Lollipop) BLE蓝牙4.0+浅析demo连接(三)

    作者:Bgwan链接:https://zhuanlan.zhihu.com/p/23363591来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. Android5.0(L ...

  5. Android5.0(Lollipop) BLE蓝牙4.0+浅析概念(四)

    作者:Bgwan链接:https://zhuanlan.zhihu.com/p/23679793来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 置顶:此文转载CSDN博 ...

  6. Android5.0(lollipop)新特性介绍(一)

    今年6月的Google I/O大会上.Android L的初次见面我相信让会让非常多android粉丝有些小激动和小期待.当然作为开发人员的我来说,激动不言而喻,毕竟这是自08年以来改变最大的一个版本 ...

  7. android5.0 BLE 蓝牙4.0+浅析demo搜索(一)

    作者:Bgwan链接:https://zhuanlan.zhihu.com/p/23341414来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 作者:Bgwan 莳萝花 ...

  8. 解决Android5.0以下Dialog引起的内存泄漏

    最近项目开发中,开发人员和测试人员均反应在android5.0以下手机上LeakCanary频繁监控到内存泄漏,如下图所示,但凡用到Dialog或DialogFragment地方均出现了内存泄漏. 如 ...

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

    为了能让其它设备可以发现其设备,先启动特定广播.看自己需要什么广播格式. 对于广播可见的mac address: 在调用startAdvertising();时,mac address 就会改变. 并 ...

随机推荐

  1. 【LeetCode】String to Integer (atoi)(字符串转换整数 (atoi))

    这道题是LeetCode里的第8道题. 题目要求: 请你来实现一个 atoi 函数,使其能将字符串转换成整数. 首先,该函数会根据需要丢弃无用的开头空格字符,直到寻找到第一个非空格的字符为止. 当我们 ...

  2. 图论trainning-part-1 B. A Walk Through the Forest

    B. A Walk Through the Forest Time Limit: 1000ms Memory Limit: 32768KB 64-bit integer IO format: %I64 ...

  3. 九度oj 题目1153:括号匹配问题

    题目描述: 在某个字符串(长度不超过100)中有左括号.右括号和大小写字母:规定(与常见的算数式子一样)任何一个左括号都从内到外与在它右边且距离最近的右括号匹配.写一个程序,找到无法匹配的左括号和右括 ...

  4. spring之注入类型

    spring有三种注入类型: set注入: 构造注入: 接口注入: 一.set注入(引用spring官方文档中的例子)(用的最多) 1.首先在代码中我们需要编写成员变量的set方法,如下所示,一般情况 ...

  5. bzoj3609 [Heoi2014]人人尽说江南好 博弈

    [Heoi2014]人人尽说江南好 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 581  Solved: 420[Submit][Status][D ...

  6. Spoj-NPC2015A Eefun Guessing Words

    Eefun Guessing Words Eefun is currently learning to read. His way of learning  is unique, by trying ...

  7. GFS, HDFS, Blob File System架构对比

    分布式文件系统很多,包括GFS,HDFS,淘宝开源的TFS,Tencent用于相册存储的TFS (Tencent FS,为了便于区别,后续称为QFS),以及Facebook Haystack.其中,T ...

  8. 洛谷 [P1995] 程序自动分析

    并查集+ 离散化 首先本题的数据范围很大,需要离散化, STL离散化代码: //dat是原数据,id是编号,sub是数据的副本 sort(sub + 1, sub + tot + 1); size = ...

  9. ci框架——数据库(增删改查)

    1:配置数据库(application/config/database.php)修改 $db['default'] = array( 'dsn' => '', 'hostname' => ...

  10. Idea其他设置

    一.生成javadoc Tools->Gerenate JavaDoc 1. 选择是整个项目还是模块还是单个文件 2. 文档输出路径 3. Locale 选择地区,这个决定了文档的语言,中文就是 ...