use foreground service for ongoing call notification

This commit is contained in:
Daniel Gultsch 2020-04-11 19:05:07 +02:00
parent c6db651322
commit c9f7e174f7
3 changed files with 38 additions and 14 deletions

View file

@ -76,7 +76,7 @@ public class NotificationService {
private static final int NOTIFICATION_ID = NOTIFICATION_ID_MULTIPLIER * 2; private static final int NOTIFICATION_ID = NOTIFICATION_ID_MULTIPLIER * 2;
private static final int ERROR_NOTIFICATION_ID = NOTIFICATION_ID_MULTIPLIER * 6; private static final int ERROR_NOTIFICATION_ID = NOTIFICATION_ID_MULTIPLIER * 6;
private static final int INCOMING_CALL_NOTIFICATION_ID = NOTIFICATION_ID_MULTIPLIER * 8; private static final int INCOMING_CALL_NOTIFICATION_ID = NOTIFICATION_ID_MULTIPLIER * 8;
private static final int ONGOING_CALL_NOTIFICATION_ID = NOTIFICATION_ID_MULTIPLIER * 10; public static final int ONGOING_CALL_NOTIFICATION_ID = NOTIFICATION_ID_MULTIPLIER * 10;
private final XmppConnectionService mXmppConnectionService; private final XmppConnectionService mXmppConnectionService;
private final LinkedHashMap<String, ArrayList<Message>> notifications = new LinkedHashMap<>(); private final LinkedHashMap<String, ArrayList<Message>> notifications = new LinkedHashMap<>();
private final HashMap<Conversation, AtomicInteger> mBacklogMessageCounter = new HashMap<>(); private final HashMap<Conversation, AtomicInteger> mBacklogMessageCounter = new HashMap<>();
@ -362,10 +362,10 @@ public class NotificationService {
.build()); .build());
final Notification notification = builder.build(); final Notification notification = builder.build();
notification.flags = notification.flags | Notification.FLAG_INSISTENT; notification.flags = notification.flags | Notification.FLAG_INSISTENT;
notify(INCOMING_CALL_NOTIFICATION_ID, builder.build()); notify(INCOMING_CALL_NOTIFICATION_ID, notification);
} }
public void showOngoingCallNotification(final AbstractJingleConnection.Id id) { public Notification getOngoingCallNotification(final AbstractJingleConnection.Id id) {
final NotificationCompat.Builder builder = new NotificationCompat.Builder(mXmppConnectionService, "ongoing_calls"); final NotificationCompat.Builder builder = new NotificationCompat.Builder(mXmppConnectionService, "ongoing_calls");
builder.setSmallIcon(R.drawable.ic_call_white_24dp); builder.setSmallIcon(R.drawable.ic_call_white_24dp);
builder.setContentTitle(mXmppConnectionService.getString(R.string.ongoing_call)); builder.setContentTitle(mXmppConnectionService.getString(R.string.ongoing_call));
@ -380,9 +380,7 @@ public class NotificationService {
mXmppConnectionService.getString(R.string.hang_up), mXmppConnectionService.getString(R.string.hang_up),
createCallAction(id.sessionId, XmppConnectionService.ACTION_END_CALL, 104)) createCallAction(id.sessionId, XmppConnectionService.ACTION_END_CALL, 104))
.build()); .build());
final Notification notification = builder.build(); return builder.build();
notification.flags = notification.flags | Notification.FLAG_INSISTENT;
notify(ONGOING_CALL_NOTIFICATION_ID, builder.build());
} }
private PendingIntent createPendingRtpSession(final AbstractJingleConnection.Id id, final String action, final int requestCode) { private PendingIntent createPendingRtpSession(final AbstractJingleConnection.Id id, final String action, final int requestCode) {
@ -1129,7 +1127,7 @@ public class NotificationService {
} }
} }
private void cancel(int id) { public void cancel(int id) {
final NotificationManagerCompat notificationManager = NotificationManagerCompat.from(mXmppConnectionService); final NotificationManagerCompat notificationManager = NotificationManagerCompat.from(mXmppConnectionService);
try { try {
notificationManager.cancel(id); notificationManager.cancel(id);

View file

@ -71,6 +71,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
import eu.siacs.conversations.Config; import eu.siacs.conversations.Config;
import eu.siacs.conversations.R; import eu.siacs.conversations.R;
@ -142,6 +143,7 @@ import eu.siacs.conversations.xmpp.Patches;
import eu.siacs.conversations.xmpp.XmppConnection; import eu.siacs.conversations.xmpp.XmppConnection;
import eu.siacs.conversations.xmpp.chatstate.ChatState; import eu.siacs.conversations.xmpp.chatstate.ChatState;
import eu.siacs.conversations.xmpp.forms.Data; import eu.siacs.conversations.xmpp.forms.Data;
import eu.siacs.conversations.xmpp.jingle.AbstractJingleConnection;
import eu.siacs.conversations.xmpp.jingle.JingleConnectionManager; import eu.siacs.conversations.xmpp.jingle.JingleConnectionManager;
import eu.siacs.conversations.xmpp.jingle.OnJinglePacketReceived; import eu.siacs.conversations.xmpp.jingle.OnJinglePacketReceived;
import eu.siacs.conversations.xmpp.jingle.RtpEndUserState; import eu.siacs.conversations.xmpp.jingle.RtpEndUserState;
@ -209,6 +211,7 @@ public class XmppConnectionService extends Service {
private AtomicBoolean mInitialAddressbookSyncCompleted = new AtomicBoolean(false); private AtomicBoolean mInitialAddressbookSyncCompleted = new AtomicBoolean(false);
private AtomicBoolean mForceForegroundService = new AtomicBoolean(false); private AtomicBoolean mForceForegroundService = new AtomicBoolean(false);
private AtomicBoolean mForceDuringOnCreate = new AtomicBoolean(false); private AtomicBoolean mForceDuringOnCreate = new AtomicBoolean(false);
private AtomicReference<AbstractJingleConnection.Id> ongoingCall = new AtomicReference<>();
private OnMessagePacketReceived mMessageParser = new MessageParser(this); private OnMessagePacketReceived mMessageParser = new MessageParser(this);
private OnPresencePacketReceived mPresenceParser = new PresenceParser(this); private OnPresencePacketReceived mPresenceParser = new PresenceParser(this);
private IqParser mIqParser = new IqParser(this); private IqParser mIqParser = new IqParser(this);
@ -1227,11 +1230,31 @@ public class XmppConnectionService extends Service {
toggleForegroundService(false); toggleForegroundService(false);
} }
public void setOngoingCall(AbstractJingleConnection.Id id) {
ongoingCall.set(id);
toggleForegroundService(false);
}
public void removeOngoingCall(AbstractJingleConnection.Id id) {
if (ongoingCall.compareAndSet(id, null)) {
toggleForegroundService(false);
}
}
private void toggleForegroundService(boolean force) { private void toggleForegroundService(boolean force) {
final boolean status; final boolean status;
if (force || mForceDuringOnCreate.get() || mForceForegroundService.get() || (Compatibility.keepForegroundService(this) && hasEnabledAccounts())) { final AbstractJingleConnection.Id ongoing = ongoingCall.get();
final Notification notification = this.mNotificationService.createForegroundNotification(); if (force || mForceDuringOnCreate.get() || mForceForegroundService.get() || ongoing != null || (Compatibility.keepForegroundService(this) && hasEnabledAccounts())) {
startForeground(NotificationService.FOREGROUND_NOTIFICATION_ID, notification); final Notification notification;
if (ongoing != null) {
notification = this.mNotificationService.getOngoingCallNotification(ongoing);
startForeground(NotificationService.ONGOING_CALL_NOTIFICATION_ID, notification);
mNotificationService.cancel(NotificationService.FOREGROUND_NOTIFICATION_ID);
} else {
notification = this.mNotificationService.createForegroundNotification();
startForeground(NotificationService.FOREGROUND_NOTIFICATION_ID, notification);
}
if (!mForceForegroundService.get()) { if (!mForceForegroundService.get()) {
mNotificationService.notify(NotificationService.FOREGROUND_NOTIFICATION_ID, notification); mNotificationService.notify(NotificationService.FOREGROUND_NOTIFICATION_ID, notification);
} }
@ -1241,7 +1264,10 @@ public class XmppConnectionService extends Service {
status = false; status = false;
} }
if (!mForceForegroundService.get()) { if (!mForceForegroundService.get()) {
mNotificationService.dismissForcedForegroundNotification(); //if the channel was changed the previous call might fail mNotificationService.cancel(NotificationService.FOREGROUND_NOTIFICATION_ID);
}
if (ongoing == null) {
mNotificationService.cancel(NotificationService.ONGOING_CALL_NOTIFICATION_ID);
} }
Log.d(Config.LOGTAG, "ForegroundService: " + (status ? "on" : "off")); Log.d(Config.LOGTAG, "ForegroundService: " + (status ? "on" : "off"));
} }
@ -1253,7 +1279,7 @@ public class XmppConnectionService extends Service {
@Override @Override
public void onTaskRemoved(final Intent rootIntent) { public void onTaskRemoved(final Intent rootIntent) {
super.onTaskRemoved(rootIntent); super.onTaskRemoved(rootIntent);
if ((Compatibility.keepForegroundService(this) && hasEnabledAccounts()) || mForceForegroundService.get()) { if ((Compatibility.keepForegroundService(this) && hasEnabledAccounts()) || mForceForegroundService.get() || ongoingCall.get() != null) {
Log.d(Config.LOGTAG, "ignoring onTaskRemoved because foreground service is activated"); Log.d(Config.LOGTAG, "ignoring onTaskRemoved because foreground service is activated");
} else { } else {
this.logoutAndSave(false); this.logoutAndSave(false);

View file

@ -772,9 +772,9 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
private void updateOngoingCallNotification() { private void updateOngoingCallNotification() {
if (STATES_SHOWING_ONGOING_CALL.contains(this.state)) { if (STATES_SHOWING_ONGOING_CALL.contains(this.state)) {
xmppConnectionService.getNotificationService().showOngoingCallNotification(id); xmppConnectionService.setOngoingCall(id);
} else { } else {
xmppConnectionService.getNotificationService().cancelOngoingCallNotification(); xmppConnectionService.removeOngoingCall(id);
} }
} }