我正在尝试启动 android 前台服务,以便使用 Socket-IO android 本机客户端与我的服务器进行实时连接,并且 当我使用调试模式运行应用程序时它可以工作但是当我使用 释放模式运行它时仅连接事件执行,其他事件不起作用
服务.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())
}
}
所以我希望每次 ping 服务器时都能得到一个登录侦听器事件
我像这样启动服务
serviceIntent = Intent(requireContext(), MyService::class.java)
ContextCompat.startForegroundService(requireContext(),serviceIntent)
因此在发布版本中禁用 proguard 后,它开始工作!
我在 proguard 文件中定义了我的模型类。
-keep class com.example.model.** { *; }
如果您使用 SSL,这可能就是原因。 这样就可以正常工作了:
val socket = IO.socket(socketUrl, SocketOptionsSSL.getOptions())
socketConnect()
private fun socketConnect() {
val obj = JSONObject()
obj.put("type", "client")
obj.put("userId", "XXXX")
socket.emit("roomConnect", obj)
socket.on("tableupdate", onSocketTableStateChange())
socket.connect()
}
private fun onSocketTableStateChange(): Emitter.Listener {
return object : Emitter.Listener {
override fun call(vararg args: Any?) {
try {
val socketData = Gson().fromJson(args[0].toString(), SocketDataClass::class.java)
} catch (e: Exception) {
}
}
}
}
public class SocketOptionsSSL {
public static IO.Options getOptions() {
HostnameVerifier hostnameVerifier = new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
@Override
public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) {
}
@Override
public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) {
}
@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new java.security.cert.X509Certificate[0];
}
}};
X509TrustManager trustManager = (X509TrustManager) trustAllCerts[0];
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.hostnameVerifier(hostnameVerifier)
.build();
try {
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustAllCerts, null);
SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
okHttpClient = null;
okHttpClient = new OkHttpClient.Builder()
.hostnameVerifier(hostnameVerifier)
.sslSocketFactory(sslSocketFactory, trustManager)
.build();
} catch (Exception e) {
Logger.INSTANCE.d("SocketSSL", "Options çekilirken hata oluştu.");
}
IO.Options opts = new IO.Options();
opts.callFactory = okHttpClient;
opts.webSocketFactory = okHttpClient;
return opts;
}
}