Flutter集成华为Push绑定60s自动解绑后无法持续接收推送问题
问题根因
日志里提示的The serviceConnection has been bind for 60s, need to unbind是HMS SDK的默认设计,不属于异常。com.huawei.hms.adapter.BinderAdapter是客户端和HMS核心服务通信的临时绑定通道,SDK默认在单次接口请求(比如初始化时调用的getToken)完成60秒后自动解绑该通道,目的是减少不必要的内存占用。
出现解绑后无法接收通知的问题,本质是接入逻辑存在三个问题:
- 把Push初始化、消息流监听的逻辑写在了单个登录页的
initState生命周期里,页面销毁、应用切后台后监听流会被中断,临时Binder解绑后没有触发重连 - 没有开启HMS Push的自动初始化、长连接保活开关
- 没有配置Android端必要的保活权限,且大概率在x86模拟器上测试,模拟器环境对HMS后台服务的保活支持存在天然缺陷
解决方案
1. 调整初始化位置
禁止将Push初始化逻辑绑定在单个页面的生命周期中,需要将初始化逻辑移到应用全局入口,确保应用启动后全局生效,不会随页面销毁中断:
void main() async { WidgetsFlutterBinding.ensureInitialized(); await initHmsPushGlobal(); runApp(const MyApp()); }
将原来写在UserSigninPageState里的Push初始化逻辑抽成全局方法,不要和页面State绑定。
2. 补充保活与自动重连逻辑
在全局初始化方法中补充以下配置,确保连接断开后能自动恢复:
// 全局消息回调不要放在类内部,要定义为顶层函数 void backgroundMessageCallback(RemoteMessage remoteMessage) async { String? data = remoteMessage.data; if (data != null) { Push.localNotification( <String, String>{ HMSLocalNotificationAttr.TITLE: '[Headless] DataMessage Received', HMSLocalNotificationAttr.MESSAGE: data, }, ); } } Future<void> initHmsPushGlobal() async { // 开启自动初始化 await Push.setAutoInitEnabled(true); // 启动推送服务常驻 await Push.turnOnPush(); // 原有事件监听逻辑 Push.getTokenStream.listen((token) { log("huawei push token: $token"); }, onError: (e) { PlatformException err = e as PlatformException; log("get token error: ${err.message}"); }); Push.onNotificationOpenedApp.listen((initialNotification) { if (initialNotification != null) { log("open notification from quit state: ${initialNotification.toString()}"); } }); dynamic initialNotification = await Push.getInitialNotification(); Push.onMessageReceivedStream.listen((remoteMessage) { String? data = remoteMessage.data; if (data != null) { Push.localNotification( <String, String>{ HMSLocalNotificationAttr.TITLE: 'DataMessage Received', HMSLocalNotificationAttr.MESSAGE: data, }, ); log("receive foreground message: $data"); } }, onError: (e) { PlatformException err = e as PlatformException; log("receive message error: ${err.message}"); }); // 注册后台消息处理器 await Push.registerBackgroundMessageHandler(backgroundMessageCallback); // 监听推送连接状态,断开后自动重连 Push.getMsgReceiveStateStream.listen((state) { // state=0代表推送连接断开 if (state == 0) { Future.delayed(const Duration(seconds: 1), () { // 重新调用getToken会触发SDK自动重建Binder连接 Push.getToken(''); }); } }); // 首次拉取token建立连接 Push.getToken(''); }
3. 补充Android端配置
在android/app/src/main/AndroidManifest.xml中补充必要权限,避免系统杀死推送进程:
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="com.huawei.hms.permission.PUSH_PROVIDER" />
在华为/荣耀真机上测试时,手动给应用开启「自启动」「后台活动无限制」权限,避免系统省电策略拦截推送进程。
4. 避坑说明
- 不要手动修改、反射调用
BinderAdapter的绑定/解绑逻辑,这个组件是HMS SDK内部自动管理的:每次调用Push相关接口时SDK会自动绑定,请求完成后自动解绑,这个临时通道和推送长连接无关——真正维持推送接收的是HMS核心服务的独立进程,不会因为这个临时Binder解绑就断连。 - 不要在x86安卓模拟器上验证推送功能,模拟器上的HMS核心服务是裁剪版本,存在大量兼容性问题,长连接断开、消息丢失是常见现象,必须用华为真机测试。
- 提前确认AppGallery Connect后台已经正确配置应用签名、包名,开通Push服务,否则即使客户端连接正常也无法收到推送。
验证方法:配置完成后启动应用,等待控制台输出Binder自动解绑日志后,从AGC后台发送测试推送,确认应用在前台、后台、锁屏状态下都能正常收到通知即可。
内容的提问来源于stack exchange,提问作者Theem Phuwakhon
相关产品推荐
相关产品推荐

