使用Android Beacon Library解析Eddystone EID的技术问题
解析RadiusNetwork 4X信标EID的完整实现(用Google API密钥而非OAuth)
我刚好折腾过类似的需求,先给你划个重点:Android Beacon Library本身并不带EID解密逻辑——EID的解密必须依赖Google的Proximity Beacon API,虽然官方文档里OAuth的提及更多,但API密钥确实可以用于客户端请求,只要你做好密钥的权限限制就行。
下面是一步到位的实现方案,包含代码和注意事项:
一、前期准备
- 先在Google Cloud项目里启用Proximity Beacon API
- 创建一个API密钥,一定要限制它的使用范围:只允许调用Proximity Beacon API,最好再绑定你的Android应用包名和SHA-1,避免密钥泄露后被滥用
- 从Android Beacon Library的扫描结果里拿到EID值(比如
beacon.getId1().toHexString()) - 扫描到EID时的UTC时间戳必须准确,API靠这个来解密
二、核心代码实现
我们直接用OkHttp发REST请求调用解密接口,不用额外的客户端SDK:
1. 先加依赖(app/build.gradle)
implementation 'com.squareup.okhttp3:okhttp:4.11.0' implementation 'org.json:json:20230618'
2. 写个EID解密工具类
import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; import org.json.JSONObject; import java.io.IOException; import java.time.Instant; public class EidDecoder { // 替换成你的Google API密钥 private static final String GOOGLE_API_KEY = "your-api-key-here"; private static final String DECRYPT_ENDPOINT = "https://proximitybeacon.googleapis.com/v1beta1/beacons:decryptEid?key=" + GOOGLE_API_KEY; public static String decryptEid(String eidHex) throws IOException { OkHttpClient client = new OkHttpClient(); // 构建请求体:必须传EID和当前UTC时间 JSONObject requestBody = new JSONObject(); requestBody.put("eid", eidHex); requestBody.put("now", Instant.now().toString()); // 格式是"2024-05-20T12:34:56Z"这种 Request request = new Request.Builder() .url(DECRYPT_ENDPOINT) .post(okhttp3.RequestBody.create( requestBody.toString(), okhttp3.MediaType.parse("application/json; charset=utf-8"))) .build(); try (Response response = client.newCall(request).execute()) { if (!response.isSuccessful()) throw new IOException("请求失败:" + response.code()); String responseJson = response.body().string(); JSONObject result = new JSONObject(responseJson); // 解密后会返回信标的稳定UUID,这里直接返回,你也可以按需取其他字段 return result.getJSONObject("beaconName").getString("stableUuid"); } } }
3. 结合Android Beacon Library的扫描回调使用
BeaconManager beaconManager = BeaconManager.getInstanceForApplication(getApplicationContext()); // 配置RadiusNetwork 4X的EID解析布局 beaconManager.getBeaconParsers().add(new BeaconParser() .setBeaconLayout("s:0-1=feaa,m:2-2=00,p:3-3:-41,i:4-13,i:14-19")); // 添加扫描回调 beaconManager.addRangeNotifier((beacons, region) -> { for (Beacon beacon : beacons) { String eidHex = beacon.getId1().toHexString(); // 网络请求不能在主线程跑,开个线程处理 new Thread(() -> { try { String stableUuid = EidDecoder.decryptEid(eidHex); // 回到主线程更新UI或者处理结果 runOnUiThread(() -> { // 比如把解密后的UUID显示出来 Log.d("EID解密结果", stableUuid); }); } catch (IOException e) { e.printStackTrace(); // 这里可以加错误处理,比如提示用户解密失败 } }).start(); } }); // 启动扫描 try { beaconManager.startRangingBeaconsInRegion(new Region("my-ranging-id", null, null, null)); } catch (RemoteException e) { e.printStackTrace(); }
三、必看的注意事项
- 网络权限:别忘了在AndroidManifest.xml里加
<uses-permission android:name="android.permission.INTERNET" /> - 时间同步:设备时间必须和UTC同步,不然解密肯定失败
- API密钥安全:一定要在Google Cloud控制台给密钥加应用限制,只允许你的APP调用,不然密钥泄露了别人能随便用你的配额
- 异步处理:绝对不能在主线程发网络请求,上面用了Thread,你也可以用Coroutine或者RxJava
四、常见问题排查
- 要是返回
PERMISSION_DENIED:检查API密钥是不是没启用Proximity Beacon API,或者应用限制没配对 - 要是返回
INVALID_ARGUMENT:看看EID格式对不对,时间是不是UTC格式 - 要是返回
NOT_FOUND:这个EID对应的信标没在Google Proximity Beacon API里注册,得先去注册才行
内容的提问来源于stack exchange,提问作者Muppet
相关产品推荐
相关产品推荐

