From 08a9ae470426b9fe5592262df449637f4fee5a70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=89=BE=E5=90=89?= Date: Sat, 27 Jun 2026 13:29:33 +0800 Subject: [PATCH] feat: support setting location via adb broadcast Register a dynamic BroadcastReceiver in ServiceGo that listens for com.zcshou.gogogo.action.SET_LOCATION and reuses ServiceGoBinder.setPosition() to update lat/lng/alt. Enables scripted / automated coordinate injection without touching the UI; both GPS and NETWORK mock providers refresh within 100ms and the joystick current position is kept in sync. Usage (service must be started from the UI first so the receiver is alive): adb shell am broadcast -p com.zcshou.gogogo \ -a com.zcshou.gogogo.action.SET_LOCATION \ --ed lat --ed lng [--ed alt ] README updated with the full command, parameter notes and caveats. --- README.md | 32 +++++++++++++ .../java/com/zcshou/service/ServiceGo.java | 48 +++++++++++++++++++ 2 files changed, 80 insertions(+) diff --git a/README.md b/README.md index e054bb9a..edeec097 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,7 @@ 3. 历史记录 4. 位置搜索 5. 直接输入坐标 +6. 通过 adb 远程设置坐标(无需操作 UI,适合脚本与自动化场景,命令示例见下文「通过 adb 设置坐标」一节) ## 截图 ![joystick.jpg](./docs/images/joystick.jpg) @@ -63,6 +64,37 @@ 2. 启动影梭,赋予相关权限 3. 单击地图位置,然后点击启动按钮 +## 通过 adb 设置坐标 +  在按上述步骤启动定位服务(点击启动按钮、通知栏出现影梭常驻通知)之后,可以通过 adb 直接注入经纬度,方便脚本化、自动化等场景使用。GPS 与 NETWORK 两个 provider 会在 100ms 内同步刷新,摇杆的当前位也会一并更新。 + +命令格式: + +```bash +adb shell am broadcast -p com.zcshou.gogogo \ + -a com.zcshou.gogogo.action.SET_LOCATION \ + --ed lat <纬度> --ed lng <经度> [--ed alt <海拔>] +``` + +参数说明: + +- `lat` / `lng`:必填,WGS84 经纬度,类型为 `double`,因此 adb 端必须使用 `--ed`(extra double),写成 `--ef` 或 `--ei` 会被忽略 +- `alt`:可选,海拔(米),缺省时沿用当前值 +- `-p com.zcshou.gogogo`:显式指定包名,避免在 Android 13+ 上被隐式广播限制拦截 + +示例(注入上海外滩坐标): + +```bash +adb shell am broadcast -p com.zcshou.gogogo \ + -a com.zcshou.gogogo.action.SET_LOCATION \ + --ed lat 31.2304 --ed lng 121.4737 --ed alt 10 +``` + +注意: + +- 服务必须先通过 APP UI 启动一次,receiver 才会注册;服务被销毁后该通道随之失效 +- 必须在系统设置 → 开发者选项中将"选择模拟位置应用"设为本 APP,否则系统不会接受 mock 位置 +- 经纬度的合法范围会做基础校验(`lat ∈ [-90, 90]`,`lng ∈ [-180, 180]`),越界将被忽略并在日志中提示 + ## 文档   由于本人并不是做移动开发的,很多功能代码写的都比较差。我也第一次写 Android APP,目前还处在学习中。。。此外,就一个简单的 APP,应该也不需要啥文档,开发过程中遇到的一些问题,我一般都会记录在个人博客中,具体参见:https://blog.csdn.net/zcshoucsdn/category_10559121.html diff --git a/app/src/main/java/com/zcshou/service/ServiceGo.java b/app/src/main/java/com/zcshou/service/ServiceGo.java index 6218cac7..c632c674 100644 --- a/app/src/main/java/com/zcshou/service/ServiceGo.java +++ b/app/src/main/java/com/zcshou/service/ServiceGo.java @@ -58,6 +58,14 @@ public class ServiceGo extends Service { private NoteActionReceiver mActReceiver; // 摇杆相关 private JoyStick mJoyStick; + // adb 远程设位通道:通过 am broadcast 注入坐标 + // 用法: adb shell am broadcast -a com.zcshou.gogogo.action.SET_LOCATION \ + // --ed lat 31.2304 --ed lng 121.4737 [--ed alt 10] + public static final String ACTION_SET_LOCATION = "com.zcshou.gogogo.action.SET_LOCATION"; + public static final String EXTRA_LAT = "lat"; + public static final String EXTRA_LNG = "lng"; + public static final String EXTRA_ALT = "alt"; + private AdbLocationReceiver mAdbReceiver; private final ServiceGoBinder mBinder = new ServiceGoBinder(); @@ -83,6 +91,8 @@ public void onCreate() { initNotification(); initJoyStick(); + + initAdbReceiver(); } @Override @@ -108,6 +118,13 @@ public void onDestroy() { removeTestProviderGPS(); unregisterReceiver(mActReceiver); + if (mAdbReceiver != null) { + try { + unregisterReceiver(mAdbReceiver); + } catch (IllegalArgumentException e) { + XLog.e("SERVICEGO: ERROR - unregister mAdbReceiver"); + } + } stopForeground(STOP_FOREGROUND_REMOVE); super.onDestroy(); @@ -307,6 +324,37 @@ private void setLocationNetwork() { } } + private void initAdbReceiver() { + mAdbReceiver = new AdbLocationReceiver(); + IntentFilter filter = new IntentFilter(ACTION_SET_LOCATION); + // target=32, 暂不需要 RECEIVER_EXPORTED 显式 flag;后续升 33+ 再加 + registerReceiver(mAdbReceiver, filter); + } + + public class AdbLocationReceiver extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + if (intent == null || !ACTION_SET_LOCATION.equals(intent.getAction())) { + return; + } + // lat/lng 必填;alt 可缺省,沿用当前值 + if (!intent.hasExtra(EXTRA_LAT) || !intent.hasExtra(EXTRA_LNG)) { + XLog.e("SERVICEGO: ADB - missing lat or lng extra"); + return; + } + double lat = intent.getDoubleExtra(EXTRA_LAT, mCurLat); + double lng = intent.getDoubleExtra(EXTRA_LNG, mCurLng); + double alt = intent.getDoubleExtra(EXTRA_ALT, mCurAlt); + if (lat < -90.0 || lat > 90.0 || lng < -180.0 || lng > 180.0) { + XLog.e("SERVICEGO: ADB - invalid lat/lng " + lat + "," + lng); + return; + } + XLog.d("SERVICEGO: ADB - setPosition lng=" + lng + " lat=" + lat + " alt=" + alt); + // 复用 UI 路径:会同步推送给 GPS/NETWORK provider 并刷新摇杆当前位 + mBinder.setPosition(lng, lat, alt); + } + } + public class NoteActionReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) {