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

开启ProGuard后Android Socket-IO仅连接事件生效,其他事件失效求助

Socket-IO Android前台服务发布模式仅Connect事件生效问题

我使用Socket-IO Android原生客户端实现前台服务,与服务器建立实时连接。调试模式下一切正常,但发布模式中仅Connect事件可执行,其他事件完全无法触发。

我的预期是:每次向服务器发送Ping时,能触发loginListener对应的SOCKET_EVENT_ONLINE事件。

Service.kt 代码

class MyService() : Service() {


    private val notifBuilder = NotificationCompat.Builder(this, ongoingChannelId)
        .setSmallIcon(R.drawable.ic_notification_offline)
        .setPriority(NotificationCompat.PRIORITY_MIN)
        .setOngoing(true)


    override fun onCreate() {
        Log.e(TAG, "onCreate: Service ONCREATE")
        notificationIntent = Intent(this, MainActivity::class.java)
        pendingIntent = PendingIntent.getActivity(
            applicationContext,
            0, notificationIntent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT),
            PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE
        )
        notifBuilder.setContentIntent(pendingIntent)
            .setOnlyAlertOnce(true)
            .setContentTitle(getString(R.string.app_name))

        super.onCreate()
    }


    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        Log.e(TAG, "onStartCommand: ")
        createNotificationChannel()
        startForeground(onGoingNotificationId, notifBuilder.build())
        startSocket()
        return START_STICKY
    }


    private fun startSocket() {
        if (!socketStarted) {
            socketStarted = true
            socket.on(Socket.EVENT_CONNECT) {
                Log.e(TAG, "onStartCommand: ${Socket.EVENT_CONNECT}")
                notifBuilder.setContentText("Connected to Server")
                NotificationManagerCompat.from(this)
                    .notify(onGoingNotificationId, notifBuilder.build())
                socket.emit(
                    SOCKET_EVENT_LOGIN,
                    "my token"
                )
                if (this::pingTimerTask.isInitialized)
                    pingTimerTask.cancel()
                pingTimerTask = object : TimerTask() {
                    override fun run() {
                        Log.e(TAG, "run: Pinging ".plus(socket.connected()))
                        if (socket.connected())
                            socket.emit(
                                SOCKET_EVENT_PING,
                                "my token"
                            )
                    }
                }

                pingTimer = if (!this::pingTimer.isInitialized)
                    Timer(true)
                else {
                    pingTimer.cancel()
                    pingTimer.purge()
                    Timer(true)
                }
                pingTimer.schedule(pingTimerTask, 2000, 10000)

            }
            socket.on(Socket.EVENT_CONNECT_ERROR) {
                Log.e(TAG, "onStartCommand: ${Socket.EVENT_CONNECT_ERROR}")
                notifBuilder.setContentText("Connection error to Server")
                    .setSmallIcon(R.drawable.ic_notification_offline)
                NotificationManagerCompat.from(this)
                    .notify(onGoingNotificationId, notifBuilder.build())
                pingTimer.cancel()
            }
            socket.on(Socket.EVENT_DISCONNECT) {
                Log.e(TAG, "onStartCommand: ${Socket.EVENT_DISCONNECT}")
                notifBuilder.setContentText("Disconnected from Server")
                notifBuilder.setOngoing(false)
                    .setSmallIcon(R.drawable.ic_notification_offline)
                NotificationManagerCompat.from(this)
                    .notify(onGoingNotificationId, notifBuilder.build())
                pingTimer.cancel()
            }
            socket.on(SOCKET_EVENT_ONLINE, loginListener)
            socket.connect()
        }
    }

    @SuppressLint("MissingPermission")
    private val loginListener = Emitter.Listener { res ->
        Log.e(TAG, "loginListener: Pinged")
        val date = System.currentTimeMillis()
        val dateFormat = SimpleDateFormat("HH:mm:ss", Locale.getDefault())
        val dateStr: String = dateFormat.format(date)
        notifBuilder.setContentText("Last Ping was $dateStr")
            .setSmallIcon(R.drawable.ic_notification_online)
        NotificationManagerCompat.from(this).notify(onGoingNotificationId, notifBuilder.build())

    }

}

启动服务代码

serviceIntent = Intent(requireContext(), MyService::class.java)
ContextCompat.startForegroundService(requireContext(),serviceIntent)

解决方案

1. 修复混淆规则

发布模式默认开启代码混淆,Socket-IO的事件监听、回调及自定义事件常量可能被混淆破坏。在proguard-rules.pro中添加以下规则:

# 保留Socket-IO相关类不被混淆
-keep class io.socket.** { *; }
-keep class com.github.nkzawa.socketio.** { *; }
-keep class io.emitter.** { *; }

# 保留自定义事件常量(替换成你的实际包名)
-keepclassmembers class com.yourpackage.MyService {
    public static final java.lang.String SOCKET_EVENT_LOGIN;
    public static final java.lang.String SOCKET_EVENT_PING;
    public static final java.lang.String SOCKET_EVENT_ONLINE;
}

# 保留匿名内部类和私有方法,避免TimerTask等被移除
-keepattributes InnerClasses
-keepclassmembers class * {
    private <methods>;
}

2. 确保事件名称完全匹配

检查客户端与服务器的事件名称是否完全一致(大小写、拼写)。发布模式下如果事件常量被混淆,会导致收发事件不匹配,可临时改用字符串字面量排查问题。

3. 切换到主线程更新通知

Socket-IO回调默认在后台线程执行,部分设备发布模式下对后台线程更新通知有严格限制,将通知更新代码切换到主线程:

@SuppressLint("MissingPermission")
private val loginListener = Emitter.Listener { res ->
    Log.e(TAG, "loginListener: Pinged")
    runOnUiThread {
        val date = System.currentTimeMillis()
        val dateFormat = SimpleDateFormat("HH:mm:ss", Locale.getDefault())
        val dateStr: String = dateFormat.format(date)
        notifBuilder.setContentText("Last Ping was $dateStr")
            .setSmallIcon(R.drawable.ic_notification_online)
        NotificationManagerCompat.from(this).notify(onGoingNotificationId, notifBuilder.build())
    }
}

4. 验证Socket初始化配置

检查发布模式下Socket实例的初始化参数(如服务器URL、transports设置)是否与调试模式一致,部分网络配置差异会导致连接后无法正常收发事件。


内容的提问来源于stack exchange,提问作者Ebrahim Karimi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 16:15:07