开启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
相关产品推荐
相关产品推荐

