Android 开发中 iBeacon的使用
iBeacon的工作原理是基于Bluetooth Low Energy(BLE)低功耗蓝牙传输技术,iBeacon基站不断向四周发送蓝牙信号,当智能设备进入设定区域时,就能够收到信号。只要满足iBeacon技术标准的都可以使用,所以Android也能够支持iBeacon。Google在Android4.3中支持BLE技术
定位一直是非常关键的功能。通过iBeacon基站的部署能够实现室内导航,同时通过蓝牙推送信息,iBeacon在商场零售或者一些公共服务领域如体育馆、博物馆能提供非常棒的体验。尤其是蓝牙不错传输距离、低功耗、以及信号加密使得iBeacon在移动支付领域也非常有前景。总之,iBeacon的潜力似乎是无穷大,也受到了越来越多的关注。
要了解iBeacon是如何工作首先我们要了解BLE。BLE(也称为Bluetooth Smart)最早追溯到Nokia于2006年提出的Wibree,后来融合进了蓝牙标准,成为Bluetooth4.0的一部分。目前我们经常能看到3种蓝牙设备:
- Bluetooth:只支持传统模式的蓝牙设备
- Bluetooth Smart Ready:支持传统和低功耗两种模式设备
- Bluetooth Smart:只支持低功耗蓝牙设备
![]()
BLE与传统的蓝牙相比最大的优势是功耗降低90%,同时传输距离增大(超过100米)、安全和稳定性提高(支持AES加密和CRC验证)。iBeacon同时有一些自己的特点:
- 无需配对,一般蓝牙设备印象中都需要配对工作。iBeacon无需配对,因为它是采用蓝牙的广播频道传送信号。
- 程序可以后台唤醒,iBeacon的信息推送需要App支持。但是我们接收iBeacon信号无需打开App,只要保证安装了,同时手机蓝牙打开。
iBeacon是如何工作呢?实际上iBeacon基站通过蓝牙的广播频道不断向外发送位置信息,发送频率越快越耗电。也就是说iBeacon并不推送消息,而只是用于定位,推送消息的功能必须由App来完成。苹果定义了iBeacon 其中32位广播的数据格式。
![]()
- UUID:厂商识别号
- Major:相当于群组号,同一个组里Beacon有相同的Major
- Minor:相当于识别群组里单个的Beacon
- TX Power:用于测量设备离Beacon的距离
UUID+Major+Minor就构成了一个Beacon的识别号,有点类似于网络中的IP地址。TX Power用于测距,iBeacon目前只定义了大概的3个粗略级别:
- 非常近(Immediate): 大概10厘米内
- 近(Near):1米内
- 远(Far):1米外
这里主要是对其用法做一个介绍:
首先是获取BluetoothAdapter对象:
- final BluetoothManager bluetoothManager =
- (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
- mBluetoothAdapter = bluetoothManager.getAdapter();
- mBluetoothAdapter.startLeScan(mLeScanCallback);
然后就是它的回调,在这里对搜索到的iBeacon设备距手机的信号强度做了一个排序
- private BluetoothAdapter.LeScanCallback mLeScanCallback =
- new BluetoothAdapter.LeScanCallback() {
- @Override
- public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
- final iBeacon ibeacon = iBeaconClass.fromScanData(device,rssi,scanRecord);
- addDevice(ibeacon);
- Collections.sort(mLeDevices, new Comparator<iBeacon>() {
- @Override
- public int compare(iBeacon h1, iBeacon h2) {
- return h2.rssi - h1.rssi;
- }
- });
- }
- };
最后把搜索到的数据添加到集合中去
- private ArrayList<iBeacon> mLeDevices = new ArrayList<iBeacon>();
- private void addDevice(iBeacon device) { //更新beacon信息
- if(device==null) {
- Log.d("DeviceScanActivity ", "device==null ");
- return;
- }
- for(int i=0;i<mLeDevices.size();i++){
- String btAddress = mLeDevices.get(i).bluetoothAddress;
- if(btAddress.equals(device.bluetoothAddress)){
- mLeDevices.add(i+1, device);
- mLeDevices.remove(i);
- break;
- }
- }
- mLeDevices.add(device);
- }
我们在iBbeaconClass类中对其进行数据的解析处理,参考:https://github.com/AltBeacon/android-beacon-library
- public class iBeaconClass {
- static public class iBeacon{
- public String name;
- public int major;
- public int minor;
- public String proximityUuid;
- public String bluetoothAddress;
- public int txPower;
- public int rssi;
- }
- public static iBeacon fromScanData(BluetoothDevice device, int rssi,byte[] scanData) {
- int startByte = 2;
- boolean patternFound = false;
- while (startByte <= 5) {
- if (((int)scanData[startByte+2] & 0xff) == 0x02 &&
- ((int)scanData[startByte+3] & 0xff) == 0x15) {
- // yes! This is an iBeacon
- patternFound = true;
- break;
- }
- else if (((int)scanData[startByte] & 0xff) == 0x2d &&
- ((int)scanData[startByte+1] & 0xff) == 0x24 &&
- ((int)scanData[startByte+2] & 0xff) == 0xbf &&
- ((int)scanData[startByte+3] & 0xff) == 0x16) {
- iBeacon iBeacon = new iBeacon();
- iBeacon.major = 0;
- iBeacon.minor = 0;
- iBeacon.proximityUuid = "00000000-0000-0000-0000-000000000000";
- iBeacon.txPower = -55;
- return iBeacon;
- }
- else if (((int)scanData[startByte] & 0xff) == 0xad &&
- ((int)scanData[startByte+1] & 0xff) == 0x77 &&
- ((int)scanData[startByte+2] & 0xff) == 0x00 &&
- ((int)scanData[startByte+3] & 0xff) == 0xc6) {
- iBeacon iBeacon = new iBeacon();
- iBeacon.major = 0;
- iBeacon.minor = 0;
- iBeacon.proximityUuid = "00000000-0000-0000-0000-000000000000";
- iBeacon.txPower = -55;
- return iBeacon;
- }
- startByte++;
- }
- if (patternFound == false) {
- // This is not an iBeacon
- return null;
- }
- iBeacon iBeacon = new iBeacon();
- iBeacon.major = (scanData[startByte+20] & 0xff) * 0x100 + (scanData[startByte+21] & 0xff);
- iBeacon.minor = (scanData[startByte+22] & 0xff) * 0x100 + (scanData[startByte+23] & 0xff);
- iBeacon.txPower = (int)scanData[startByte+24]; // this one is signed
- iBeacon.rssi = rssi;
- // AirLocate:
- // 02 01 1a 1a ff 4c 00 02 15 # Apple's fixed iBeacon advertising prefix
- // e2 c5 6d b5 df fb 48 d2 b0 60 d0 f5 a7 10 96 e0 # iBeacon profile uuid
- // 00 00 # major
- // 00 00 # minor
- // c5 # The 2's complement of the calibrated Tx Power
- // Estimote:
- // 02 01 1a 11 07 2d 24 bf 16
- // 394b31ba3f486415ab376e5c0f09457374696d6f7465426561636f6e00000000000000000000000000000000000000000000000000
- byte[] proximityUuidBytes = new byte[16];
- System.arraycopy(scanData, startByte+4, proximityUuidBytes, 0, 16);
- String hexString = bytesToHexString(proximityUuidBytes);
- StringBuilder sb = new StringBuilder();
- sb.append(hexString.substring(0,8));
- sb.append("-");
- sb.append(hexString.substring(8,12));
- sb.append("-");
- sb.append(hexString.substring(12,16));
- sb.append("-");
- sb.append(hexString.substring(16,20));
- sb.append("-");
- sb.append(hexString.substring(20,32));
- iBeacon.proximityUuid = sb.toString();
- if (device != null) {
- iBeacon.bluetoothAddress = device.getAddress();
- iBeacon.name = device.getName();
- }
- return iBeacon;
- }
- public static String bytesToHexString(byte[] src){
- StringBuilder stringBuilder = new StringBuilder("");
- if (src == null || src.length <= 0) {
- return null;
- }
- for (int i = 0; i < src.length; i++) {
- int v = src[i] & 0xFF;
- String hv = Integer.toHexString(v);
- if (hv.length() < 2) {
- stringBuilder.append(0);
- }
- stringBuilder.append(hv);
- }
- return stringBuilder.toString();
- }
- }
Android 开发中 iBeacon的使用的更多相关文章
- Android学习探索之Java 8 在Android 开发中的应用
前言: Java 8推出已经将近2年多了,引入很多革命性变化,加入了函数式编程的特征,使基于行为的编程成为可能,同时减化了各种设计模式的实现方式,是Java有史以来最重要的更新.但是Android上, ...
- android开发中fragment获取context
在用到fragment时无法使用.this来指定当前context内容,android开发中fragment获取context,可以使用getActivity().getApplicationCont ...
- java中的反射机制在Android开发中的用处
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反 ...
- Android开发中的输入合法性检验
Why ? 合法性检查对于程序的健壮性具有重要作用.在Android开发中,良好的合法性检查设计机制可以使程序更加清晰,产生bug更少,交互更加友好. What ? 合法性检查的目的在于确定边界.对于 ...
- 在android开发中使用multdex的方法-IT蓝豹为你整理
Android系统在安装应用时,往往需要优化Dex,而由于处理工具DexOpt对id数目的限制,导致其处理的数目不能超过65536个,因此在Android开发中,需要使用到MultiDex来解决这个问 ...
- 怎样实现了捕获应用中的日志在android开发中
怎样实现了捕获应用中的日志在android开发中,大家可研究一下. Process mLogcatProc = null; BufferedReader reader = null; try { mL ...
- Android开发中Eclispe相关问题及相应解决(持续更新)
1.Eclipse项目中的Android Private Libraries没有自动生成. 一般而言,在Android开发中,项目中引用到的jar包会放到项目目录中的libs中,引入库会放到Andro ...
- Android开发中的问题及相应解决(持续更新)
最近博客写的少了,以后还得经常更新才行. ------------------------------------------------------------ 1.特定业务需求下try cath ...
- 关于Android开发中的证书和密钥等问题
关于Android开发中的证书和密钥等问题 引言 除了Android发布应用签名时需要用到证书外,在进行google Map Api开发和Facebook SDK API开发等时都需要申请API Ke ...
随机推荐
- php5.4安装ecshopphp5.4问题及解决
includes/cls_template.php line422 将 $tag_sel = array_shift(explode(" ", $tag)); 这句话拆开为两句. $tag_exp = ...
- PHPUnit测试
今天单元测试测到一个有点坑的小问题: public function testUpdataStatusFailForNegative() { // // Remove the following li ...
- apache2.4配置虚拟主机
step1 启用 httpd-vhosts.conf 找到E:/apache/Apache24/conf 中httpd.conf 文件,取消注释下面这句话 step2 在 httpd-vhosts.c ...
- Apache 支持.htaccess
******************************************************************************* Apache 服务器 ********* ...
- Windows下面对环境变量的操作
如何在cmd命令行中查看.修改.删除与添加环境变量:首先明确一点:所有的在cmd命令行下对环境变量的修改只对当前窗口有效,不是永久性的修改.也就是说当关闭此cmd命令行窗口后,将不再起作用.永久性修改 ...
- 【python】原始字符创
原始字符串语法在字符串前加"r" 如 tem=r"h\c\d\n"print(tem) 结果:h\c\d\n 注意:字符串结尾不能是\,否则报错,应对措施将\单 ...
- Python 学习笔记(2) - 基本概念、运算符与表达式
字符串 - 可以使用 3 种形式 - 单引号 :「'your string'」 - 双引号 :「"your string"」 - 三引号 :「'''your string''' 或 ...
- Xcode-01ARC / Block
1.nonatomic 2.assign 3.strong 4.weak 5.instancetype 6.@class @property 使部分类在编译时不使用ARC -(可以让这们支持 reta ...
- Socket 错误总结
错误 因为并没有搞清楚accept函数的使用,所以导致不停的发送失败,同时还不知道错误在哪里,无意中看见errno这个库,可以记录错误的原因,才知道原因在于没有用客户端的套接字进行接收数据,而这个客户 ...
- Solr -- Solr Facet 2
solr将以导航为目的的查询结果称为facet. 它并不会修改查询结果信息, 只是在查询结果上根据分类添加了count信息, 然后用户根据count信息做进一步的查询, 比如淘宝的查询列表中, 上面会 ...