iBeacon是苹果公司称为“一种可以检测到附近IOS7设备出现的一种新的低功耗、低成本信号传送器”的一套室内定位系统的商标。 这种技术可以使一个智能手机或其他装置在一个iBeacon基站的感应范围内能够执行相应的命令。iBeacon通过低功耗蓝牙近距离感应来向一个app或操作系统传输通用唯一识别码。
关于iBeacon的工作原理,请参考
http://blog.csdn.net/qinxiandiqi/article/details/39004337
iBeacon毕竟是苹果的东西,所以苹果提供了一套完整的iBeacon API给IOS开发人员,开发人员轻轻松松就可以让自己的APP实现相关功能。
相对来说,Android开发人员就比较麻烦了,需要自己调用BluetoothAdapter.startLeScan()去搜索iBeacon商标,
搜索出结果之后,还需要自己去解析iBeacon Format,多麻烦……
最近在GitHub上找到了一个开源库Android-Beacon-Library,它封装了一系列Beacons API(风格类似IOS),
Android开发人员,很轻松就可以将它整合到自己的APP中。
android-beacon-library官方网站:
http://altbeacon.github.io/android-beacon-library
网站里面有示例、代码、入门 、问题提交等,大家可以去看看……
注意,本人运行官方的示例,无法正常使用。主要原因是需要重新设置BeaconParser。
下面是我写的一个例子,供大家参考:
- package com.example.sample_beacon;
-
- import java.util.Collection;
-
- import org.altbeacon.beacon.Beacon;
- import org.altbeacon.beacon.BeaconConsumer;
- import org.altbeacon.beacon.BeaconManager;
- import org.altbeacon.beacon.BeaconParser;
- import org.altbeacon.beacon.MonitorNotifier;
- import org.altbeacon.beacon.RangeNotifier;
- import org.altbeacon.beacon.Region;
-
- import android.app.Activity;
- import android.os.Bundle;
- import android.os.RemoteException;
- import android.util.Log;
-
- public class MainActivity extends Activity implements BeaconConsumer
- {
- protected static final String TAG = "MonitoringActivity";
-
- public static final String IBEACON_FORMAT = "m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24";
-
- public static final String FILTER_UUID = "E2C56DB5-DFFB-48D2-B060-D0F5A71096E0";
-
- private BeaconManager beaconManager;
-
- @Override
- protected void onCreate(Bundle savedInstanceState)
- {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
-
- beaconManager = BeaconManager.getInstanceForApplication(this);
- beaconManager.getBeaconParsers().add(new BeaconParser().setBeaconLayout(IBEACON_FORMAT));
- beaconManager.bind(this);
- }
-
- @Override
- protected void onDestroy()
- {
- super.onDestroy();
- beaconManager.unbind(this);
- }
-
- @Override
- public void onBeaconServiceConnect()
- {
- beaconManager.setMonitorNotifier(new MonitorNotifier()
- {
- @Override
- public void didEnterRegion(Region region)
- {
- Log.e(TAG, "I just saw an beacon for the first time!");
- }
-
- @Override
- public void didExitRegion(Region region)
- {
- Log.e(TAG, "I no longer see an beacon");
- }
-
- @Override
- public void didDetermineStateForRegion(int state, Region region)
- {
- Log.e(TAG, "I have just switched from seeing/not seeing beacons: " + state);
- }
- });
-
- try
- {
-
- beaconManager.startMonitoringBeaconsInRegion(new Region(FILTER_UUID, null, null, null));
- }
- catch (RemoteException e)
- {
- e.printStackTrace();
- }
- }
-
- }
上述示例中,通过调用 beaconManager.getBeaconParsers()获取到BeaconParser列表,然后往里面添加一个我们自己定义的BeaconParser。
而BeaconParser是通过setBeaconLayout(String)方法,设置对应的Beacon格式。
以下是设置的iBeacon格式
- IBEACON_FORMAT = "m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24";
- m - matching byte sequence for this beacon type to parse (exactly one required)
s - ServiceUuuid for this beacon type to parse (optional, only for Gatt-based becons)
i - identifier (at least one required, multiple allowed)
p - power calibration field (exactly one required)
d - data field (optional, multiple allowed)
下面来简单说一下iBeacon广播的数据。
一般来说,我们在调用BluetoothAdapter.startLeScan()搜索iBeacon的时候,
会在回调函数onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord)中获取到iBeacon发出广播数据,
就是参数scanRecord所携带的数据。如下所示:
- 02 01 06 1A FF 4C 00 02 15 E2 C5 6D B5 DF FB 48 D2 B0 60 D0 F5 A7 10 96 E0 00 03 00 03 CD 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
把其它无关数据去掉,变成
- 02 01 06 1A FF 4C 00 02 15 E2 C5 6D B5 DF FB 48 D2 B0 60 D0 F5 A7 10 96 E0 00 03 00 03 CD
以上数据只包含了实际信息数据(其它数据如MAC、数据包报头……不在这里),共30字节
经过整理后,变成
- 02 01 06 1A FF 4C 00 02 15 (iBeacon的前缀,固定不变的)
- E2 C5 6D B5 DF FB 48 D2 B0 60 D0 F5 A7 10 96 E0 (UUID的值)
- 00 03 (major值)
- 00 03 (minor值)
- CD (tx值,表示距离1米是应该接收到的信号强度,可用于计算距离)
按照相关资料所述,识别是否iBeacon靠上面的红字(0215),参考资料如下
https://github.com/RadiusNetworks/android-ibeacon-service/blob/master/src/main/java/com/radiusnetworks/ibeacon/IBeacon.java
再回到之前我们要设置的BeaconParser的问题上……
在默认情况下,通过beaconManager.getBeaconParsers()方法获取到BeaconParser列表,默认只有一个。
而且,该默认的BeaconParser被设置为"m:2-3=beac,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25",
注意看m值,这里是”beac“来的,并不是iBeacon的标识,
也就是说,android-beacon-library这个库默认情况下,并不是用于扫描iBeacon,
想要用于扫描iBeacon商标,需要做以上修改 ……
好了,有点绕……没办法……
下面是我写的示例,仅供参考
http://download.csdn.net/detail/eieihihi/8679825