Flutter外卖配送APP因后台定位权限遭Google Play拒审,求解决方案
我正在开发一款基于Flutter的订单配送实时追踪功能,支持订单当前位置追踪。在司机端的AndroidManifest.xml中开启ACCESS_BACKGROUND_LOCATION权限后,APP被Google Play拒审。
拒审通知
经近期审核,我们发现您的应用AppName不符合一项或多项开发者计划政策。以下是应用状态及修正方式的详细信息。
发布状态
应用状态:已拒审
您的应用因下述政策问题被拒审且未发布。若您提交的是更新版本,应用的旧版本仍可在Google Play上获取。问题:功能不符合后台定位访问要求
根据审核结果,您声明的功能似乎不符合我们的位置权限政策要求。声明需后台定位访问的功能时,需注意:仅选择能为用户带来明确价值、对应用核心功能或主要用途至关重要的功能。若无此核心功能,应用将‘无法正常运行’或失去使用价值。需考虑用户是否预期应用在后台访问其位置,以及是否无需后台定位即可提供相同体验。
我的Manifest.xml权限部分
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
后台定位逻辑实现代码
Future<void> _listenLocation() async { model.location.enableBackgroundMode(enable: true); locationStream = model.location.onLocationChanged.listen((event) async { logger.w("Is it Working....."); await FirebaseFirestore.instance .collection('location') .doc(widget.orderId.toString()) .set({ 'latitude': event.latitude, 'longitude': event.longitude, 'dishOrderId': widget.orderId.toString() }, SetOptions(merge: true)); }); }
Play控制台填写的定位权限用途
应用用途:BitesVilla应用用于食品的下单、追踪及配送,司机、商家和用户功能整合在同一应用内。应用的主要用途是在配送过程中实时追踪订单,用户可追踪订单/司机的实时位置。
定位访问:应用使用后台定位来实时追踪订单配送。需要后台定位权限,以便用户在应用关闭或后台运行时仍能准确追踪订单/司机的位置。
合规解决方法
1. 精简权限,改用前台服务定位
Google Play政策中,后台静默定位(ACCESS_BACKGROUND_LOCATION)仅允许用于无法通过前台服务实现的核心场景,而配送场景完全可以通过前台服务+前台定位权限满足需求:
- 移除
ACCESS_BACKGROUND_LOCATION权限,同时将ACCESS_COARSE_LOCATION替换为ACCESS_FINE_LOCATION(配送追踪需要更精确的位置); - 保留
FOREGROUND_SERVICE和FOREGROUND_SERVICE_LOCATION权限,用于在前台服务中持续获取位置。
修改后的Manifest权限:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" />
2. 优化定位逻辑,绑定前台服务
- 强制启动前台服务:在调用
_listenLocation()前,必须启动一个前台服务并显示持续通知(例如“正在配送订单 #XXX”),明确告知用户APP正在使用位置。示例逻辑:// 启动前台服务通知(需依赖flutter_local_notifications等插件) Future<void> _startForegroundService() async { const AndroidNotificationDetails androidDetails = AndroidNotificationDetails( 'delivery_location_channel', '配送位置追踪', channelDescription: '配送过程中实时更新位置', importance: Importance.high, ongoing: true, // 标记为持续通知,无法手动关闭 ); const NotificationDetails details = NotificationDetails(android: androidDetails); await flutterLocalNotificationsPlugin.show( 1, '正在配送', '订单 #${widget.orderId} 配送中', details, payload: 'delivery', ); // 启动前台服务(根据Flutter插件要求实现) await foregroundService.start(); } - 按需启停定位:仅在司机接单后启动位置监听,订单完成后立即取消监听并停止前台服务,避免不必要的位置访问:
// 订单完成时停止定位 Future<void> _stopLocationListen() async { await locationStream?.cancel(); await model.location.enableBackgroundMode(enable: false); await flutterLocalNotificationsPlugin.cancel(1); await foregroundService.stop(); }
3. 重新撰写Play控制台权限用途声明
明确区分角色、场景和权限必要性,避免提及“后台定位”,强调前台服务的核心价值:
应用用途:BitesVilla整合食品下单、商家管理、订单配送与用户追踪功能,核心服务为餐饮配送服务。
定位访问:仅司机角色在配送订单期间,通过前台服务获取精准位置,用于向用户实时更新配送进度。该功能是配送流程的核心环节——无此功能,用户无法追踪订单状态,司机无法完成配送任务。位置访问仅在配送进行时激活,订单完成后立即停止,且全程通过前台通知告知用户。
4. 验证合规性
- 测试司机端流程:接单后自动启动前台通知+定位,切换到后台时通知持续存在、位置正常更新,订单完成后通知消失、定位停止;
- 权限申请:仅在司机首次接单时请求位置权限,弹窗明确说明用途(“需要获取您的位置以向用户实时更新配送进度”)。
内容的提问来源于stack exchange,提问作者Arnab Ghosh

