android IBeacon 开发(二)修改IBeacon参数

开发(一)中,我们介绍了怎么扫描到IBeacon。这节我们去看看怎么修改IBeacon的参数。

IBeacon里的参数,主要有这几个

name:设备名称

major:主参数

minor:副参数

mac:mac地址

UUID:IBeacon的UUID,相当与使用这个模块对映的应用的标识

rssi:信号强度

txPower:1m距离的信号强度参考值,他和rssi通过公司,可大体计算出距离来

通过上一章的扫描,我们获得了一个IBeacon的列表ArrayList,当我们想修改某个IBeacon的信息的时候,就要用到这个IBeacon的mac了

通过点击等等方式呢,我们可以获得某IBeacon的mac,

 1     /**
 2      * Connects to the GATT server hosted on the Bluetooth LE device.
 3      *
 4      * @param address
 5      *            The device address of the destination device.
 6      * @return Return true if the connection is initiated successfully. The
 7      *         connection result
 8      *         is reported asynchronously through the
 9      *         {@code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)}
10      *         callback.
11      */
12     public boolean connect(final String address)
13     {
14         if (mBluetoothAdapter == null || address == null)
15         {
16             Log.w(TAG, "BluetoothAdapter not initialized or unspecified address.");
17             return false;
18         }
19
20         // Previously connected device.  Try to reconnect.
21         if (mBluetoothDeviceAddress != null && address.equals(mBluetoothDeviceAddress) && mBluetoothGatt != null)
22         {
23             Log.d(TAG, "Trying to use an existing mBluetoothGatt for connection.");
24             if (mBluetoothGatt.connect())
25             {
26                 return true;
27             }
28             else
29             {
30                 return false;
31             }
32         }
33
34         final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
35         if (device == null)
36         {
37             Log.w(TAG, "Device not found.  Unable to connect.");
38             return false;
39         }
40         // We want to directly connect to the device, so we are setting the autoConnect
41         // parameter to false.
42         mBluetoothGatt = device.connectGatt(mContext, false, mGattCallback);
43         Log.d(TAG, "Trying to create a new connection.");
44         mBluetoothDeviceAddress = address;
45         return true;
46     }
47     

根据大神的代码呢,我们connect (mac地址),这样呢我们就可以获得BluetoothGatt。但是,连接完成了,再干嘛???

我们少了N步。

在大神的代码BluetoothLeClass类里,我们看到了好几个接口,这些接口是干嘛的?

OnConnectListener:当连接成功时调用

OnDisconnectListener:连接关闭是调用

OnServiceDiscoverListener:当services被发现的时候调用

OnDataAvailableListener:当有数据交互的时候调用

这里有个问题了,services是啥,是干神马的?

看了大神的解释,还是一头雾水啊。然后我就去看了BLE蓝牙的协议栈和其他N种东西,搞明白了他。

services是这样滴。每个IBeacon 都是基于BLE的,而BLE信息交互的时候,需要有个东西当接口啊,services就是这种东东。

就例如 BLE要做一个钟表,那就得有个service能不断的发送当前时间给显示器,like

同理,我们和IBeacon 通信,就是去调用BLE里的某个Service。

我们知道IBeacon里的参数有好几个呢,一个service够吗?跟你说,够了。

每个service下边还有多个Characteristic,就相当于service是端口,Characteristic是程序,不同的程序处理不同的东西,但数据都通过同一个端口(service)进出。

当然,service下边还有多个Descriptor,就是描述符,没啥大用。

对了,services,Characteristic这些东东,都是通过UUID来标识的,就相当于UUID是service、Characteristic的名字一样。

