Support Android Q call notifications.

This commit is contained in:
Greyson Parrelli 2019-06-27 15:17:14 -04:00
parent 8a3d0dde91
commit abcd599ad8
6 changed files with 80 additions and 27 deletions

View File

@ -86,6 +86,7 @@
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<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.USE_FULL_SCREEN_INTENT"/>
<application android:name=".ApplicationContext"
android:icon="@mipmap/ic_launcher"

View File

@ -26,6 +26,7 @@ import android.content.res.Configuration;
import android.media.AudioManager;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import org.thoughtcrime.securesms.logging.Log;
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.TextSecurePreferences;
import org.thoughtcrime.securesms.util.ViewUtil;
import org.thoughtcrime.securesms.webrtc.CallNotificationBuilder;
import org.whispersystems.libsignal.IdentityKey;
import org.whispersystems.libsignal.SignalProtocolAddress;
@ -77,6 +79,8 @@ public class WebRtcCallActivity extends Activity {
setVolumeControlStream(AudioManager.STREAM_VOICE_CALL);
initializeResources();
processIntent(getIntent());
}
@ -91,13 +95,7 @@ public class WebRtcCallActivity extends Activity {
@Override
public void onNewIntent(Intent intent){
Log.i(TAG, "onNewIntent");
if (ANSWER_ACTION.equals(intent.getAction())) {
handleAnswerCall();
} else if (DENY_ACTION.equals(intent.getAction())) {
handleDenyCall();
} else if (END_CALL_ACTION.equals(intent.getAction())) {
handleEndCall();
}
processIntent(intent);
}
@Override
@ -117,6 +115,16 @@ public class WebRtcCallActivity extends Activity {
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() {
if (TextSecurePreferences.isScreenSecurityEnabled(this)) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);

View File

@ -146,7 +146,7 @@ public class MessageNotifier {
StatusBarNotification[] activeNotifications = notifications.getActiveNotifications();
for (StatusBarNotification activeNotification : activeNotifications) {
if (activeNotification.getId() != CallNotificationBuilder.WEBRTC_NOTIFICATION) {
if (!CallNotificationBuilder.isWebRtcNotification(activeNotification.getId())) {
notifications.cancel(activeNotification.getId());
}
}
@ -167,11 +167,11 @@ public class MessageNotifier {
for (StatusBarNotification notification : activeNotifications) {
boolean validNotification = false;
if (notification.getId() != SUMMARY_NOTIFICATION_ID &&
notification.getId() != CallNotificationBuilder.WEBRTC_NOTIFICATION &&
notification.getId() != KeyCachingService.SERVICE_RUNNING_ID &&
notification.getId() != IncomingMessageObserver.FOREGROUND_ID &&
notification.getId() != PENDING_MESSAGES_ID)
if (notification.getId() != SUMMARY_NOTIFICATION_ID &&
notification.getId() != KeyCachingService.SERVICE_RUNNING_ID &&
notification.getId() != IncomingMessageObserver.FOREGROUND_ID &&
notification.getId() != PENDING_MESSAGES_ID &&
!CallNotificationBuilder.isWebRtcNotification(notification.getId()))
{
for (NotificationItem item : notificationState.getNotifications()) {
if (notification.getId() == (SUMMARY_NOTIFICATION_ID + item.getThreadId())) {

View File

@ -41,15 +41,16 @@ public class NotificationChannels {
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 CONTACT_PREFIX = "contact_";
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 APP_UPDATES = "app_updates";
public static final String BACKUPS = "backups_v2";
@ -425,7 +426,7 @@ public class NotificationChannels {
notificationManager.createNotificationChannelGroup(messagesGroup);
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 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);
@ -462,6 +463,10 @@ public class NotificationChannels {
notificationManager.deleteNotificationChannel("backups");
notificationManager.deleteNotificationChannel("other");
}
if (oldVersion < VERSION_CALLS_PRIORITY_BUMP) {
notificationManager.deleteNotificationChannel("calls_v2");
}
}
@TargetApi(26)

View File

@ -578,7 +578,7 @@ public class WebRtcCallService extends Service implements InjectableType,
this.lockManager.updatePhoneState(LockManager.PhoneState.INTERACTIVE);
sendMessage(WebRtcViewModel.State.CALL_INCOMING, recipient, localCameraState, remoteVideoEnabled, bluetoothAvailable, microphoneEnabled);
startCallCardActivity();
startCallCardActivityIfPossible();
audioManager.initializeAudioForCall();
if (TextSecurePreferences.isCallNotificationsEnabled(this)) {
@ -943,7 +943,7 @@ public class WebRtcCallService extends Service implements InjectableType,
}
private void setCallInProgressNotification(int type, Recipient recipient) {
startForeground(CallNotificationBuilder.WEBRTC_NOTIFICATION,
startForeground(CallNotificationBuilder.getNotificationId(getApplicationContext(), type),
CallNotificationBuilder.getCallInProgressNotification(this, type, recipient));
}
@ -1021,7 +1021,11 @@ public class WebRtcCallService extends Service implements InjectableType,
return listenableFutureTask;
}
private void startCallCardActivity() {
private void startCallCardActivityIfPossible() {
if (Build.VERSION.SDK_INT >= 29 && !ApplicationContext.getInstance(getApplicationContext()).isAppVisible()) {
return;
}
Intent activityIntent = new Intent();
activityIntent.setClass(this, WebRtcCallActivity.class);
activityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

View File

@ -4,16 +4,20 @@ import android.app.Notification;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.annotation.StringRes;
import androidx.core.app.NotificationCompat;
import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.WebRtcCallActivity;
import org.thoughtcrime.securesms.notifications.NotificationChannels;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.service.WebRtcCallService;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
/**
* 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 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_OUTGOING_RINGING = 2;
public static final int TYPE_ESTABLISHED = 3;
public static final int TYPE_INCOMING_CONNECTING = 4;
public static Notification getCallInProgressNotification(Context context, int type, Recipient recipient) {
Intent contentIntent = new Intent(context, WebRtcCallActivity.class);
contentIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, contentIntent, 0);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, NotificationChannels.CALLS)
.setSmallIcon(R.drawable.ic_call_secure_white_24dp)
.setContentIntent(pendingIntent)
.setOngoing(true)
.setContentTitle(recipient.getName());
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, getNotificationChannel(context, type))
.setSmallIcon(R.drawable.ic_call_secure_white_24dp)
.setContentIntent(pendingIntent)
.setOngoing(true)
.setContentTitle(recipient.getName());
if (type == TYPE_INCOMING_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.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));
if (callActivityRestricted(context)) {
builder.setFullScreenIntent(pendingIntent, true);
builder.setPriority(NotificationCompat.PRIORITY_HIGH);
builder.setCategory(NotificationCompat.CATEGORY_CALL);
}
} else if (type == TYPE_OUTGOING_RINGING) {
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));
@ -62,6 +72,27 @@ public class CallNotificationBuilder {
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) {
Intent intent = new Intent(context, WebRtcCallService.class);
intent.setAction(action);
@ -81,4 +112,8 @@ public class CallNotificationBuilder {
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();
}
}