From 74261a1830516d31905bf7c2998fad14ab82c7ed Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Wed, 11 Sep 2019 16:17:53 +0200 Subject: [PATCH] Improved notifications: start call activity after answering from notification + show reply in message notification like SMS app + improved compatibility methods to fully used available APIs + updated target api to 29 --- .gitlab-ci-files/job-android.yml | 4 +- CHANGELOG.md | 1 + app/build.gradle | 4 +- .../java/org/linphone/LinphoneService.java | 10 ++ .../linphone/call/CallIncomingActivity.java | 6 +- .../linphone/call/CallOutgoingActivity.java | 6 +- .../compatibility/ApiTwentyEightPlus.java | 61 ++++++- .../compatibility/ApiTwentyFourPlus.java | 8 +- .../compatibility/ApiTwentyNinePlus.java | 126 +++++++++++++++ .../compatibility/ApiTwentySixPlus.java | 8 +- .../linphone/compatibility/Compatibility.java | 41 +++++ .../NotificationBroadcastReceiver.java | 23 +-- .../notifications/NotificationsManager.java | 151 +++++++++++++----- .../{bc-dev-android-28 => bc-dev-android-29} | 6 +- 14 files changed, 374 insertions(+), 81 deletions(-) create mode 100644 app/src/main/java/org/linphone/compatibility/ApiTwentyNinePlus.java rename docker-files/{bc-dev-android-28 => bc-dev-android-29} (91%) diff --git a/.gitlab-ci-files/job-android.yml b/.gitlab-ci-files/job-android.yml index 34cfba452..4c130ecec 100644 --- a/.gitlab-ci-files/job-android.yml +++ b/.gitlab-ci-files/job-android.yml @@ -2,7 +2,7 @@ job-android: stage: build tags: [ "docker-android" ] - image: gitlab.linphone.org:4567/bc/public/linphone-android/bc-dev-android:28 + image: gitlab.linphone.org:4567/bc/public/linphone-android/bc-dev-android:29 before_script: - if ! [ -z ${SCP_PRIVATE_KEY+x} ]; then eval $(ssh-agent -s); fi @@ -30,4 +30,4 @@ job-android: .scheduled-job-android: extends: job-android only: - - schedules \ No newline at end of file + - schedules diff --git a/CHANGELOG.md b/CHANGELOG.md index 78afeb8c2..e3b10d29f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ Group changes to describe their impact on the project, as follows: - Call statistics are now available for each call & conference - Added our own devices in LIME encrypted chatrooms' security view - No longer display incoming call activity from Service, instead use incoming call notification with full screen intent +- Improved reply notification when replying to a chat message from the notification ## [4.1.0] - 2019-05-03 diff --git a/app/build.gradle b/app/build.gradle index 9bc8ffadf..47f9366a4 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -74,10 +74,10 @@ android { abortOnError false } - compileSdkVersion 28 + compileSdkVersion 29 defaultConfig { minSdkVersion 21 - targetSdkVersion 28 + targetSdkVersion 29 versionCode 4126 versionName "${project.version}" applicationId getPackageName() diff --git a/app/src/main/java/org/linphone/LinphoneService.java b/app/src/main/java/org/linphone/LinphoneService.java index bb26781d6..b70c0d044 100644 --- a/app/src/main/java/org/linphone/LinphoneService.java +++ b/app/src/main/java/org/linphone/LinphoneService.java @@ -30,6 +30,7 @@ import android.os.Handler; import android.os.IBinder; import android.provider.ContactsContract; import android.view.WindowManager; +import org.linphone.call.CallActivity; import org.linphone.call.CallIncomingActivity; import org.linphone.call.CallOutgoingActivity; import org.linphone.contacts.ContactsManager; @@ -159,6 +160,8 @@ public final class LinphoneService extends Service { // if (!mLinphoneManager.getCallGsmON()) onIncomingReceived(); } else if (state == State.OutgoingInit) { onOutgoingStarted(); + } else if (state == State.Connected) { + onCallStarted(); } else if (state == State.End || state == State.Released || state == State.Error) { @@ -384,4 +387,11 @@ public final class LinphoneService extends Service { intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); } + + private void onCallStarted() { + Intent intent = new Intent(LinphoneService.this, CallActivity.class); + // This flag is required to start an Activity from a Service context + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + startActivity(intent); + } } diff --git a/app/src/main/java/org/linphone/call/CallIncomingActivity.java b/app/src/main/java/org/linphone/call/CallIncomingActivity.java index 9c259c6c6..1b469d2b9 100644 --- a/app/src/main/java/org/linphone/call/CallIncomingActivity.java +++ b/app/src/main/java/org/linphone/call/CallIncomingActivity.java @@ -22,7 +22,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. import android.Manifest; import android.app.KeyguardManager; import android.content.Context; -import android.content.Intent; import android.content.pm.PackageManager; import android.os.Bundle; import android.view.KeyEvent; @@ -126,8 +125,9 @@ public class CallIncomingActivity extends LinphoneGenericActivity { Core core, Call call, State state, String message) { if (call == mCall) { if (state == State.Connected) { - startActivity( - new Intent(CallIncomingActivity.this, CallActivity.class)); + // This is done by the Service listener now + // startActivity(new Intent(CallOutgoingActivity.this, + // CallActivity.class)); } } diff --git a/app/src/main/java/org/linphone/call/CallOutgoingActivity.java b/app/src/main/java/org/linphone/call/CallOutgoingActivity.java index 59c14b2de..242f99e6a 100644 --- a/app/src/main/java/org/linphone/call/CallOutgoingActivity.java +++ b/app/src/main/java/org/linphone/call/CallOutgoingActivity.java @@ -20,7 +20,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import android.Manifest; -import android.content.Intent; import android.content.pm.PackageManager; import android.os.Bundle; import android.view.KeyEvent; @@ -129,8 +128,9 @@ public class CallOutgoingActivity extends LinphoneGenericActivity implements OnC .show(); } } else if (state == State.Connected) { - startActivity( - new Intent(CallOutgoingActivity.this, CallActivity.class)); + // This is done by the Service listener now + // startActivity(new Intent(CallOutgoingActivity.this, + // CallActivity.class)); } if (LinphoneManager.getCore().getCallsNb() == 0) { diff --git a/app/src/main/java/org/linphone/compatibility/ApiTwentyEightPlus.java b/app/src/main/java/org/linphone/compatibility/ApiTwentyEightPlus.java index 2e3624fde..23515d484 100644 --- a/app/src/main/java/org/linphone/compatibility/ApiTwentyEightPlus.java +++ b/app/src/main/java/org/linphone/compatibility/ApiTwentyEightPlus.java @@ -20,19 +20,27 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import static org.linphone.compatibility.Compatibility.CHAT_NOTIFICATIONS_GROUP; +import static org.linphone.compatibility.Compatibility.INTENT_LOCAL_IDENTITY; +import static org.linphone.compatibility.Compatibility.INTENT_MARK_AS_READ_ACTION; +import static org.linphone.compatibility.Compatibility.INTENT_NOTIF_ID; +import static org.linphone.compatibility.Compatibility.INTENT_REPLY_NOTIF_ACTION; +import static org.linphone.compatibility.Compatibility.KEY_TEXT_REPLY; import android.annotation.TargetApi; import android.app.ActivityManager; import android.app.Notification; import android.app.PendingIntent; import android.app.Person; +import android.app.RemoteInput; import android.app.usage.UsageStatsManager; import android.content.Context; +import android.content.Intent; import android.graphics.Bitmap; import android.graphics.drawable.Icon; import org.linphone.R; import org.linphone.notifications.Notifiable; import org.linphone.notifications.NotifiableMessage; +import org.linphone.notifications.NotificationBroadcastReceiver; @TargetApi(28) class ApiTwentyEightPlus { @@ -84,8 +92,8 @@ class ApiTwentyEightPlus { .setShowWhen(true) .setColor(context.getColor(R.color.notification_led_color)) .setStyle(style) - .addAction(ApiTwentyFourPlus.getReplyMessageAction(context, notif)) - .addAction(ApiTwentyFourPlus.getMarkMessageAsReadAction(context, notif)) + .addAction(Compatibility.getReplyMessageAction(context, notif)) + .addAction(Compatibility.getMarkMessageAsReadAction(context, notif)) .build(); } @@ -114,4 +122,53 @@ class ApiTwentyEightPlus { } return null; } + + public static Notification.Action getReplyMessageAction(Context context, Notifiable notif) { + String replyLabel = context.getResources().getString(R.string.notification_reply_label); + RemoteInput remoteInput = + new RemoteInput.Builder(KEY_TEXT_REPLY).setLabel(replyLabel).build(); + + Intent replyIntent = new Intent(context, NotificationBroadcastReceiver.class); + replyIntent.setAction(INTENT_REPLY_NOTIF_ACTION); + replyIntent.putExtra(INTENT_NOTIF_ID, notif.getNotificationId()); + replyIntent.putExtra(INTENT_LOCAL_IDENTITY, notif.getLocalIdentity()); + + PendingIntent replyPendingIntent = + PendingIntent.getBroadcast( + context, + notif.getNotificationId(), + replyIntent, + PendingIntent.FLAG_UPDATE_CURRENT); + + return new Notification.Action.Builder( + R.drawable.chat_send_over, + context.getString(R.string.notification_reply_label), + replyPendingIntent) + .addRemoteInput(remoteInput) + .setAllowGeneratedReplies(true) + .setSemanticAction(Notification.Action.SEMANTIC_ACTION_REPLY) + .build(); + } + + public static Notification.Action getMarkMessageAsReadAction( + Context context, Notifiable notif) { + Intent markAsReadIntent = new Intent(context, NotificationBroadcastReceiver.class); + markAsReadIntent.setAction(INTENT_MARK_AS_READ_ACTION); + markAsReadIntent.putExtra(INTENT_NOTIF_ID, notif.getNotificationId()); + markAsReadIntent.putExtra(INTENT_LOCAL_IDENTITY, notif.getLocalIdentity()); + + PendingIntent markAsReadPendingIntent = + PendingIntent.getBroadcast( + context, + notif.getNotificationId(), + markAsReadIntent, + PendingIntent.FLAG_UPDATE_CURRENT); + + return new Notification.Action.Builder( + R.drawable.chat_send_over, + context.getString(R.string.notification_mark_as_read_label), + markAsReadPendingIntent) + .setSemanticAction(Notification.Action.SEMANTIC_ACTION_MARK_AS_READ) + .build(); + } } diff --git a/app/src/main/java/org/linphone/compatibility/ApiTwentyFourPlus.java b/app/src/main/java/org/linphone/compatibility/ApiTwentyFourPlus.java index e05e91d33..7abe859cb 100644 --- a/app/src/main/java/org/linphone/compatibility/ApiTwentyFourPlus.java +++ b/app/src/main/java/org/linphone/compatibility/ApiTwentyFourPlus.java @@ -86,8 +86,8 @@ class ApiTwentyFourPlus { .setShowWhen(true) .setColor(context.getColor(R.color.notification_led_color)) .setStyle(style) - .addAction(getReplyMessageAction(context, notif)) - .addAction(getMarkMessageAsReadAction(context, notif)) + .addAction(Compatibility.getReplyMessageAction(context, notif)) + .addAction(Compatibility.getMarkMessageAsReadAction(context, notif)) .build(); } @@ -116,11 +116,11 @@ class ApiTwentyFourPlus { .setShowWhen(true) .setOngoing(true) .setColor(context.getColor(R.color.notification_led_color)) - .addAction(getCallDeclineAction(context, callId)); + .addAction(Compatibility.getCallDeclineAction(context, callId)); if (showAnswerAction) { builder.setFullScreenIntent(intent, true); - builder.addAction(getCallAnswerAction(context, callId)); + builder.addAction(Compatibility.getCallAnswerAction(context, callId)); } return builder.build(); diff --git a/app/src/main/java/org/linphone/compatibility/ApiTwentyNinePlus.java b/app/src/main/java/org/linphone/compatibility/ApiTwentyNinePlus.java new file mode 100644 index 000000000..ff5c114cc --- /dev/null +++ b/app/src/main/java/org/linphone/compatibility/ApiTwentyNinePlus.java @@ -0,0 +1,126 @@ +package org.linphone.compatibility; + +/* +ApiTwentyNinePlus.java +Copyright (C) 2019 Belledonne Communications, Grenoble, France + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +import static org.linphone.compatibility.Compatibility.INTENT_ANSWER_CALL_NOTIF_ACTION; +import static org.linphone.compatibility.Compatibility.INTENT_HANGUP_CALL_NOTIF_ACTION; +import static org.linphone.compatibility.Compatibility.INTENT_LOCAL_IDENTITY; +import static org.linphone.compatibility.Compatibility.INTENT_MARK_AS_READ_ACTION; +import static org.linphone.compatibility.Compatibility.INTENT_NOTIF_ID; +import static org.linphone.compatibility.Compatibility.INTENT_REPLY_NOTIF_ACTION; +import static org.linphone.compatibility.Compatibility.KEY_TEXT_REPLY; + +import android.annotation.TargetApi; +import android.app.Notification; +import android.app.PendingIntent; +import android.app.RemoteInput; +import android.content.Context; +import android.content.Intent; +import org.linphone.R; +import org.linphone.notifications.Notifiable; +import org.linphone.notifications.NotificationBroadcastReceiver; + +@TargetApi(29) +public class ApiTwentyNinePlus { + public static Notification.Action getReplyMessageAction(Context context, Notifiable notif) { + String replyLabel = context.getResources().getString(R.string.notification_reply_label); + RemoteInput remoteInput = + new RemoteInput.Builder(KEY_TEXT_REPLY).setLabel(replyLabel).build(); + + Intent replyIntent = new Intent(context, NotificationBroadcastReceiver.class); + replyIntent.setAction(INTENT_REPLY_NOTIF_ACTION); + replyIntent.putExtra(INTENT_NOTIF_ID, notif.getNotificationId()); + replyIntent.putExtra(INTENT_LOCAL_IDENTITY, notif.getLocalIdentity()); + + PendingIntent replyPendingIntent = + PendingIntent.getBroadcast( + context, + notif.getNotificationId(), + replyIntent, + PendingIntent.FLAG_UPDATE_CURRENT); + + return new Notification.Action.Builder( + R.drawable.chat_send_over, + context.getString(R.string.notification_reply_label), + replyPendingIntent) + .addRemoteInput(remoteInput) + .setAllowGeneratedReplies(true) + .setSemanticAction(Notification.Action.SEMANTIC_ACTION_REPLY) + .setContextual(true) + .build(); + } + + public static Notification.Action getMarkMessageAsReadAction( + Context context, Notifiable notif) { + Intent markAsReadIntent = new Intent(context, NotificationBroadcastReceiver.class); + markAsReadIntent.setAction(INTENT_MARK_AS_READ_ACTION); + markAsReadIntent.putExtra(INTENT_NOTIF_ID, notif.getNotificationId()); + markAsReadIntent.putExtra(INTENT_LOCAL_IDENTITY, notif.getLocalIdentity()); + + PendingIntent markAsReadPendingIntent = + PendingIntent.getBroadcast( + context, + notif.getNotificationId(), + markAsReadIntent, + PendingIntent.FLAG_UPDATE_CURRENT); + + return new Notification.Action.Builder( + R.drawable.chat_send_over, + context.getString(R.string.notification_mark_as_read_label), + markAsReadPendingIntent) + .setSemanticAction(Notification.Action.SEMANTIC_ACTION_MARK_AS_READ) + .setContextual(true) + .build(); + } + + public static Notification.Action getCallAnswerAction(Context context, int callId) { + Intent answerIntent = new Intent(context, NotificationBroadcastReceiver.class); + answerIntent.setAction(INTENT_ANSWER_CALL_NOTIF_ACTION); + answerIntent.putExtra(INTENT_NOTIF_ID, callId); + + PendingIntent answerPendingIntent = + PendingIntent.getBroadcast( + context, callId, answerIntent, PendingIntent.FLAG_UPDATE_CURRENT); + + return new Notification.Action.Builder( + R.drawable.call_audio_start, + context.getString(R.string.notification_call_answer_label), + answerPendingIntent) + .setContextual(true) + .build(); + } + + public static Notification.Action getCallDeclineAction(Context context, int callId) { + Intent hangupIntent = new Intent(context, NotificationBroadcastReceiver.class); + hangupIntent.setAction(INTENT_HANGUP_CALL_NOTIF_ACTION); + hangupIntent.putExtra(INTENT_NOTIF_ID, callId); + + PendingIntent hangupPendingIntent = + PendingIntent.getBroadcast( + context, callId, hangupIntent, PendingIntent.FLAG_UPDATE_CURRENT); + + return new Notification.Action.Builder( + R.drawable.call_hangup, + context.getString(R.string.notification_call_hangup_label), + hangupPendingIntent) + .setContextual(true) + .build(); + } +} diff --git a/app/src/main/java/org/linphone/compatibility/ApiTwentySixPlus.java b/app/src/main/java/org/linphone/compatibility/ApiTwentySixPlus.java index e30a9c57a..157eca5d4 100644 --- a/app/src/main/java/org/linphone/compatibility/ApiTwentySixPlus.java +++ b/app/src/main/java/org/linphone/compatibility/ApiTwentySixPlus.java @@ -135,8 +135,8 @@ class ApiTwentySixPlus { .setShowWhen(true) .setColor(context.getColor(R.color.notification_led_color)) .setStyle(style) - .addAction(ApiTwentyFourPlus.getReplyMessageAction(context, notif)) - .addAction(ApiTwentyFourPlus.getMarkMessageAsReadAction(context, notif)) + .addAction(Compatibility.getReplyMessageAction(context, notif)) + .addAction(Compatibility.getMarkMessageAsReadAction(context, notif)) .build(); } @@ -171,11 +171,11 @@ class ApiTwentySixPlus { .setShowWhen(true) .setOngoing(true) .setColor(context.getColor(R.color.notification_led_color)) - .addAction(ApiTwentyFourPlus.getCallDeclineAction(context, callId)); + .addAction(Compatibility.getCallDeclineAction(context, callId)); if (isIncoming) { builder.setFullScreenIntent(intent, true); - builder.addAction(ApiTwentyFourPlus.getCallAnswerAction(context, callId)); + builder.addAction(Compatibility.getCallAnswerAction(context, callId)); } return builder.build(); } diff --git a/app/src/main/java/org/linphone/compatibility/Compatibility.java b/app/src/main/java/org/linphone/compatibility/Compatibility.java index a1be9edd6..89e178c5a 100644 --- a/app/src/main/java/org/linphone/compatibility/Compatibility.java +++ b/app/src/main/java/org/linphone/compatibility/Compatibility.java @@ -249,4 +249,45 @@ public class Compatibility { ApiTwentySixPlus.enterPipMode(activity); } } + + public static Notification.Action getReplyMessageAction(Context context, Notifiable notif) { + if (Version.sdkAboveOrEqual(Version.API29_ANDROID_10)) { + return ApiTwentyNinePlus.getReplyMessageAction(context, notif); + } else if (Version.sdkAboveOrEqual(Version.API28_PIE_90)) { + return ApiTwentyEightPlus.getReplyMessageAction(context, notif); + } else if (Version.sdkAboveOrEqual(Version.API24_NOUGAT_70)) { + return ApiTwentyFourPlus.getReplyMessageAction(context, notif); + } + return null; + } + + public static Notification.Action getMarkMessageAsReadAction( + Context context, Notifiable notif) { + if (Version.sdkAboveOrEqual(Version.API29_ANDROID_10)) { + return ApiTwentyNinePlus.getMarkMessageAsReadAction(context, notif); + } else if (Version.sdkAboveOrEqual(Version.API28_PIE_90)) { + return ApiTwentyEightPlus.getMarkMessageAsReadAction(context, notif); + } else if (Version.sdkAboveOrEqual(Version.API24_NOUGAT_70)) { + return ApiTwentyFourPlus.getMarkMessageAsReadAction(context, notif); + } + return null; + } + + public static Notification.Action getCallAnswerAction(Context context, int callId) { + if (Version.sdkAboveOrEqual(Version.API29_ANDROID_10)) { + return ApiTwentyNinePlus.getCallAnswerAction(context, callId); + } else if (Version.sdkAboveOrEqual(Version.API24_NOUGAT_70)) { + return ApiTwentyFourPlus.getCallAnswerAction(context, callId); + } + return null; + } + + public static Notification.Action getCallDeclineAction(Context context, int callId) { + if (Version.sdkAboveOrEqual(Version.API29_ANDROID_10)) { + return ApiTwentyNinePlus.getCallDeclineAction(context, callId); + } else if (Version.sdkAboveOrEqual(Version.API24_NOUGAT_70)) { + return ApiTwentyFourPlus.getCallDeclineAction(context, callId); + } + return null; + } } diff --git a/app/src/main/java/org/linphone/notifications/NotificationBroadcastReceiver.java b/app/src/main/java/org/linphone/notifications/NotificationBroadcastReceiver.java index ceb9154d9..e7b466a55 100644 --- a/app/src/main/java/org/linphone/notifications/NotificationBroadcastReceiver.java +++ b/app/src/main/java/org/linphone/notifications/NotificationBroadcastReceiver.java @@ -32,7 +32,6 @@ import org.linphone.compatibility.Compatibility; import org.linphone.core.Address; import org.linphone.core.Call; import org.linphone.core.ChatMessage; -import org.linphone.core.ChatMessageListenerStub; import org.linphone.core.ChatRoom; import org.linphone.core.Core; import org.linphone.core.tools.Log; @@ -97,25 +96,11 @@ public class NotificationBroadcastReceiver extends BroadcastReceiver { } ChatMessage msg = room.createMessage(reply); - msg.send(); + msg.setUserData(notifId); msg.addListener( - new ChatMessageListenerStub() { - @Override - public void onMsgStateChanged( - ChatMessage msg, ChatMessage.State state) { - if (state == ChatMessage.State.Delivered) { - Notification replied = - Compatibility.createRepliedNotification(context, reply); - LinphoneService.instance() - .getNotificationManager() - .sendNotification(notifId, replied); - } else if (state == ChatMessage.State.NotDelivered) { - Log.e( - "[Notification Broadcast Receiver] Couldn't send reply, message is not delivered"); - onError(context, notifId); - } - } - }); + LinphoneService.instance().getNotificationManager().getMessageListener()); + msg.send(); + Log.i("[Notification Broadcast Receiver] Reply sent for notif id " + notifId); } else { LinphoneService.instance().getNotificationManager().dismissNotification(notifId); } diff --git a/app/src/main/java/org/linphone/notifications/NotificationsManager.java b/app/src/main/java/org/linphone/notifications/NotificationsManager.java index 795fb9324..218c58963 100644 --- a/app/src/main/java/org/linphone/notifications/NotificationsManager.java +++ b/app/src/main/java/org/linphone/notifications/NotificationsManager.java @@ -45,6 +45,7 @@ import org.linphone.contacts.LinphoneContact; import org.linphone.core.Address; import org.linphone.core.Call; import org.linphone.core.ChatMessage; +import org.linphone.core.ChatMessageListenerStub; import org.linphone.core.ChatRoom; import org.linphone.core.ChatRoomCapabilities; import org.linphone.core.Content; @@ -73,6 +74,7 @@ public class NotificationsManager { private int mCurrentForegroundServiceNotification; private String mCurrentChatRoomAddress; private CoreListenerStub mListener; + private ChatMessageListenerStub mMessageListener; public NotificationsManager(Context context) { mContext = context; @@ -207,6 +209,53 @@ public class NotificationsManager { } } }; + + mMessageListener = + new ChatMessageListenerStub() { + @Override + public void onMsgStateChanged(ChatMessage msg, ChatMessage.State state) { + if (msg.getUserData() == null) return; + int notifId = (int) msg.getUserData(); + Log.i( + "[Notifications Manager] Reply message state changed (" + + state.name() + + ") for notif id " + + notifId); + + if (state != ChatMessage.State.InProgress) { + // There is no need to be called here twice + msg.removeListener(this); + } + + if (state == ChatMessage.State.Delivered + || state == ChatMessage.State.Displayed) { + Notifiable notif = + mChatNotifMap.get( + msg.getChatRoom().getPeerAddress().asStringUriOnly()); + if (notif == null) { + Log.e( + "[Notifications Manager] Couldn't find message notification for SIP URI " + + msg.getChatRoom() + .getPeerAddress() + .asStringUriOnly()); + dismissNotification(notifId); + return; + } else if (notif.getNotificationId() != notifId) { + Log.w( + "[Notifications Manager] Notif ID doesn't match: " + + notifId + + " != " + + notif.getNotificationId()); + } + + displayReplyMessageNotification(msg, notif); + } else if (state == ChatMessage.State.NotDelivered) { + Log.e( + "[Notifications Manager] Couldn't send reply, message is not delivered"); + dismissNotification(notifId); + } + } + }; } public void onCoreReady() { @@ -294,6 +343,10 @@ public class NotificationsManager { } } + public ChatMessageListenerStub getMessageListener() { + return mMessageListener; + } + private boolean isServiceNotificationDisplayed() { return LinphonePreferences.instance().getServiceNotificationVisibility(); } @@ -307,6 +360,61 @@ public class NotificationsManager { return null; } + private void displayMessageNotificationFromNotifiable( + Notifiable notif, String remoteSipUri, String localSipUri) { + Intent notifIntent = new Intent(mContext, ChatActivity.class); + notifIntent.putExtra("RemoteSipUri", remoteSipUri); + notifIntent.putExtra("LocalSipUri", localSipUri); + addFlagsToIntent(notifIntent); + + PendingIntent pendingIntent = + PendingIntent.getActivity( + mContext, + notif.getNotificationId(), + notifIntent, + PendingIntent.FLAG_UPDATE_CURRENT); + + NotifiableMessage lastNotifiable = notif.getMessages().get(notif.getMessages().size() - 1); + String from = lastNotifiable.getSender(); + String message = lastNotifiable.getMessage(); + Bitmap bm = lastNotifiable.getSenderBitmap(); + if (notif.isGroup()) { + message = + mContext.getString(R.string.group_chat_notif) + .replace("%1", from) + .replace("%2", message); + from = notif.getGroupTitle(); + } + + Notification notification = + Compatibility.createMessageNotification( + mContext, notif, from, message, bm, pendingIntent); + sendNotification(notif.getNotificationId(), notification); + } + + private void displayReplyMessageNotification(ChatMessage msg, Notifiable notif) { + if (msg == null || notif == null) return; + Log.i( + "[Notifications Manager] Updating message notification with reply for notif " + + notif.getNotificationId()); + + NotifiableMessage notifMessage = + new NotifiableMessage( + msg.getTextContent(), + notif.getMyself(), + System.currentTimeMillis(), + null, + null); + notif.addMessage(notifMessage); + + ChatRoom cr = msg.getChatRoom(); + + displayMessageNotificationFromNotifiable( + notif, + cr.getPeerAddress().asStringUriOnly(), + cr.getLocalAddress().asStringUriOnly()); + } + public void displayGroupChatMessageNotification( String subject, String conferenceAddress, @@ -336,29 +444,8 @@ public class NotificationsManager { notif.setMyself(LinphoneUtils.getAddressDisplayName(localIdentity)); notif.setLocalIdentity(localIdentity.asString()); - Intent notifIntent = new Intent(mContext, ChatActivity.class); - notifIntent.putExtra("RemoteSipUri", conferenceAddress); - notifIntent.putExtra("LocalSipUri", localIdentity.asStringUriOnly()); - addFlagsToIntent(notifIntent); - - PendingIntent pendingIntent = - PendingIntent.getActivity( - mContext, - notif.getNotificationId(), - notifIntent, - PendingIntent.FLAG_UPDATE_CURRENT); - - Notification notification = - Compatibility.createMessageNotification( - mContext, - notif, - subject, - mContext.getString(R.string.group_chat_notif) - .replace("%1", fromName) - .replace("%2", message), - bm, - pendingIntent); - sendNotification(notif.getNotificationId(), notification); + displayMessageNotificationFromNotifiable( + notif, conferenceAddress, localIdentity.asStringUriOnly()); } public void displayMessageNotification( @@ -391,22 +478,8 @@ public class NotificationsManager { notif.setMyself(LinphoneUtils.getAddressDisplayName(localIdentity)); notif.setLocalIdentity(localIdentity.asString()); - Intent notifIntent = new Intent(mContext, ChatActivity.class); - notifIntent.putExtra("RemoteSipUri", fromSipUri); - notifIntent.putExtra("LocalSipUri", localIdentity.asStringUriOnly()); - addFlagsToIntent(notifIntent); - - PendingIntent pendingIntent = - PendingIntent.getActivity( - mContext, - notif.getNotificationId(), - notifIntent, - PendingIntent.FLAG_UPDATE_CURRENT); - - Notification notification = - Compatibility.createMessageNotification( - mContext, notif, fromName, message, bm, pendingIntent); - sendNotification(notif.getNotificationId(), notification); + displayMessageNotificationFromNotifiable( + notif, fromSipUri, localIdentity.asStringUriOnly()); } public void displayMissedCallNotification(Call call) { diff --git a/docker-files/bc-dev-android-28 b/docker-files/bc-dev-android-29 similarity index 91% rename from docker-files/bc-dev-android-28 rename to docker-files/bc-dev-android-29 index 6d3c8b4b7..9bd77760c 100644 --- a/docker-files/bc-dev-android-28 +++ b/docker-files/bc-dev-android-29 @@ -29,15 +29,15 @@ RUN wget https://dl.google.com/android/repository/tools_r$ANDROID_SDK-linux.zip ENV PATH $ANDROID_HOME/tools:$ANDROID_HOME/tools/bin:$ANDROID_HOME/platform-tools:$PATH # Get the Android SDK -RUN echo "y" | sdkmanager "platforms;android-28" "build-tools;28.0.3" "extras;android;m2repository" "extras;google;m2repository" "platform-tools" "tools" +RUN echo "y" | sdkmanager "platforms;android-29" "build-tools;29.0.2" "extras;android;m2repository" "extras;google;m2repository" "platform-tools" "tools" # Accept Android SDK licenses RUN yes | sdkmanager --licenses # Update if needed RUN echo y | android update sdk --no-ui --all --filter platform-tools -RUN echo y | android update sdk --no-ui --all --filter android-28 -RUN echo y | android update sdk --no-ui --all --filter build-tools-28.0.3 +RUN echo y | android update sdk --no-ui --all --filter android-29 +RUN echo y | android update sdk --no-ui --all --filter build-tools-29.0.2 # Configure user bc RUN useradd -ms /bin/bash bc && \