You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jetpack Compose中使用Tinder/Scarlet WebSocket切后台断开问题求解

后台保持WebSocket连接的调整方案
  • 修改Scarlet生命周期绑定

    你当前使用的AndroidLifecycle.ofApplicationForeground(application)逻辑为应用退后台时自动触发STOP事件,Scarlet会主动断开连接,这是断连的直接原因。替换为自定义的常驻生命周期即可:
    // 自定义全局常驻生命周期
    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
    }
    
    然后修改Scarlet配置中的lifecycle参数:
    val scarletConfiguration = Scarlet.Configuration(
        // 其余原有配置保持不变
        lifecycle = PermanentLifecycle
    )
    
  • 搭配前台服务实现进程保活

    Android系统对后台应用有运行限制,仅修改Scarlet配置仍会被系统切断网络或回收进程,需要启动前台服务持有连接:
    1. 补充权限:Android 12+需要新增前台服务类型权限,Android 13+需要申请通知权限:
    <!-- AndroidManifest.xml 补充权限 -->
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
    <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
    
    1. 实现前台服务代码:
    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
    }
    
    1. 注册服务:
    <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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 22:45:04