下边我们看看大神定义的接口都是怎么工作的。

 1     // Implements callback methods for GATT events that the app cares about.  For example,
 2     // connection change and services discovered.
 3     private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback()
 4     {
 5         @Override
 6         public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState)
 7         {
 8             Log.e(TAG, "onConnectionStateChange完成");
 9             if (newState == BluetoothProfile.STATE_CONNECTED)
10             {
11                 if (mOnConnectListener != null)
12                     mOnConnectListener.onConnect(gatt);
13                 Log.i(TAG, "Connected to GATT server.");
14                 // Attempts to discover services after successful connection.
15                 Log.i(TAG, "Attempting to start service discovery:" + mBluetoothGatt.discoverServices());
16
17             }
18             else if (newState == BluetoothProfile.STATE_DISCONNECTED)
19             {
20                 if (mOnDisconnectListener != null)
21                     mOnDisconnectListener.onDisconnect(gatt);
22                 Log.i(TAG, "Disconnected from GATT server.");
23             }
24         }
25
26         @Override
27         public void onServicesDiscovered(BluetoothGatt gatt, int status)
28         {
29             Log.e(TAG, "onServicesDiscovered完成");
30             if (status == BluetoothGatt.GATT_SUCCESS && mOnServiceDiscoverListener != null)
31             {
32                 mOnServiceDiscoverListener.onServiceDiscover(gatt);
33             }
34             else
35             {
36                 Log.w(TAG, "onServicesDiscovered received: " + status);
37             }
38         }
39
40         @Override
41         public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status)
42         {
43             Log.e(TAG, "onCharacteristicRead完成");
44             if (mOnDataAvailableListener != null)
45                 mOnDataAvailableListener.onCharacteristicRead(gatt, characteristic, status);
46         }
47
48         @Override
49         public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status)
50         {
51             Log.e(TAG, "onCharacteristicWrite完成");
52             if (mOnDataAvailableListener != null)
53                 mOnDataAvailableListener.onCharacteristicWrite(gatt, characteristic, status);
54         }
55         @Override
56         public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic)
57         {
58             Log.e(TAG, "onCharacteristicChanged完成");
59             if (mOnDataAvailableListener != null)
60                 mOnDataAvailableListener.onCharacteristicChanged(gatt, characteristic);
61         }
62     };

这里我改了下代码,

1     public interface OnDataAvailableListener
2     {
3         public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status);
4
5         public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic);
6
7         public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status);
8     }

OnConnectListener、OnDisconnectListener这两个接口,一看就是一对

onCharacteristicRead、onCharacteristicWrite、onCharacteristicChanged这三个,从函数名上也能看出作用来。

那么,定义好这些个listener,嗯,C#里边就是委托了,我就就得看看他是怎么工作的了。

本文一开始就说connect函数了,当connect成功后,就回去调用  onConnectionStateChange(连接状态改变事件),然后根据某值,分离出是连接成功还是连接失败。

在大神的代码了,我看到了调用OnConnectListener,但是怎么发现service呢。

大神开了个玩笑啊,将最重要的一句代码写在了Log.i里边,我狂晕啊,找了好半天呢。

mBluetoothGatt.discoverServices()就这句。。。。。。解释一下这句代码?——发现service

发现services,发现的services在哪?

好吧,android还是调用回调,onServicesDiscovered

发现services完成后,调用onServiceDiscover,这样我们就能获得BluetoothGatt,然后调用BluetoothGatt.getServices()获取所有的services了,当然你还可以根据你所开发的IBeacon的文档中定义的service的UUID,通过调用BluetoothGatt.getService(某个UUID)直接找这个service。

我所用的service的UUID是  0000fff0-0000-1000-8000-00805f9b34fb

