Mercury-IM/app/src/main/java/org/mercury_im/messenger/android/service/MercuryForegroundService.java

210 lines
7.3 KiB
Java
Raw Normal View History

2020-06-06 18:45:20 +02:00
package org.mercury_im.messenger.android.service;
2019-05-27 21:34:11 +02:00
import android.app.Notification;
import android.app.NotificationManager;
2019-05-27 21:34:11 +02:00
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
2019-06-10 02:52:08 +02:00
import androidx.annotation.NonNull;
2019-05-27 21:34:11 +02:00
import androidx.core.app.NotificationCompat;
2019-06-10 02:52:08 +02:00
import org.jivesoftware.smackx.ping.android.ServerPingWithAlarmManager;
import org.mercury_im.messenger.R;
2020-06-06 18:45:20 +02:00
import org.mercury_im.messenger.android.MercuryImApplication;
import org.mercury_im.messenger.android.Notifications;
import org.mercury_im.messenger.android.ui.MainActivity;
import org.mercury_im.messenger.core.connection.MercuryConnectionManager;
import org.mercury_im.messenger.core.connection.state.ConnectionPoolState;
import org.mercury_im.messenger.core.connection.state.ConnectionState;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.inject.Inject;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.disposables.Disposable;
2019-05-27 21:34:11 +02:00
/**
* Started, Bound Service, which is responsible keeping the application alive when the app is not open.
2019-05-27 21:34:11 +02:00
*/
public class MercuryForegroundService extends Service {
2019-05-27 21:34:11 +02:00
2019-06-20 17:20:23 +02:00
private static final String APP = "org.mercury-im.messenger";
private static final String SERVICE = APP + ".MercuryForegroundService";
2019-05-27 21:34:11 +02:00
private static final String ACTION = SERVICE + ".ACTION";
2019-06-06 23:32:41 +02:00
// ACTIONS
2019-05-27 21:34:11 +02:00
public static final String ACTION_START = ACTION + ".START";
public static final String ACTION_STOP = ACTION + ".STOP";
private static final Logger LOGGER = Logger.getLogger(MercuryForegroundService.class.getName());
@Inject
MercuryConnectionManager connectionManager;
CompositeDisposable disposable;
2019-05-27 21:34:11 +02:00
2019-06-10 02:52:08 +02:00
@NonNull
2019-05-27 21:34:11 +02:00
@Override
public final IBinder onBind(Intent intent) {
2019-06-10 02:52:08 +02:00
return new Binder(this);
2019-05-27 21:34:11 +02:00
}
@Override
public void onCreate() {
super.onCreate();
MercuryImApplication.getApplication().getAppComponent().inject(this);
2019-12-09 13:50:26 +01:00
beginLifecycleOfPingManager();
disposable = new CompositeDisposable();
disposable.add(connectionManager.observeConnectionPool()
.subscribe(state -> {
Notification notification = buildForegroundNotification(getApplicationContext(), state);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(Notifications.FOREGROUND_SERVICE_ID, notification);
}));
LOGGER.log(Level.INFO, "onCreate");
2019-12-09 13:50:26 +01:00
}
2019-06-10 02:52:08 +02:00
2019-12-09 13:50:26 +01:00
/**
* PingManager will ensure the XMPP connection is kept alive.
*/
private void beginLifecycleOfPingManager() {
2019-06-10 02:52:08 +02:00
ServerPingWithAlarmManager.onCreate(this);
}
@Override
public void onDestroy() {
super.onDestroy();
disposable.dispose();
2019-12-09 13:50:26 +01:00
endLifecycleOfPingManager();
LOGGER.log(Level.INFO, "onDestroy");
2019-12-09 13:50:26 +01:00
}
private void endLifecycleOfPingManager() {
2019-06-10 02:52:08 +02:00
ServerPingWithAlarmManager.onDestroy();
2019-05-27 21:34:11 +02:00
}
2019-06-20 17:20:23 +02:00
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
2019-05-27 21:34:11 +02:00
if (intent == null) {
startAndDisplayForegroundNotification();
} else {
String action = intent.getAction();
action = action == null ? "" : action;
switch (action) {
case ACTION_START:
startAndDisplayForegroundNotification();
break;
case ACTION_STOP:
stopForeground(true);
2019-06-20 17:20:23 +02:00
stopSelf();
2019-05-27 21:34:11 +02:00
break;
default:
break;
}
}
return START_STICKY_COMPATIBILITY;
}
2019-12-21 03:46:17 +01:00
private void startAndDisplayForegroundNotification() {
Notification notification = buildForegroundNotification(getApplicationContext(),
connectionManager.observeConnectionPool().blockingFirst());
2019-05-27 21:34:11 +02:00
startForeground(Notifications.FOREGROUND_SERVICE_ID, notification);
}
private static Notification buildForegroundNotification(Context context, ConnectionPoolState state) {
2019-05-27 21:34:11 +02:00
Intent startMainActivityIntent = new Intent(context, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,
startMainActivityIntent, 0);
String notificationText = notificationTextFrom(state);
2019-05-27 21:34:11 +02:00
return new NotificationCompat.Builder(context, Notifications.NOTIFICATION_CHANNEL__FOREGROUND_SERVICE)
.setSmallIcon(R.drawable.ic_mercury_black_24dp)
.setContentTitle("Mercury-IM is running!")
.setContentText(notificationText)
.setStyle(new NotificationCompat.BigTextStyle().bigText(notificationText))
2019-05-27 21:34:11 +02:00
.setContentIntent(pendingIntent)
.build();
}
private static String notificationTextFrom(ConnectionPoolState state) {
List<UUID> connecting = new ArrayList<>();
List<UUID> authenticated = new ArrayList<>();
List<UUID> erred = new ArrayList<>();
for (UUID id : state.getConnectionStates().keySet()) {
ConnectionState connectionState = state.getConnectionStates().get(id);
switch (connectionState.getConnectivity()) {
case disconnected:
break;
case connecting:
case connected:
connecting.add(id);
break;
case authenticated:
authenticated.add(id);
break;
case disconnectedOnError:
erred.add(id);
break;
}
}
StringBuilder sb = new StringBuilder();
if (!authenticated.isEmpty()) {
sb.append(authenticated.size())
.append(authenticated.size() == 1 ? " account" : " accounts")
.append(" connected.");
}
if (!connecting.isEmpty()) {
if (!sb.toString().isEmpty()) {
sb.append("\n");
}
sb.append(connecting.size())
.append(authenticated.size() == 1 ? " account" : " accounts")
.append(" connecting.");
}
if (!erred.isEmpty()) {
if (!sb.toString().isEmpty()) {
sb.append("\n");
}
Iterator<UUID> iterator = erred.iterator();
while (iterator.hasNext()) {
UUID id = iterator.next();
sb.append(getAddress(state, id));
if (iterator.hasNext()) sb.append(", ");
}
sb.append(erred.size() == 1 ? " has an error." : " have errors.");
}
return sb.toString();
}
private static String getAddress(ConnectionPoolState state, UUID uuid) {
return state.getConnectionStates().get(uuid).getConnection().getAccount().getAddress();
}
2019-06-10 02:52:08 +02:00
public class Binder extends android.os.Binder {
private final MercuryForegroundService service;
2019-06-10 02:52:08 +02:00
public Binder(MercuryForegroundService service) {
2019-06-10 02:52:08 +02:00
this.service = service;
}
public MercuryForegroundService getService() {
2019-06-10 02:52:08 +02:00
return service;
}
}
2019-05-27 21:34:11 +02:00
}