Jetpack Compose中使用Tinder/Scarlet WebSocket切后台断开问题求解
后台保持WebSocket连接的调整方案
修改Scarlet生命周期绑定
你当前使用的AndroidLifecycle.ofApplicationForeground(application)逻辑为应用退后台时自动触发STOP事件,Scarlet会主动断开连接,这是断连的直接原因。替换为自定义的常驻生命周期即可:
然后修改Scarlet配置中的lifecycle参数:// 自定义全局常驻生命周期 object PermanentLifecycle : Lifecycle { private val registry = LifecycleRegistry(this).apply { currentState = Lifecycle.State.STARTED } override fun addObserver(observer: LifecycleObserver) = registry.addObserver(observer) override fun removeObserver(observer: LifecycleObserver) = registry.removeObserver(observer) override fun getCurrentState(): Lifecycle.State = registry.currentState }val scarletConfiguration = Scarlet.Configuration( // 其余原有配置保持不变 lifecycle = PermanentLifecycle )搭配前台服务实现进程保活
Android系统对后台应用有运行限制,仅修改Scarlet配置仍会被系统切断网络或回收进程,需要启动前台服务持有连接:- 补充权限:Android 12+需要新增前台服务类型权限,Android 13+需要申请通知权限:
<!-- AndroidManifest.xml 补充权限 --> <uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" /> <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />- 实现前台服务代码:
class WebSocketKeepAliveService : Service() { @Inject lateinit var messagingService: ScarletMessagingService private val serviceScope = CoroutineScope(Dispatchers.IO + SupervisorJob()) private val NOTIFICATION_ID = 10086 private val CHANNEL_ID = "websocket_keep_alive" override fun onCreate() { super.onCreate() (application as MyApplication).appComponent.inject(this) // 创建通知渠道 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val channel = NotificationChannel( CHANNEL_ID, "消息连接", NotificationManager.IMPORTANCE_LOW ).apply { setShowBadge(false) } getSystemService(NotificationManager::class.java).createNotificationChannel(channel) } // 启动前台 val notification = NotificationCompat.Builder(this, CHANNEL_ID) .setContentTitle("后台消息接收中") .setContentText("应用正在后台保持连接") .setSmallIcon(R.drawable.ic_app_icon) .build() startForeground(NOTIFICATION_ID, notification) } override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { // 服务内启动消息监听,不要放在ViewModel中 messagingService.observeMessage() .onEach { Timber.d("收到服务端消息: $it") // 处理消息,可通过广播、EventBus或者SharedFlow传递给UI层 } .launchIn(serviceScope) return START_STICKY } override fun onDestroy() { super.onDestroy() serviceScope.cancel() } override fun onBind(intent: Intent?): IBinder? = null }- 注册服务:
<service android:name=".WebSocketKeepAliveService" android:exported="false" android:foregroundServiceType="dataSync" />调整OkHttpClient心跳配置
避免服务器或运营商链路长时间无数据主动断开连接,给OkHttpClient添加心跳间隔:val okHttpClient = OkHttpClient.Builder() .pingInterval(30, TimeUnit.SECONDS) // 每30秒发送一次心跳包 // 其余原有配置保持不变 .build()调整原有逻辑
移除ViewModel中的消息监听启动逻辑,改为在应用启动后主动启动WebSocketKeepAliveService,ViewModel只需要监听服务传递过来的消息做UI更新即可,避免ViewModel销毁导致监听被取消。
内容的提问来源于stack exchange,提问作者ArtixModernal
相关产品推荐
相关产品推荐

