Added custom heads up notification for incoming calls + fixed incoming call activity not showing up on Android < 24

This commit is contained in:
Sylvain Berfini 2019-09-12 16:31:55 +02:00
parent 74261a1830
commit fe880d7774
7 changed files with 240 additions and 88 deletions

View file

@ -155,9 +155,11 @@ public final class LinphoneService extends Service {
if (state == Call.State.IncomingReceived if (state == Call.State.IncomingReceived
|| state == State.IncomingEarlyMedia) { || state == State.IncomingEarlyMedia) {
// Now we rely on the fullscreen intent of the call incoming // Starting SDK 24 (Android 7.0) we rely on the fullscreen intent of the
// notification // call incoming notification
// if (!mLinphoneManager.getCallGsmON()) onIncomingReceived(); if (Version.sdkStrictlyBelow(Version.API24_NOUGAT_70)) {
if (!mLinphoneManager.getCallGsmON()) onIncomingReceived();
}
} else if (state == State.OutgoingInit) { } else if (state == State.OutgoingInit) {
onOutgoingStarted(); onOutgoingStarted();
} else if (state == State.Connected) { } else if (state == State.Connected) {

View file

@ -36,6 +36,7 @@ import android.content.ContentProviderClient;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.widget.RemoteViews;
import org.linphone.R; import org.linphone.R;
import org.linphone.notifications.Notifiable; import org.linphone.notifications.Notifiable;
import org.linphone.notifications.NotifiableMessage; import org.linphone.notifications.NotifiableMessage;
@ -94,36 +95,65 @@ class ApiTwentyFourPlus {
public static Notification createInCallNotification( public static Notification createInCallNotification(
Context context, Context context,
int callId, int callId,
boolean showAnswerAction,
String msg, String msg,
int iconID, int iconID,
Bitmap contactIcon, Bitmap contactIcon,
String contactName, String contactName,
PendingIntent intent) { PendingIntent intent) {
Notification.Builder builder = return new Notification.Builder(context)
new Notification.Builder(context) .setContentTitle(contactName)
.setContentTitle(contactName) .setContentText(msg)
.setContentText(msg) .setSmallIcon(iconID)
.setSmallIcon(iconID) .setAutoCancel(false)
.setAutoCancel(false) .setContentIntent(intent)
.setContentIntent(intent) .setLargeIcon(contactIcon)
.setLargeIcon(contactIcon) .setCategory(Notification.CATEGORY_CALL)
.setCategory(Notification.CATEGORY_CALL) .setVisibility(Notification.VISIBILITY_PUBLIC)
.setVisibility(Notification.VISIBILITY_PUBLIC) .setPriority(Notification.PRIORITY_HIGH)
.setPriority(Notification.PRIORITY_HIGH) .setWhen(System.currentTimeMillis())
.setWhen(System.currentTimeMillis()) .setShowWhen(true)
.setShowWhen(true) .setOngoing(true)
.setOngoing(true) .setColor(context.getColor(R.color.notification_led_color))
.setColor(context.getColor(R.color.notification_led_color)) .addAction(Compatibility.getCallDeclineAction(context, callId))
.addAction(Compatibility.getCallDeclineAction(context, callId)); .build();
}
if (showAnswerAction) { public static Notification createIncomingCallNotification(
builder.setFullScreenIntent(intent, true); Context context,
builder.addAction(Compatibility.getCallAnswerAction(context, callId)); int callId,
Bitmap contactIcon,
String contactName,
String sipUri,
PendingIntent intent) {
RemoteViews notificationLayoutHeadsUp =
new RemoteViews(
context.getPackageName(), R.layout.call_incoming_notification_heads_up);
notificationLayoutHeadsUp.setTextViewText(R.id.caller, contactName);
notificationLayoutHeadsUp.setTextViewText(R.id.sip_uri, sipUri);
notificationLayoutHeadsUp.setTextViewText(
R.id.incoming_call_info, context.getString(R.string.incall_notif_incoming));
if (contactIcon != null) {
notificationLayoutHeadsUp.setImageViewBitmap(R.id.caller_picture, contactIcon);
} }
return builder.build(); return new Notification.Builder(context)
.setStyle(new Notification.DecoratedCustomViewStyle())
.setSmallIcon(R.drawable.topbar_call_notification)
.setAutoCancel(false)
.setContentIntent(intent)
.setCategory(Notification.CATEGORY_CALL)
.setVisibility(Notification.VISIBILITY_PUBLIC)
.setPriority(Notification.PRIORITY_HIGH)
.setWhen(System.currentTimeMillis())
.setShowWhen(true)
.setOngoing(true)
.setColor(context.getColor(R.color.notification_led_color))
.addAction(Compatibility.getCallDeclineAction(context, callId))
.addAction(Compatibility.getCallAnswerAction(context, callId))
.setCustomHeadsUpContentView(notificationLayoutHeadsUp)
.setFullScreenIntent(intent, true)
.build();
} }
public static Notification.Action getReplyMessageAction(Context context, Notifiable notif) { public static Notification.Action getReplyMessageAction(Context context, Notifiable notif) {

View file

@ -75,36 +75,56 @@ class ApiTwentyOnePlus {
public static Notification createInCallNotification( public static Notification createInCallNotification(
Context context, Context context,
boolean isIncoming,
String msg, String msg,
int iconID, int iconID,
Bitmap contactIcon, Bitmap contactIcon,
String contactName, String contactName,
PendingIntent intent) { PendingIntent intent) {
Notification.Builder builder = return new Notification.Builder(context)
new Notification.Builder(context) .setContentTitle(contactName)
.setContentTitle(contactName) .setContentText(msg)
.setContentText(msg) .setSmallIcon(iconID)
.setSmallIcon(iconID) .setAutoCancel(false)
.setAutoCancel(false) .setContentIntent(intent)
.setContentIntent(intent) .setLargeIcon(contactIcon)
.setLargeIcon(contactIcon) .setCategory(Notification.CATEGORY_CALL)
.setCategory(Notification.CATEGORY_CALL) .setVisibility(Notification.VISIBILITY_PUBLIC)
.setVisibility(Notification.VISIBILITY_PUBLIC) .setPriority(Notification.PRIORITY_HIGH)
.setPriority(Notification.PRIORITY_HIGH) .setOngoing(true)
.setOngoing(true) .setLights(
.setLights( ContextCompat.getColor(context, R.color.notification_led_color),
ContextCompat.getColor(context, R.color.notification_led_color), context.getResources().getInteger(R.integer.notification_ms_on),
context.getResources().getInteger(R.integer.notification_ms_on), context.getResources().getInteger(R.integer.notification_ms_off))
context.getResources().getInteger(R.integer.notification_ms_off)) .setShowWhen(true)
.setShowWhen(true); .build();
}
if (isIncoming) { public static Notification createIncomingCallNotification(
builder.setFullScreenIntent(intent, true); Context context,
} Bitmap contactIcon,
String contactName,
String sipUri,
PendingIntent intent) {
return builder.build(); return new Notification.Builder(context)
.setContentTitle(contactName)
.setContentText(context.getString(R.string.incall_notif_incoming))
.setSmallIcon(R.drawable.topbar_call_notification)
.setAutoCancel(false)
.setContentIntent(intent)
.setLargeIcon(contactIcon)
.setCategory(Notification.CATEGORY_CALL)
.setVisibility(Notification.VISIBILITY_PUBLIC)
.setPriority(Notification.PRIORITY_HIGH)
.setOngoing(true)
.setLights(
ContextCompat.getColor(context, R.color.notification_led_color),
context.getResources().getInteger(R.integer.notification_ms_on),
context.getResources().getInteger(R.integer.notification_ms_off))
.setShowWhen(true)
.setFullScreenIntent(intent, true)
.build();
} }
public static Notification createNotification( public static Notification createNotification(

View file

@ -35,6 +35,7 @@ import android.content.pm.PackageManager;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.os.Build; import android.os.Build;
import android.provider.Settings; import android.provider.Settings;
import android.widget.RemoteViews;
import org.linphone.R; import org.linphone.R;
import org.linphone.core.tools.Log; import org.linphone.core.tools.Log;
import org.linphone.notifications.Notifiable; import org.linphone.notifications.Notifiable;
@ -143,41 +144,67 @@ class ApiTwentySixPlus {
public static Notification createInCallNotification( public static Notification createInCallNotification(
Context context, Context context,
int callId, int callId,
boolean isIncoming,
String msg, String msg,
int iconID, int iconID,
Bitmap contactIcon, Bitmap contactIcon,
String contactName, String contactName,
PendingIntent intent) { PendingIntent intent) {
Notification.Builder builder = return new Notification.Builder(
new Notification.Builder( context, context.getString(R.string.notification_service_channel_id))
context, .setContentTitle(contactName)
isIncoming .setContentText(msg)
? context.getString(R.string.notification_channel_id) .setSmallIcon(iconID)
: context.getString( .setAutoCancel(false)
R.string.notification_service_channel_id)) .setContentIntent(intent)
.setContentTitle(contactName) .setLargeIcon(contactIcon)
.setContentText(msg) .setCategory(Notification.CATEGORY_CALL)
.setSmallIcon(iconID) .setVisibility(Notification.VISIBILITY_PUBLIC)
.setAutoCancel(false) .setPriority(Notification.PRIORITY_LOW)
.setContentIntent(intent) .setWhen(System.currentTimeMillis())
.setLargeIcon(contactIcon) .setShowWhen(true)
.setCategory(Notification.CATEGORY_CALL) .setOngoing(true)
.setVisibility(Notification.VISIBILITY_PUBLIC) .setColor(context.getColor(R.color.notification_led_color))
.setPriority( .addAction(Compatibility.getCallDeclineAction(context, callId))
isIncoming ? Notification.PRIORITY_HIGH : Notification.PRIORITY_LOW) .build();
.setWhen(System.currentTimeMillis()) }
.setShowWhen(true)
.setOngoing(true)
.setColor(context.getColor(R.color.notification_led_color))
.addAction(Compatibility.getCallDeclineAction(context, callId));
if (isIncoming) { public static Notification createIncomingCallNotification(
builder.setFullScreenIntent(intent, true); Context context,
builder.addAction(Compatibility.getCallAnswerAction(context, callId)); int callId,
Bitmap contactIcon,
String contactName,
String sipUri,
PendingIntent intent) {
RemoteViews notificationLayoutHeadsUp =
new RemoteViews(
context.getPackageName(), R.layout.call_incoming_notification_heads_up);
notificationLayoutHeadsUp.setTextViewText(R.id.caller, contactName);
notificationLayoutHeadsUp.setTextViewText(R.id.sip_uri, sipUri);
notificationLayoutHeadsUp.setTextViewText(
R.id.incoming_call_info, context.getString(R.string.incall_notif_incoming));
if (contactIcon != null) {
notificationLayoutHeadsUp.setImageViewBitmap(R.id.caller_picture, contactIcon);
} }
return builder.build();
return new Notification.Builder(
context, context.getString(R.string.notification_channel_id))
.setStyle(new Notification.DecoratedCustomViewStyle())
.setSmallIcon(R.drawable.topbar_call_notification)
.setContentIntent(intent)
.setCategory(Notification.CATEGORY_CALL)
.setVisibility(Notification.VISIBILITY_PUBLIC)
.setPriority(Notification.PRIORITY_HIGH)
.setWhen(System.currentTimeMillis())
.setAutoCancel(false)
.setShowWhen(true)
.setOngoing(true)
.setColor(context.getColor(R.color.notification_led_color))
.setFullScreenIntent(intent, true)
.addAction(Compatibility.getCallDeclineAction(context, callId))
.addAction(Compatibility.getCallAnswerAction(context, callId))
.setCustomHeadsUpContentView(notificationLayoutHeadsUp)
.build();
} }
public static Notification createNotification( public static Notification createNotification(

View file

@ -112,7 +112,6 @@ public class Compatibility {
public static Notification createInCallNotification( public static Notification createInCallNotification(
Context context, Context context,
int callId, int callId,
boolean isIncoming,
String msg, String msg,
int iconID, int iconID,
Bitmap contactIcon, Bitmap contactIcon,
@ -120,13 +119,31 @@ public class Compatibility {
PendingIntent intent) { PendingIntent intent) {
if (Version.sdkAboveOrEqual(Version.API26_O_80)) { if (Version.sdkAboveOrEqual(Version.API26_O_80)) {
return ApiTwentySixPlus.createInCallNotification( return ApiTwentySixPlus.createInCallNotification(
context, callId, isIncoming, msg, iconID, contactIcon, contactName, intent); context, callId, msg, iconID, contactIcon, contactName, intent);
} else if (Version.sdkAboveOrEqual(Version.API24_NOUGAT_70)) { } else if (Version.sdkAboveOrEqual(Version.API24_NOUGAT_70)) {
return ApiTwentyFourPlus.createInCallNotification( return ApiTwentyFourPlus.createInCallNotification(
context, callId, isIncoming, msg, iconID, contactIcon, contactName, intent); context, callId, msg, iconID, contactIcon, contactName, intent);
} }
return ApiTwentyOnePlus.createInCallNotification( return ApiTwentyOnePlus.createInCallNotification(
context, isIncoming, msg, iconID, contactIcon, contactName, intent); context, msg, iconID, contactIcon, contactName, intent);
}
public static Notification createIncomingCallNotification(
Context context,
int callId,
Bitmap contactIcon,
String contactName,
String sipUri,
PendingIntent intent) {
if (Version.sdkAboveOrEqual(Version.API26_O_80)) {
return ApiTwentySixPlus.createIncomingCallNotification(
context, callId, contactIcon, contactName, sipUri, intent);
} else if (Version.sdkAboveOrEqual(Version.API24_NOUGAT_70)) {
return ApiTwentyFourPlus.createIncomingCallNotification(
context, callId, contactIcon, contactName, sipUri, intent);
}
return ApiTwentyOnePlus.createIncomingCallNotification(
context, contactIcon, contactName, sipUri, intent);
} }
public static Notification createNotification( public static Notification createNotification(

View file

@ -614,21 +614,32 @@ public class NotificationsManager {
+ callNotifIntentClass); + callNotifIntentClass);
LinphoneContact contact = ContactsManager.getInstance().findContactFromAddress(address); LinphoneContact contact = ContactsManager.getInstance().findContactFromAddress(address);
Uri pictureUri = contact != null ? contact.getPhotoUri() : null; Uri pictureUri = contact != null ? contact.getThumbnailUri() : null;
Bitmap bm = ImageUtils.getRoundBitmapFromUri(mContext, pictureUri); Bitmap bm = ImageUtils.getRoundBitmapFromUri(mContext, pictureUri);
String name = LinphoneUtils.getAddressDisplayName(address); String name = LinphoneUtils.getAddressDisplayName(address);
boolean isIncoming = callNotifIntentClass == CallIncomingActivity.class; boolean isIncoming = callNotifIntentClass == CallIncomingActivity.class;
Notification notification = Notification notification;
Compatibility.createInCallNotification( if (isIncoming) {
mContext, notification =
notif.getNotificationId(), Compatibility.createIncomingCallNotification(
isIncoming, mContext,
mContext.getString(notificationTextId), notif.getNotificationId(),
iconId, bm,
bm, name,
name, addressAsString,
pendingIntent); pendingIntent);
} else {
notification =
Compatibility.createInCallNotification(
mContext,
notif.getNotificationId(),
mContext.getString(notificationTextId),
iconId,
bm,
name,
pendingIntent);
}
// Don't use incoming call notification as foreground service notif ! // Don't use incoming call notification as foreground service notif !
if (!isServiceNotificationDisplayed() && !isIncoming) { if (!isServiceNotificationDisplayed() && !isIncoming) {

View file

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:orientation="vertical">
<TextView
android:id="@+id/caller"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@android:style/TextAppearance.Material.Notification.Title"/>
<TextView
android:id="@+id/sip_uri"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@color/primary_color"
style="@android:style/TextAppearance.Material.Notification.Line2"/>
<TextView
android:id="@+id/incoming_call_info"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@android:style/TextAppearance.Material.Notification.Info"/>
</LinearLayout>
<ImageView
android:id="@+id/caller_picture"
android:layout_width="50dp"
android:layout_height="50dp"
android:adjustViewBounds="true"
android:src="@drawable/avatar"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:layout_marginRight="20dp" />
</RelativeLayout>