I'm trying to start android foreground service for real-time connection with my server using Socket-IO android native client and it works when i run the application with debug mode but when i run it with with release mode only connect event executes and other events won't work
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())
}
}
So i expect to get a loginlistener event everytime i ping the server
and i start the service like this
serviceIntent = Intent(requireContext(), MyService::class.java)
ContextCompat.startForegroundService(requireContext(),serviceIntent)
I defined my model class in the proguard file.
-keep class com.example.model.** { *; }
If you are using SSL, this may be the reason. It's work fine like that :
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;
}
}