mirror of
https://github.com/oxen-io/session-android.git
synced 2025-06-09 05:38:33 +00:00
Support Android Q call notifications.
This commit is contained in:
parent
8a3d0dde91
commit
abcd599ad8
@ -86,6 +86,7 @@
|
|||||||
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
|
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
|
||||||
<uses-permission android:name="android.permission.RAISED_THREAD_PRIORITY" />
|
<uses-permission android:name="android.permission.RAISED_THREAD_PRIORITY" />
|
||||||
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>
|
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>
|
||||||
|
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT"/>
|
||||||
|
|
||||||
<application android:name=".ApplicationContext"
|
<application android:name=".ApplicationContext"
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
|
@ -26,6 +26,7 @@ import android.content.res.Configuration;
|
|||||||
import android.media.AudioManager;
|
import android.media.AudioManager;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
import androidx.appcompat.app.AlertDialog;
|
import androidx.appcompat.app.AlertDialog;
|
||||||
import org.thoughtcrime.securesms.logging.Log;
|
import org.thoughtcrime.securesms.logging.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
@ -46,6 +47,7 @@ import org.thoughtcrime.securesms.service.WebRtcCallService;
|
|||||||
import org.thoughtcrime.securesms.util.ServiceUtil;
|
import org.thoughtcrime.securesms.util.ServiceUtil;
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||||
|
import org.thoughtcrime.securesms.webrtc.CallNotificationBuilder;
|
||||||
import org.whispersystems.libsignal.IdentityKey;
|
import org.whispersystems.libsignal.IdentityKey;
|
||||||
import org.whispersystems.libsignal.SignalProtocolAddress;
|
import org.whispersystems.libsignal.SignalProtocolAddress;
|
||||||
|
|
||||||
@ -77,6 +79,8 @@ public class WebRtcCallActivity extends Activity {
|
|||||||
setVolumeControlStream(AudioManager.STREAM_VOICE_CALL);
|
setVolumeControlStream(AudioManager.STREAM_VOICE_CALL);
|
||||||
|
|
||||||
initializeResources();
|
initializeResources();
|
||||||
|
|
||||||
|
processIntent(getIntent());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -91,13 +95,7 @@ public class WebRtcCallActivity extends Activity {
|
|||||||
@Override
|
@Override
|
||||||
public void onNewIntent(Intent intent){
|
public void onNewIntent(Intent intent){
|
||||||
Log.i(TAG, "onNewIntent");
|
Log.i(TAG, "onNewIntent");
|
||||||
if (ANSWER_ACTION.equals(intent.getAction())) {
|
processIntent(intent);
|
||||||
handleAnswerCall();
|
|
||||||
} else if (DENY_ACTION.equals(intent.getAction())) {
|
|
||||||
handleDenyCall();
|
|
||||||
} else if (END_CALL_ACTION.equals(intent.getAction())) {
|
|
||||||
handleEndCall();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -117,6 +115,16 @@ public class WebRtcCallActivity extends Activity {
|
|||||||
Permissions.onRequestPermissionsResult(this, requestCode, permissions, grantResults);
|
Permissions.onRequestPermissionsResult(this, requestCode, permissions, grantResults);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void processIntent(@NonNull Intent intent) {
|
||||||
|
if (ANSWER_ACTION.equals(intent.getAction())) {
|
||||||
|
handleAnswerCall();
|
||||||
|
} else if (DENY_ACTION.equals(intent.getAction())) {
|
||||||
|
handleDenyCall();
|
||||||
|
} else if (END_CALL_ACTION.equals(intent.getAction())) {
|
||||||
|
handleEndCall();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void initializeScreenshotSecurity() {
|
private void initializeScreenshotSecurity() {
|
||||||
if (TextSecurePreferences.isScreenSecurityEnabled(this)) {
|
if (TextSecurePreferences.isScreenSecurityEnabled(this)) {
|
||||||
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
|
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
|
||||||
|
@ -146,7 +146,7 @@ public class MessageNotifier {
|
|||||||
StatusBarNotification[] activeNotifications = notifications.getActiveNotifications();
|
StatusBarNotification[] activeNotifications = notifications.getActiveNotifications();
|
||||||
|
|
||||||
for (StatusBarNotification activeNotification : activeNotifications) {
|
for (StatusBarNotification activeNotification : activeNotifications) {
|
||||||
if (activeNotification.getId() != CallNotificationBuilder.WEBRTC_NOTIFICATION) {
|
if (!CallNotificationBuilder.isWebRtcNotification(activeNotification.getId())) {
|
||||||
notifications.cancel(activeNotification.getId());
|
notifications.cancel(activeNotification.getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -167,11 +167,11 @@ public class MessageNotifier {
|
|||||||
for (StatusBarNotification notification : activeNotifications) {
|
for (StatusBarNotification notification : activeNotifications) {
|
||||||
boolean validNotification = false;
|
boolean validNotification = false;
|
||||||
|
|
||||||
if (notification.getId() != SUMMARY_NOTIFICATION_ID &&
|
if (notification.getId() != SUMMARY_NOTIFICATION_ID &&
|
||||||
notification.getId() != CallNotificationBuilder.WEBRTC_NOTIFICATION &&
|
notification.getId() != KeyCachingService.SERVICE_RUNNING_ID &&
|
||||||
notification.getId() != KeyCachingService.SERVICE_RUNNING_ID &&
|
notification.getId() != IncomingMessageObserver.FOREGROUND_ID &&
|
||||||
notification.getId() != IncomingMessageObserver.FOREGROUND_ID &&
|
notification.getId() != PENDING_MESSAGES_ID &&
|
||||||
notification.getId() != PENDING_MESSAGES_ID)
|
!CallNotificationBuilder.isWebRtcNotification(notification.getId()))
|
||||||
{
|
{
|
||||||
for (NotificationItem item : notificationState.getNotifications()) {
|
for (NotificationItem item : notificationState.getNotifications()) {
|
||||||
if (notification.getId() == (SUMMARY_NOTIFICATION_ID + item.getThreadId())) {
|
if (notification.getId() == (SUMMARY_NOTIFICATION_ID + item.getThreadId())) {
|
||||||
|
@ -41,15 +41,16 @@ public class NotificationChannels {
|
|||||||
|
|
||||||
private static final String TAG = NotificationChannels.class.getSimpleName();
|
private static final String TAG = NotificationChannels.class.getSimpleName();
|
||||||
|
|
||||||
private static final int VERSION_MESSAGES_CATEGORY = 2;
|
private static final int VERSION_MESSAGES_CATEGORY = 2;
|
||||||
|
private static final int VERSION_CALLS_PRIORITY_BUMP = 3;
|
||||||
|
|
||||||
private static final int VERSION = 2;
|
private static final int VERSION = 3;
|
||||||
|
|
||||||
private static final String CATEGORY_MESSAGES = "messages";
|
private static final String CATEGORY_MESSAGES = "messages";
|
||||||
private static final String CONTACT_PREFIX = "contact_";
|
private static final String CONTACT_PREFIX = "contact_";
|
||||||
private static final String MESSAGES_PREFIX = "messages_";
|
private static final String MESSAGES_PREFIX = "messages_";
|
||||||
|
|
||||||
public static final String CALLS = "calls_v2";
|
public static final String CALLS = "calls_v3";
|
||||||
public static final String FAILURES = "failures";
|
public static final String FAILURES = "failures";
|
||||||
public static final String APP_UPDATES = "app_updates";
|
public static final String APP_UPDATES = "app_updates";
|
||||||
public static final String BACKUPS = "backups_v2";
|
public static final String BACKUPS = "backups_v2";
|
||||||
@ -425,7 +426,7 @@ public class NotificationChannels {
|
|||||||
notificationManager.createNotificationChannelGroup(messagesGroup);
|
notificationManager.createNotificationChannelGroup(messagesGroup);
|
||||||
|
|
||||||
NotificationChannel messages = new NotificationChannel(getMessagesChannel(context), context.getString(R.string.NotificationChannel_messages), NotificationManager.IMPORTANCE_HIGH);
|
NotificationChannel messages = new NotificationChannel(getMessagesChannel(context), context.getString(R.string.NotificationChannel_messages), NotificationManager.IMPORTANCE_HIGH);
|
||||||
NotificationChannel calls = new NotificationChannel(CALLS, context.getString(R.string.NotificationChannel_calls), NotificationManager.IMPORTANCE_LOW);
|
NotificationChannel calls = new NotificationChannel(CALLS, context.getString(R.string.NotificationChannel_calls), NotificationManager.IMPORTANCE_HIGH);
|
||||||
NotificationChannel failures = new NotificationChannel(FAILURES, context.getString(R.string.NotificationChannel_failures), NotificationManager.IMPORTANCE_HIGH);
|
NotificationChannel failures = new NotificationChannel(FAILURES, context.getString(R.string.NotificationChannel_failures), NotificationManager.IMPORTANCE_HIGH);
|
||||||
NotificationChannel backups = new NotificationChannel(BACKUPS, context.getString(R.string.NotificationChannel_backups), NotificationManager.IMPORTANCE_LOW);
|
NotificationChannel backups = new NotificationChannel(BACKUPS, context.getString(R.string.NotificationChannel_backups), NotificationManager.IMPORTANCE_LOW);
|
||||||
NotificationChannel lockedStatus = new NotificationChannel(LOCKED_STATUS, context.getString(R.string.NotificationChannel_locked_status), NotificationManager.IMPORTANCE_LOW);
|
NotificationChannel lockedStatus = new NotificationChannel(LOCKED_STATUS, context.getString(R.string.NotificationChannel_locked_status), NotificationManager.IMPORTANCE_LOW);
|
||||||
@ -462,6 +463,10 @@ public class NotificationChannels {
|
|||||||
notificationManager.deleteNotificationChannel("backups");
|
notificationManager.deleteNotificationChannel("backups");
|
||||||
notificationManager.deleteNotificationChannel("other");
|
notificationManager.deleteNotificationChannel("other");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (oldVersion < VERSION_CALLS_PRIORITY_BUMP) {
|
||||||
|
notificationManager.deleteNotificationChannel("calls_v2");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TargetApi(26)
|
@TargetApi(26)
|
||||||
|
@ -578,7 +578,7 @@ public class WebRtcCallService extends Service implements InjectableType,
|
|||||||
this.lockManager.updatePhoneState(LockManager.PhoneState.INTERACTIVE);
|
this.lockManager.updatePhoneState(LockManager.PhoneState.INTERACTIVE);
|
||||||
|
|
||||||
sendMessage(WebRtcViewModel.State.CALL_INCOMING, recipient, localCameraState, remoteVideoEnabled, bluetoothAvailable, microphoneEnabled);
|
sendMessage(WebRtcViewModel.State.CALL_INCOMING, recipient, localCameraState, remoteVideoEnabled, bluetoothAvailable, microphoneEnabled);
|
||||||
startCallCardActivity();
|
startCallCardActivityIfPossible();
|
||||||
audioManager.initializeAudioForCall();
|
audioManager.initializeAudioForCall();
|
||||||
|
|
||||||
if (TextSecurePreferences.isCallNotificationsEnabled(this)) {
|
if (TextSecurePreferences.isCallNotificationsEnabled(this)) {
|
||||||
@ -943,7 +943,7 @@ public class WebRtcCallService extends Service implements InjectableType,
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void setCallInProgressNotification(int type, Recipient recipient) {
|
private void setCallInProgressNotification(int type, Recipient recipient) {
|
||||||
startForeground(CallNotificationBuilder.WEBRTC_NOTIFICATION,
|
startForeground(CallNotificationBuilder.getNotificationId(getApplicationContext(), type),
|
||||||
CallNotificationBuilder.getCallInProgressNotification(this, type, recipient));
|
CallNotificationBuilder.getCallInProgressNotification(this, type, recipient));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1021,7 +1021,11 @@ public class WebRtcCallService extends Service implements InjectableType,
|
|||||||
return listenableFutureTask;
|
return listenableFutureTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startCallCardActivity() {
|
private void startCallCardActivityIfPossible() {
|
||||||
|
if (Build.VERSION.SDK_INT >= 29 && !ApplicationContext.getInstance(getApplicationContext()).isAppVisible()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Intent activityIntent = new Intent();
|
Intent activityIntent = new Intent();
|
||||||
activityIntent.setClass(this, WebRtcCallActivity.class);
|
activityIntent.setClass(this, WebRtcCallActivity.class);
|
||||||
activityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
activityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
@ -4,16 +4,20 @@ import android.app.Notification;
|
|||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.os.Build;
|
||||||
|
|
||||||
import androidx.annotation.DrawableRes;
|
import androidx.annotation.DrawableRes;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.StringRes;
|
import androidx.annotation.StringRes;
|
||||||
import androidx.core.app.NotificationCompat;
|
import androidx.core.app.NotificationCompat;
|
||||||
|
|
||||||
|
import org.thoughtcrime.securesms.ApplicationContext;
|
||||||
import org.thoughtcrime.securesms.R;
|
import org.thoughtcrime.securesms.R;
|
||||||
import org.thoughtcrime.securesms.WebRtcCallActivity;
|
import org.thoughtcrime.securesms.WebRtcCallActivity;
|
||||||
import org.thoughtcrime.securesms.notifications.NotificationChannels;
|
import org.thoughtcrime.securesms.notifications.NotificationChannels;
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||||
import org.thoughtcrime.securesms.service.WebRtcCallService;
|
import org.thoughtcrime.securesms.service.WebRtcCallService;
|
||||||
|
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manages the state of the WebRtc items in the Android notification bar.
|
* Manages the state of the WebRtc items in the Android notification bar.
|
||||||
@ -24,25 +28,25 @@ import org.thoughtcrime.securesms.service.WebRtcCallService;
|
|||||||
|
|
||||||
public class CallNotificationBuilder {
|
public class CallNotificationBuilder {
|
||||||
|
|
||||||
public static final int WEBRTC_NOTIFICATION = 313388;
|
private static final int WEBRTC_NOTIFICATION = 313388;
|
||||||
|
private static final int WEBRTC_NOTIFICATION_RINGING = 313389;
|
||||||
|
|
||||||
public static final int TYPE_INCOMING_RINGING = 1;
|
public static final int TYPE_INCOMING_RINGING = 1;
|
||||||
public static final int TYPE_OUTGOING_RINGING = 2;
|
public static final int TYPE_OUTGOING_RINGING = 2;
|
||||||
public static final int TYPE_ESTABLISHED = 3;
|
public static final int TYPE_ESTABLISHED = 3;
|
||||||
public static final int TYPE_INCOMING_CONNECTING = 4;
|
public static final int TYPE_INCOMING_CONNECTING = 4;
|
||||||
|
|
||||||
|
|
||||||
public static Notification getCallInProgressNotification(Context context, int type, Recipient recipient) {
|
public static Notification getCallInProgressNotification(Context context, int type, Recipient recipient) {
|
||||||
Intent contentIntent = new Intent(context, WebRtcCallActivity.class);
|
Intent contentIntent = new Intent(context, WebRtcCallActivity.class);
|
||||||
contentIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
contentIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
||||||
|
|
||||||
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, contentIntent, 0);
|
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, contentIntent, 0);
|
||||||
|
|
||||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, NotificationChannels.CALLS)
|
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, getNotificationChannel(context, type))
|
||||||
.setSmallIcon(R.drawable.ic_call_secure_white_24dp)
|
.setSmallIcon(R.drawable.ic_call_secure_white_24dp)
|
||||||
.setContentIntent(pendingIntent)
|
.setContentIntent(pendingIntent)
|
||||||
.setOngoing(true)
|
.setOngoing(true)
|
||||||
.setContentTitle(recipient.getName());
|
.setContentTitle(recipient.getName());
|
||||||
|
|
||||||
if (type == TYPE_INCOMING_CONNECTING) {
|
if (type == TYPE_INCOMING_CONNECTING) {
|
||||||
builder.setContentText(context.getString(R.string.CallNotificationBuilder_connecting));
|
builder.setContentText(context.getString(R.string.CallNotificationBuilder_connecting));
|
||||||
@ -51,6 +55,12 @@ public class CallNotificationBuilder {
|
|||||||
builder.setContentText(context.getString(R.string.NotificationBarManager__incoming_signal_call));
|
builder.setContentText(context.getString(R.string.NotificationBarManager__incoming_signal_call));
|
||||||
builder.addAction(getServiceNotificationAction(context, WebRtcCallService.ACTION_DENY_CALL, R.drawable.ic_close_grey600_32dp, R.string.NotificationBarManager__deny_call));
|
builder.addAction(getServiceNotificationAction(context, WebRtcCallService.ACTION_DENY_CALL, R.drawable.ic_close_grey600_32dp, R.string.NotificationBarManager__deny_call));
|
||||||
builder.addAction(getActivityNotificationAction(context, WebRtcCallActivity.ANSWER_ACTION, R.drawable.ic_phone_grey600_32dp, R.string.NotificationBarManager__answer_call));
|
builder.addAction(getActivityNotificationAction(context, WebRtcCallActivity.ANSWER_ACTION, R.drawable.ic_phone_grey600_32dp, R.string.NotificationBarManager__answer_call));
|
||||||
|
|
||||||
|
if (callActivityRestricted(context)) {
|
||||||
|
builder.setFullScreenIntent(pendingIntent, true);
|
||||||
|
builder.setPriority(NotificationCompat.PRIORITY_HIGH);
|
||||||
|
builder.setCategory(NotificationCompat.CATEGORY_CALL);
|
||||||
|
}
|
||||||
} else if (type == TYPE_OUTGOING_RINGING) {
|
} else if (type == TYPE_OUTGOING_RINGING) {
|
||||||
builder.setContentText(context.getString(R.string.NotificationBarManager__establishing_signal_call));
|
builder.setContentText(context.getString(R.string.NotificationBarManager__establishing_signal_call));
|
||||||
builder.addAction(getServiceNotificationAction(context, WebRtcCallService.ACTION_LOCAL_HANGUP, R.drawable.ic_call_end_grey600_32dp, R.string.NotificationBarManager__cancel_call));
|
builder.addAction(getServiceNotificationAction(context, WebRtcCallService.ACTION_LOCAL_HANGUP, R.drawable.ic_call_end_grey600_32dp, R.string.NotificationBarManager__cancel_call));
|
||||||
@ -62,6 +72,27 @@ public class CallNotificationBuilder {
|
|||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int getNotificationId(@NonNull Context context, int type) {
|
||||||
|
if (callActivityRestricted(context) && type == TYPE_INCOMING_RINGING) {
|
||||||
|
return WEBRTC_NOTIFICATION_RINGING;
|
||||||
|
} else {
|
||||||
|
return WEBRTC_NOTIFICATION;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
|
||||||
|
public static boolean isWebRtcNotification(int notificationId) {
|
||||||
|
return notificationId == WEBRTC_NOTIFICATION || notificationId == WEBRTC_NOTIFICATION_RINGING;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static @NonNull String getNotificationChannel(@NonNull Context context, int type) {
|
||||||
|
if (callActivityRestricted(context) && type == TYPE_INCOMING_RINGING) {
|
||||||
|
return NotificationChannels.CALLS;
|
||||||
|
} else {
|
||||||
|
return NotificationChannels.OTHER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static NotificationCompat.Action getServiceNotificationAction(Context context, String action, int iconResId, int titleResId) {
|
private static NotificationCompat.Action getServiceNotificationAction(Context context, String action, int iconResId, int titleResId) {
|
||||||
Intent intent = new Intent(context, WebRtcCallService.class);
|
Intent intent = new Intent(context, WebRtcCallService.class);
|
||||||
intent.setAction(action);
|
intent.setAction(action);
|
||||||
@ -81,4 +112,8 @@ public class CallNotificationBuilder {
|
|||||||
|
|
||||||
return new NotificationCompat.Action(iconResId, context.getString(titleResId), pendingIntent);
|
return new NotificationCompat.Action(iconResId, context.getString(titleResId), pendingIntent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean callActivityRestricted(@NonNull Context context) {
|
||||||
|
return Build.VERSION.SDK_INT >= 29 && !ApplicationContext.getInstance(context).isAppVisible();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user