android蓝牙4.0(BLE)开发之ibeacon初步
-
此文使用的ibeacon模块是april beacon,至于什么是ibeacon。本文不做解释,具体请自查。
一个april beacon里携带的信息如下
10201061AFF4C0002159069BDB88C11416BAC3F33468C2788A3044B0378C60C09417072696C426561636F6E051250002003020A0000000000000000000000
具体是什么意思呢
123456789101112131415161718192021222324252627282930313202
Number of bytes that follow in first AD structure
01
Flags AD type
06
Flags value
0x1A
=
000011010
bit
0
(OFF) LE Limited Discoverable Mode
bit
1
(ON) LE General Discoverable Mode
bit
2
(OFF) BR/EDR Not Supported
bit
3
(ON) Simultaneous LE and BR/EDR to Same Device Capable (controller)
bit
4
(ON) Simultaneous LE and BR/EDR to Same Device Capable (Host)
1a Number of bytes that follow in second (and last) AD structure
前面是常规智能硬件广播包部分
ff (FF代表后面是Manufacture Data)
4c
00
(组织标识,
0x4c00
苹果公司标识,https:
//www.bluetooth.org/en-us/specification/assigned-numbers/company-identifiers)
02
(
0x02
ibeacon标识位)
15
(
0x15
,
22
个字节标识长度,uuid,major,minor总和的长度)
90
69
bd b8-8c
11
-
41
6b-ac 3f-
33
46
8c
27
88
a3 (Proximity UUID)
04
4b(
1099
,major)
03
78
(
888
,minor)
c6 (切记这里是补码,转化为原码就是-
58
,iBeacon的信号发出强度值,用来作为和RSSI一起测距的基准 ,txPower)
计算
C6
1100
0110
补码
1100
0101
反码
1011
1010
原码
-(
32
+
16
+
8
+
2
)
-
58
0c09 (未知)
417072696c426561636f6e(AprilBeacon字符串对应的十六进制)
051250002003020a0000000000000000000000(未知)
Proximity UUID :这是将你所有的beacon与其他人的beacon设备区别开的id!例如,目前在商店里某个区域分布着多个beacon形成一条“链带”,用于为顾客提供特定的服务,那么归属于同一条“链带”的beacon将分配到相同的proximity UUID。为这条“链带”设计的专用应用程序将会在后台使用这个UUID扫描到这条“链带”中的beacon设备。
major 编号:用于将相关的beacon标识为一组。例如,一个商店中的所有beacon将会分配到相同的major编号。通过这种方式,应用程序就能够知道顾客位于哪一家商店。
minor 标号:用于标识特定的beacon设备。例如一个商店中的每一个beacon设备都拥有唯一的minor编号,这样你才能够知道顾客位于商店中的哪个位置。
Measuring distance(测量距离)
最后一个值, TX power ,用于确定你和beacon之间距离有多近。根据这个值不但可以获得粗略的信息(比如靠近/远离/不在范围内等),也可以获取精确到米的距离(当然你也可以转换为以步为单位的距离)。那么如何实现?TX power (上面例子中为0xC6=198,根据2的补码测得256-198=-58dBm)是距离设备1米测得的信号强度值(RSSI- Received Signal Strength Indication,接收到的信号强弱指标)。假如接收到的信号强度减弱了,那么我们可能在远离。只要知道1米距离的RSSI,以及当前的RSSI(我们可以从接收到的信号中一块获取到这些信息),那么计算出当前的距离是可能的。IOS已经实现了个这个功能,对于其它平台需要自己手动编码计算 。
一个简单的测距函数
12345678910111213protected
static
double
calculateAccuracy(
int
txPower,
double
rssi) {
if
(rssi ==
0
) {
return
-
1.0
;
// if we cannot determine accuracy, return -1.
}
double
ratio = rssi *
1.0
/ txPower;
if
(ratio <
1.0
) {
return
Math.pow(ratio,
10
);
}
else
{
double
accuracy = (
0.89976
) * Math.pow(ratio,
7.7095
) +
0.111
;
return
accuracy;
}
}
在使用蓝牙时需要加权限
12关键代码如下
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110package
cn.edu.zafu.ble;
import
android.app.Activity;
import
android.bluetooth.BluetoothAdapter;
import
android.bluetooth.BluetoothDevice;
import
android.bluetooth.BluetoothManager;
import
android.content.Context;
import
android.content.Intent;
import
android.os.Bundle;
import
android.util.Log;
public
class
MainActivity
extends
Activity {
private
BluetoothAdapter mBluetoothAdapter;
@Override
protected
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
if
(mBluetoothAdapter ==
null
|| !mBluetoothAdapter.isEnabled()) {
Intent enableBluetooth =
new
Intent(
BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBluetooth,
1
);
}
mBluetoothAdapter.startLeScan(mLeScanCallback);
}
private
BluetoothAdapter.LeScanCallback mLeScanCallback =
new
BluetoothAdapter.LeScanCallback() {
@Override
public
void
onLeScan(
final
BluetoothDevice device,
final
int
rssi,
final
byte
[] scanRecord) {
int
startByte =
2
;
boolean
patternFound =
false
;
// 寻找ibeacon
while
(startByte <=
5
) {
if
(((
int
) scanRecord[startByte +
2
] &
0xff
) ==
0x02
&&
// Identifies
// an
// iBeacon
((
int
) scanRecord[startByte +
3
] &
0xff
) ==
0x15
) {
// Identifies
// correct
// data
// length
patternFound =
true
;
break
;
}
startByte++;
}
// 如果找到了的话
if
(patternFound) {
// 转换为16进制
byte
[] uuidBytes =
new
byte
[
16
];
System.arraycopy(scanRecord, startByte +
4
, uuidBytes,
0
,
16
);
String hexString = bytesToHex(uuidBytes);
// ibeacon的UUID值
String uuid = hexString.substring(
0
,
8
) +
"-"
+ hexString.substring(
8
,
12
) +
"-"
+ hexString.substring(
12
,
16
) +
"-"
+ hexString.substring(
16
,
20
) +
"-"
+ hexString.substring(
20
,
32
);
// ibeacon的Major值
int
major = (scanRecord[startByte +
20
] &
0xff
) *
0x100
+ (scanRecord[startByte +
21
] &
0xff
);
// ibeacon的Minor值
int
minor = (scanRecord[startByte +
22
] &
0xff
) *
0x100
+ (scanRecord[startByte +
23
] &
0xff
);
String ibeaconName = device.getName();
String mac = device.getAddress();
int
txPower = (scanRecord[startByte +
24
]);
Log.d(
"BLE"
,bytesToHex(scanRecord));
Log.d(
"BLE"
,
"Name:"
+ ibeaconName +
"\nMac:"
+ mac
+
" \nUUID:"
+ uuid +
"\nMajor:"
+ major +
"\nMinor:"
+ minor +
"\nTxPower:"
+ txPower +
"\nrssi:"
+ rssi);
Log.d(
"BLE"
,
"distance:"
+calculateAccuracy(txPower,rssi));
}
}
};
static
final
char
[] hexArray =
"0123456789ABCDEF"
.toCharArray();
private
static
String bytesToHex(
byte
[] bytes) {
char
[] hexChars =
new
char
[bytes.length *
2
];
for
(
int
j =
0
; j < bytes.length; j++) {
int
v = bytes[j] &
0xFF
;
hexChars[j *
2
] = hexArray[v >>>
4
];
hexChars[j *
2
+
1
] = hexArray[v &
0x0F
];
}
return
new
String(hexChars);
}
protected
static
double
calculateAccuracy(
int
txPower,
double
rssi) {
if
(rssi ==
0
) {
return
-
1.0
;
// if we cannot determine accuracy, return -1.
}
double
ratio = rssi *
1.0
/ txPower;
if
(ratio <
1.0
) {
return
Math.pow(ratio,
10
);
}
else
{
double
accuracy = (
0.89976
) * Math.pow(ratio,
7.7095
) +
0.111
;
return
accuracy;
}
}
}
至此,本文也就结束,所谓初步,就是获取ibeacon模块的基本信息。
源码下载
http://download.csdn.net/detail/sbsujjbcy/8503507
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
2015-11-24 Swift 闭包表达式
2015-11-24 swift 深入理解Swift的闭包
2015-11-24 Swift学习之十四:闭包(Closures)
2015-11-24 Swift与Objective-C交互
2015-11-24 教你爱上Blocks(闭包)
2015-11-24 IOS开发环境更换后重新制作Provisioning Profile证书详解
2015-11-24 iOS点滴- ViewController详解