show notification during ongoing call
This commit is contained in:
parent
2e8b91665b
commit
d19b5e0634
|
@ -76,6 +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;
|
||||||
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<>();
|
||||||
|
@ -166,6 +167,13 @@ public class NotificationService {
|
||||||
incomingCallsChannel.setGroup("calls");
|
incomingCallsChannel.setGroup("calls");
|
||||||
notificationManager.createNotificationChannel(incomingCallsChannel);
|
notificationManager.createNotificationChannel(incomingCallsChannel);
|
||||||
|
|
||||||
|
final NotificationChannel ongoingCallsChannel = new NotificationChannel("ongoing_calls",
|
||||||
|
c.getString(R.string.ongoing_calls_channel_name),
|
||||||
|
NotificationManager.IMPORTANCE_LOW);
|
||||||
|
ongoingCallsChannel.setShowBadge(false);
|
||||||
|
ongoingCallsChannel.setGroup("calls");
|
||||||
|
notificationManager.createNotificationChannel(ongoingCallsChannel);
|
||||||
|
|
||||||
|
|
||||||
final NotificationChannel messagesChannel = new NotificationChannel("messages",
|
final NotificationChannel messagesChannel = new NotificationChannel("messages",
|
||||||
c.getString(R.string.messages_channel_name),
|
c.getString(R.string.messages_channel_name),
|
||||||
|
@ -333,7 +341,6 @@ public class NotificationService {
|
||||||
fullScreenIntent.putExtra(RtpSessionActivity.EXTRA_SESSION_ID, id.sessionId);
|
fullScreenIntent.putExtra(RtpSessionActivity.EXTRA_SESSION_ID, id.sessionId);
|
||||||
fullScreenIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
fullScreenIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
fullScreenIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
fullScreenIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||||
final PendingIntent pendingIntent = PendingIntent.getActivity(mXmppConnectionService, 101, fullScreenIntent, PendingIntent.FLAG_UPDATE_CURRENT);
|
|
||||||
final NotificationCompat.Builder builder = new NotificationCompat.Builder(mXmppConnectionService, "incoming_calls");
|
final NotificationCompat.Builder builder = new NotificationCompat.Builder(mXmppConnectionService, "incoming_calls");
|
||||||
builder.setSmallIcon(R.drawable.ic_call_white_24dp);
|
builder.setSmallIcon(R.drawable.ic_call_white_24dp);
|
||||||
builder.setContentTitle(mXmppConnectionService.getString(R.string.rtp_state_incoming_call));
|
builder.setContentTitle(mXmppConnectionService.getString(R.string.rtp_state_incoming_call));
|
||||||
|
@ -346,7 +353,7 @@ public class NotificationService {
|
||||||
builder.addAction(new NotificationCompat.Action.Builder(
|
builder.addAction(new NotificationCompat.Action.Builder(
|
||||||
R.drawable.ic_call_end_white_48dp,
|
R.drawable.ic_call_end_white_48dp,
|
||||||
mXmppConnectionService.getString(R.string.dismiss_call),
|
mXmppConnectionService.getString(R.string.dismiss_call),
|
||||||
createDismissCall(id.sessionId, 102))
|
createCallAction(id.sessionId, XmppConnectionService.ACTION_DISMISS_CALL, 102))
|
||||||
.build());
|
.build());
|
||||||
builder.addAction(new NotificationCompat.Action.Builder(
|
builder.addAction(new NotificationCompat.Action.Builder(
|
||||||
R.drawable.ic_call_white_24dp,
|
R.drawable.ic_call_white_24dp,
|
||||||
|
@ -358,6 +365,26 @@ public class NotificationService {
|
||||||
notify(INCOMING_CALL_NOTIFICATION_ID, builder.build());
|
notify(INCOMING_CALL_NOTIFICATION_ID, builder.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void showOngoingCallNotification(final AbstractJingleConnection.Id id) {
|
||||||
|
final NotificationCompat.Builder builder = new NotificationCompat.Builder(mXmppConnectionService, "ongoing_calls");
|
||||||
|
builder.setSmallIcon(R.drawable.ic_call_white_24dp);
|
||||||
|
builder.setContentTitle(mXmppConnectionService.getString(R.string.ongoing_call));
|
||||||
|
builder.setContentText(id.account.getRoster().getContact(id.with).getDisplayName());
|
||||||
|
builder.setVisibility(NotificationCompat.VISIBILITY_PUBLIC);
|
||||||
|
builder.setPriority(NotificationCompat.PRIORITY_HIGH);
|
||||||
|
builder.setCategory(NotificationCompat.CATEGORY_CALL);
|
||||||
|
builder.setContentIntent(createPendingRtpSession(id, Intent.ACTION_VIEW, 101));
|
||||||
|
builder.setOngoing(true);
|
||||||
|
builder.addAction(new NotificationCompat.Action.Builder(
|
||||||
|
R.drawable.ic_call_end_white_48dp,
|
||||||
|
mXmppConnectionService.getString(R.string.hang_up),
|
||||||
|
createCallAction(id.sessionId, XmppConnectionService.ACTION_END_CALL, 104))
|
||||||
|
.build());
|
||||||
|
final Notification notification = 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) {
|
||||||
final Intent fullScreenIntent = new Intent(mXmppConnectionService, RtpSessionActivity.class);
|
final Intent fullScreenIntent = new Intent(mXmppConnectionService, RtpSessionActivity.class);
|
||||||
fullScreenIntent.setAction(action);
|
fullScreenIntent.setAction(action);
|
||||||
|
@ -373,6 +400,10 @@ public class NotificationService {
|
||||||
cancel(INCOMING_CALL_NOTIFICATION_ID);
|
cancel(INCOMING_CALL_NOTIFICATION_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void cancelOngoingCallNotification() {
|
||||||
|
cancel(ONGOING_CALL_NOTIFICATION_ID);
|
||||||
|
}
|
||||||
|
|
||||||
private void pushNow(final Message message) {
|
private void pushNow(final Message message) {
|
||||||
mXmppConnectionService.updateUnreadCountBadge();
|
mXmppConnectionService.updateUnreadCountBadge();
|
||||||
if (!notify(message)) {
|
if (!notify(message)) {
|
||||||
|
@ -899,9 +930,9 @@ public class NotificationService {
|
||||||
return PendingIntent.getService(mXmppConnectionService, generateRequestCode(conversation, 16), intent, PendingIntent.FLAG_UPDATE_CURRENT);
|
return PendingIntent.getService(mXmppConnectionService, generateRequestCode(conversation, 16), intent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
private PendingIntent createDismissCall(String sessionId, int requestCode) {
|
private PendingIntent createCallAction(String sessionId, final String action, int requestCode) {
|
||||||
final Intent intent = new Intent(mXmppConnectionService, XmppConnectionService.class);
|
final Intent intent = new Intent(mXmppConnectionService, XmppConnectionService.class);
|
||||||
intent.setAction(XmppConnectionService.ACTION_DISMISS_CALL);
|
intent.setAction(action);
|
||||||
intent.setPackage(mXmppConnectionService.getPackageName());
|
intent.setPackage(mXmppConnectionService.getPackageName());
|
||||||
intent.putExtra(RtpSessionActivity.EXTRA_SESSION_ID, sessionId);
|
intent.putExtra(RtpSessionActivity.EXTRA_SESSION_ID, sessionId);
|
||||||
return PendingIntent.getService(mXmppConnectionService, requestCode, intent, PendingIntent.FLAG_UPDATE_CURRENT);
|
return PendingIntent.getService(mXmppConnectionService, requestCode, intent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||||
|
|
|
@ -167,6 +167,7 @@ public class XmppConnectionService extends Service {
|
||||||
public static final String ACTION_FCM_TOKEN_REFRESH = "fcm_token_refresh";
|
public static final String ACTION_FCM_TOKEN_REFRESH = "fcm_token_refresh";
|
||||||
public static final String ACTION_FCM_MESSAGE_RECEIVED = "fcm_message_received";
|
public static final String ACTION_FCM_MESSAGE_RECEIVED = "fcm_message_received";
|
||||||
public static final String ACTION_DISMISS_CALL = "dismiss_call";
|
public static final String ACTION_DISMISS_CALL = "dismiss_call";
|
||||||
|
public static final String ACTION_END_CALL = "end_call";
|
||||||
private static final String ACTION_POST_CONNECTIVITY_CHANGE = "eu.siacs.conversations.POST_CONNECTIVITY_CHANGE";
|
private static final String ACTION_POST_CONNECTIVITY_CHANGE = "eu.siacs.conversations.POST_CONNECTIVITY_CHANGE";
|
||||||
|
|
||||||
private static final String SETTING_LAST_ACTIVITY_TS = "last_activity_timestamp";
|
private static final String SETTING_LAST_ACTIVITY_TS = "last_activity_timestamp";
|
||||||
|
@ -640,10 +641,17 @@ public class XmppConnectionService extends Service {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case ACTION_DISMISS_CALL:
|
case ACTION_DISMISS_CALL: {
|
||||||
final String sessionId = intent.getStringExtra(RtpSessionActivity.EXTRA_SESSION_ID);
|
final String sessionId = intent.getStringExtra(RtpSessionActivity.EXTRA_SESSION_ID);
|
||||||
Log.d(Config.LOGTAG,"received intent to dismiss call with session id "+sessionId);
|
Log.d(Config.LOGTAG, "received intent to dismiss call with session id " + sessionId);
|
||||||
mJingleConnectionManager.rejectRtpSession(sessionId);
|
mJingleConnectionManager.rejectRtpSession(sessionId);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ACTION_END_CALL: {
|
||||||
|
final String sessionId = intent.getStringExtra(RtpSessionActivity.EXTRA_SESSION_ID);
|
||||||
|
Log.d(Config.LOGTAG, "received intent to end call with session id " + sessionId);
|
||||||
|
mJingleConnectionManager.endRtpSession(sessionId);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case ACTION_DISMISS_ERROR_NOTIFICATIONS:
|
case ACTION_DISMISS_ERROR_NOTIFICATIONS:
|
||||||
dismissErrorNotifications();
|
dismissErrorNotifications();
|
||||||
|
@ -3978,7 +3986,7 @@ public class XmppConnectionService extends Service {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void notifyJingleRtpConnectionUpdate(final Account account, final Jid with, final String sessionId, final RtpEndUserState state) {
|
public void notifyJingleRtpConnectionUpdate(final Account account, final Jid with, final String sessionId, final RtpEndUserState state) {
|
||||||
for(OnJingleRtpConnectionUpdate listener : threadSafeList(this.onJingleRtpConnectionUpdate)) {
|
for (OnJingleRtpConnectionUpdate listener : threadSafeList(this.onJingleRtpConnectionUpdate)) {
|
||||||
listener.onJingleRtpConnectionUpdate(account, with, sessionId, state);
|
listener.onJingleRtpConnectionUpdate(account, with, sessionId, state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -237,6 +237,9 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
|
||||||
finish();
|
finish();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (JingleRtpConnection.STATES_SHOWING_ONGOING_CALL.contains(requireRtpConnection().getState())) {
|
||||||
|
putScreenInCallMode();
|
||||||
|
}
|
||||||
binding.with.setText(getWith().getDisplayName());
|
binding.with.setText(getWith().getDisplayName());
|
||||||
updateStateDisplay(currentState);
|
updateStateDisplay(currentState);
|
||||||
updateButtonConfiguration(currentState);
|
updateButtonConfiguration(currentState);
|
||||||
|
|
|
@ -1,21 +1,19 @@
|
||||||
package eu.siacs.conversations.xmpp.jingle;
|
package eu.siacs.conversations.xmpp.jingle;
|
||||||
|
|
||||||
|
import android.util.Base64;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.google.common.base.Objects;
|
import com.google.common.base.Objects;
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
|
import java.security.SecureRandom;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
import eu.siacs.conversations.Config;
|
import eu.siacs.conversations.Config;
|
||||||
import eu.siacs.conversations.entities.Account;
|
import eu.siacs.conversations.entities.Account;
|
||||||
import eu.siacs.conversations.entities.Contact;
|
|
||||||
import eu.siacs.conversations.entities.Message;
|
import eu.siacs.conversations.entities.Message;
|
||||||
import eu.siacs.conversations.entities.Transferable;
|
import eu.siacs.conversations.entities.Transferable;
|
||||||
import eu.siacs.conversations.services.AbstractConnectionManager;
|
import eu.siacs.conversations.services.AbstractConnectionManager;
|
||||||
|
@ -271,7 +269,9 @@ public class JingleConnectionManager extends AbstractConnectionManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
static String nextRandomId() {
|
static String nextRandomId() {
|
||||||
return UUID.randomUUID().toString();
|
final byte[] id = new byte[16];
|
||||||
|
new SecureRandom().nextBytes(id);
|
||||||
|
return Base64.encodeToString(id, Base64.NO_WRAP | Base64.NO_PADDING);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void deliverIbbPacket(Account account, IqPacket packet) {
|
public void deliverIbbPacket(Account account, IqPacket packet) {
|
||||||
|
@ -354,6 +354,16 @@ public class JingleConnectionManager extends AbstractConnectionManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void endRtpSession(final String sessionId) {
|
||||||
|
for (final AbstractJingleConnection connection : this.connections.values()) {
|
||||||
|
if (connection.getId().sessionId.equals(sessionId)) {
|
||||||
|
if (connection instanceof JingleRtpConnection) {
|
||||||
|
((JingleRtpConnection) connection).endCall();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void failProceed(Account account, final Jid with, String sessionId) {
|
public void failProceed(Account account, final Jid with, String sessionId) {
|
||||||
final AbstractJingleConnection.Id id = AbstractJingleConnection.Id.of(account, with, sessionId);
|
final AbstractJingleConnection.Id id = AbstractJingleConnection.Id.of(account, with, sessionId);
|
||||||
final AbstractJingleConnection existingJingleConnection = connections.get(id);
|
final AbstractJingleConnection existingJingleConnection = connections.get(id);
|
||||||
|
@ -374,7 +384,7 @@ public class JingleConnectionManager extends AbstractConnectionManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static RtpSessionProposal of(Account account, Jid with) {
|
public static RtpSessionProposal of(Account account, Jid with) {
|
||||||
return new RtpSessionProposal(account, with, UUID.randomUUID().toString());
|
return new RtpSessionProposal(account, with, nextRandomId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -74,6 +74,13 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
|
||||||
VALID_TRANSITIONS = transitionBuilder.build();
|
VALID_TRANSITIONS = transitionBuilder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static final List<State> STATES_SHOWING_ONGOING_CALL = Arrays.asList(
|
||||||
|
State.PROCEED,
|
||||||
|
State.SESSION_INITIALIZED,
|
||||||
|
State.SESSION_INITIALIZED_PRE_APPROVED,
|
||||||
|
State.SESSION_ACCEPTED
|
||||||
|
);
|
||||||
|
|
||||||
private final WebRTCWrapper webRTCWrapper = new WebRTCWrapper(this);
|
private final WebRTCWrapper webRTCWrapper = new WebRTCWrapper(this);
|
||||||
private final ArrayDeque<IceCandidate> pendingIceCandidates = new ArrayDeque<>();
|
private final ArrayDeque<IceCandidate> pendingIceCandidates = new ArrayDeque<>();
|
||||||
private State state = State.NULL;
|
private State state = State.NULL;
|
||||||
|
@ -727,6 +734,7 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
|
||||||
this.state = target;
|
this.state = target;
|
||||||
Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": transitioned into " + target);
|
Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": transitioned into " + target);
|
||||||
updateEndUserState();
|
updateEndUserState();
|
||||||
|
updateOngoingCallNotification();
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
|
@ -759,6 +767,14 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
|
||||||
xmppConnectionService.notifyJingleRtpConnectionUpdate(id.account, id.with, id.sessionId, getEndUserState());
|
xmppConnectionService.notifyJingleRtpConnectionUpdate(id.account, id.with, id.sessionId, getEndUserState());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateOngoingCallNotification() {
|
||||||
|
if (STATES_SHOWING_ONGOING_CALL.contains(this.state)) {
|
||||||
|
xmppConnectionService.getNotificationService().showOngoingCallNotification(id);
|
||||||
|
} else {
|
||||||
|
xmppConnectionService.getNotificationService().cancelOngoingCallNotification();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void discoverIceServers(final OnIceServersDiscovered onIceServersDiscovered) {
|
private void discoverIceServers(final OnIceServersDiscovered onIceServersDiscovered) {
|
||||||
if (id.account.getXmppConnection().getFeatures().extendedServiceDiscovery()) {
|
if (id.account.getXmppConnection().getFeatures().extendedServiceDiscovery()) {
|
||||||
final IqPacket request = new IqPacket(IqPacket.TYPE.GET);
|
final IqPacket request = new IqPacket(IqPacket.TYPE.GET);
|
||||||
|
@ -815,6 +831,10 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public State getState() {
|
||||||
|
return this.state;
|
||||||
|
}
|
||||||
|
|
||||||
private interface OnIceServersDiscovered {
|
private interface OnIceServersDiscovered {
|
||||||
void onIceServersDiscovered(List<PeerConnection.IceServer> iceServers);
|
void onIceServersDiscovered(List<PeerConnection.IceServer> iceServers);
|
||||||
}
|
}
|
||||||
|
|
|
@ -751,6 +751,7 @@
|
||||||
<string name="notification_group_calls">Calls</string>
|
<string name="notification_group_calls">Calls</string>
|
||||||
<string name="messages_channel_name">Messages</string>
|
<string name="messages_channel_name">Messages</string>
|
||||||
<string name="incoming_calls_channel_name">Incoming calls</string>
|
<string name="incoming_calls_channel_name">Incoming calls</string>
|
||||||
|
<string name="ongoing_calls_channel_name">Ongoing calls</string>
|
||||||
<string name="silent_messages_channel_name">Silent messages</string>
|
<string name="silent_messages_channel_name">Silent messages</string>
|
||||||
<string name="silent_messages_channel_description">This notification group is used to display notifications that should not trigger any sound. For example when being active on another device (Grace Period).</string>
|
<string name="silent_messages_channel_description">This notification group is used to display notifications that should not trigger any sound. For example when being active on another device (Grace Period).</string>
|
||||||
<string name="pref_more_notification_settings">Notification Settings</string>
|
<string name="pref_more_notification_settings">Notification Settings</string>
|
||||||
|
@ -899,6 +900,8 @@
|
||||||
<string name="rtp_state_declined_or_busy">Busy</string>
|
<string name="rtp_state_declined_or_busy">Busy</string>
|
||||||
<string name="rtp_state_connectivity_error">Unable to connect call</string>
|
<string name="rtp_state_connectivity_error">Unable to connect call</string>
|
||||||
<string name="rtp_state_application_failure">Application failure</string>
|
<string name="rtp_state_application_failure">Application failure</string>
|
||||||
|
<string name="hang_up">Hang up</string>
|
||||||
|
<string name="ongoing_call">Ongoing call</string>
|
||||||
<plurals name="view_users">
|
<plurals name="view_users">
|
||||||
<item quantity="one">View %1$d Participant</item>
|
<item quantity="one">View %1$d Participant</item>
|
||||||
<item quantity="other">View %1$d Participants</item>
|
<item quantity="other">View %1$d Participants</item>
|
||||||
|
|
Loading…
Reference in a new issue