我们获取了service,就可以通信了。

 1     private void displayGattServices(List<BluetoothGattService> gattServices)
 2     {
 3         if (gattServices == null)
 4             return;
 5
 6         for (BluetoothGattService gattService : gattServices)
 7         {
 8             //-----Service的字段信息-----//
 9             int type = gattService.getType();
10             Log.e(TAG, "-->service type:" + Utils.getServiceType(type));
11             Log.e(TAG, "-->includedServices size:" + gattService.getIncludedServices().size());
12             Log.e(TAG, "-->service uuid:" + gattService.getUuid());
13
14             //-----Characteristics的字段信息-----//
15             List<BluetoothGattCharacteristic> gattCharacteristics = gattService.getCharacteristics();
16             for (final BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics)
17             {
18                 Log.e(TAG, "---->char uuid:" + gattCharacteristic.getUuid());
19
20                 int permission = gattCharacteristic.getPermissions();
21                 Log.e(TAG, "---->char permission:" + Utils.getCharPermission(permission));
22
23                 int property = gattCharacteristic.getProperties();
24                 Log.e(TAG, "---->char property:" + Utils.getCharPropertie(property));
25
26                 byte[] data = gattCharacteristic.getValue();
27                 if (data != null && data.length > 0)
28                 {
29                     Log.e(TAG, "---->char value:" + new String(data));
30                 }
31
32                 //UUID_KEY_DATA是可以跟蓝牙模块串口通信的Characteristic
33                 if (gattCharacteristic.getUuid().toString().equals(UUID_KEY_DATA))
34                 {
35                     //测试读取当前Characteristic数据,会触发mOnDataAvailable.onCharacteristicRead()
36                     mHandler.postDelayed(new Runnable()
37                     {
38                         @Override
39                         public void run()
40                         {
41                             mBLE.readCharacteristic(gattCharacteristic);
42                         }
43                     }, 500);
44
45                     //接受Characteristic被写的通知,收到蓝牙模块的数据后会触发mOnDataAvailable.onCharacteristicWrite()
46                     mBLE.setCharacteristicNotification(gattCharacteristic, true);
47                     //设置数据内容
48                     byte[] bytes = new byte[6];
49
50                     bytes[0] = 1;
51                     bytes[1] = 2;
52                     bytes[2] = 3;
53                     bytes[3] = 4;
54                     bytes[4] = 5;
55                     bytes[5] = 6;
56                     gattCharacteristic.setValue("123456");
57                     //往蓝牙模块写入数据
58                     mBLE.writeCharacteristic(gattCharacteristic);
59                     Log.v(TAG, "写入");
60                 }
61
62                 //-----Descriptors的字段信息-----//
63                 List<BluetoothGattDescriptor> gattDescriptors = gattCharacteristic.getDescriptors();
64                 for (BluetoothGattDescriptor gattDescriptor : gattDescriptors)
65                 {
66                     Log.e(TAG, "-------->desc uuid:" + gattDescriptor.getUuid());
67                     int descPermission = gattDescriptor.getPermissions();
68                     Log.e(TAG, "-------->desc permission:" + Utils.getDescPermission(descPermission));
69
70                     byte[] desData = gattDescriptor.getValue();
71                     if (desData != null && desData.length > 0)
72                     {
73                         Log.e(TAG, "-------->desc value:" + new String(desData));
74                     }
75                 }
76             }
77         }//
78
79     }

大神的代码里,把所有的services,Characteristic都显示出来了,每个Characteristic也都读取了一遍。然后又在   UUID_KEY_DATA  表示的那个Characteristic里边写了点什么。

一开始我不太懂,为啥还得等500毫秒,后来我知道了,BLE是单双工通信的。

解释一下,“双工通信”是指的两边都可以发送信息,也都可以接收信息,“单”代表通信双方不能同时收发信息。

就是说,我发送信息(读、写)给IBeacon,在IBeacon返回信息之前,我不能有任何操作。

好了,言归正传。

我们只看到了mBLE.readCharacteristic(gattCharacteristic);mBLE.writeCharacteristic(gattCharacteristic);,但是读写出来的数据呢?

在这个mBLE.setCharacteristicNotification(gattCharacteristic, true);之前的注释里,我们看到

//接受Characteristic被写的通知,收到蓝牙模块的数据后会触发mOnDataAvailable.onCharacteristicWrite()

好吧,我们知道了,他会去调用mOnDataAvailable里的函数。

大体流程就是这样滴。

时间: 2024-08-03 05:50:03

android IBeacon 开发(二)修改IBeacon参数的相关文章

CSDN Android客户端开发(二):详解如何基于Java用Jsoup爬虫HTML数据

本文参考链接详细介绍如何使用Jsoup包抓取HTML数据,是一个纯java工程,并将其打包成jar包.希望了解如何用java语言爬虫网页的可以看下. 杂家前文就又介绍用HTTP访问百度主页得到html的string字符串,但html的文本数据如果不经过处理就是个文本字符串没有任何效果的.所谓的浏览器就是负责将文本的html"翻译"成看到的界面.在前文有介绍,这个csdn的客户端app分首页.业界.移动.研发.程序员.云计算五大类.以业界为例,http://news.csdn.net/ 

Android NDK开发(二)——从Hello World学起

转载请注明出处:http://blog.csdn.net/allen315410/article/details/41805719  上篇文章讲述了Android NDK开发的一些基本概念,以及NDK的环境搭建,相信看过的朋友NDK开发环境搭建应该是没有问题了,还没有搭建或者不知道怎么搭建的朋友请点击这里.那么这篇文章,我们跟刚学Java编程语言一样,从世界知名程序"Hello World!"开始,开发出我们的第一个NDK程序. NDK目录简单介绍 在进行NDK开发之前,我们有必须熟悉

玩转Android Camera开发(二):使用TextureView和SurfaceTexture预览Camera 基础拍照demo

Google自Android4.0出了TextureView.为什么推出呢?就是为了弥补Surfaceview的不足.另外一方面也是为了平衡GlSurfaceView.当然这是本人揣度的. 关于TextureView.Surfaceview.SurfaceTexture.GLSurfaceView的关系,待咱家推出GLSurfaceview预览Camera后再专门分析. 本文主要介绍使用TextureView预览Camera. 事实上关于怎样用TextureView预览Camera,官网已经给出

Android项目开发二

新浪微博客户端开发 本周学习计划 学习布局控件和UI设计相关知识. 微博验证,学习OAuth相关知识. 看懂微博客户端开发部分代码. 把借鉴代码导入到Android Studio中并运行成功. 实际完成情况 我学习到布局控件XML在res/layout中,是以.xml的形式保存.下图是登录界面,这个layout采用LinearLayout控件作为顶层控件,然后用ImageView控件分别实现版本号图片顶部靠左对齐显示.软件名称和图标图片居中对齐.作者名称和blog图片底部靠右对齐. 2.微博验证

C#-Xamarin的Android项目开发(二)——控件应用

相信我,这不是一篇吐槽文章.... 基础控件 Android的控件和控件样式非常特别,它是一种内联特别高的设计模式,换句话说,它是非常烂的设计.... 但在这种特别的关系里还是有一定的规律的,下面我们一起来看看控件的使用方式. 首先我们定义一个ImageButton,如下: <ImageButton android:src="@drawable/toolbar_upload_photo_normal" android:layout_gravity="right|cent

Android开发--二维码开发应用(转载!)

android项目开发 二维码扫描   基于android平台的二维码扫描项目,可以查看结果并且链接网址 工具/原料 zxing eclipse 方法/步骤 首先需要用到google提供的zxing和core.jar文件,可以在csdn上下载   解压zxing,并将android文件夹作为项目导入到eclipse中   打开文件列表,在libs文件中导入core.jar,并修改掉部分报错的地方(都是小问题,按照提示修改就行)   项目在这个时候就可以运行了,效果如图所示(在这之前我已经对界面进

Android TV开发--实现延时关机功能(二)逻辑实现

模块功能描述(总述) 上一篇文章:Android TV开发--实现延时关机功能(一)功能描述 讲的是延时关机整体功能描述以及UI效果,这篇文章将着重讲解逻辑实现. 按照功能模块分为3部分:关机App.关机Service.Launcher 模块图如下: 关机App模块 主要功能:1.展示UI设置延时时长 2.取消延时关机 3.取消延时对话框倒计时功能 1.展示UI设置延时时长 此处即为延时关机功能入口: 1.布局及逻辑处理Activity如下,代码中含有注释: /** * 延时关机 */ publ

上门洗车APP --- Android客户端开发 之 网络框架封装(二)

上门洗车APP --- Android客户端开发 之 网络框架封装(二) 前几篇博文中给大家介绍了一下APP中的基本业务及开发本项目使用的网络架构: 上门洗车APP --- Android客户端开发 前言及业务简介 上门洗车APP --- Android客户端开发 之 网络框架封装介绍(一) 本篇接着给大家分享网络框架封装,相信感兴趣的朋友已经对上篇博文中的一些开源项目有了些许了解,这里继续为大家介绍关于GenericDataManager 通用网络管理类中的 dataRequest 方法 和

十二、Android UI开发专题(转)

http://dev.10086.cn/cmdn/bbs/viewthread.php?tid=18736&page=1#pid89255Android UI开发专题(一) 之界面设计 近期很多网友对Android用户界面的设计表示很感兴趣,对于Android UI开发自绘控件和游戏制作而言掌握好绘图基础是必不可少的.本次专题分10节来讲述,有关OpenGL ES相关的可能将放到以后再透露.本次主要涉及以下四个包的相关内容: android.content.res 资源类 android.gra