diff --git a/CHANGELOG.md b/CHANGELOG.md index 04b64d016..02d03013b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,7 +31,8 @@ Group changes to describe their impact on the project, as follows: - Support of H265 codec. - Use TextureView instead of GL2JNIView, easier to use and will fix issues. - Send SMS to invite your friends in using Linphone. -- Reply to received chat message in notification +- Reply to received chat message in notification. +- Answer or hangup incoming call in notification. ## [4.0.1] - 2018-06-26 diff --git a/app/src/main/java/org/linphone/LinphoneManager.java b/app/src/main/java/org/linphone/LinphoneManager.java index d51e20795..6ca687ea2 100644 --- a/app/src/main/java/org/linphone/LinphoneManager.java +++ b/app/src/main/java/org/linphone/LinphoneManager.java @@ -504,7 +504,7 @@ public class LinphoneManager implements CoreListener, SensorEventListener, Accou if (call != null) { call.enableCamera(enable); if (mServiceContext.getResources().getBoolean(R.bool.enable_call_notification)) - LinphoneService.instance().refreshIncallIcon(mLc.getCurrentCall()); + LinphoneService.instance().displayCallNotification(mLc.getCurrentCall()); } } diff --git a/app/src/main/java/org/linphone/LinphoneService.java b/app/src/main/java/org/linphone/LinphoneService.java index 29425945c..65933e308 100644 --- a/app/src/main/java/org/linphone/LinphoneService.java +++ b/app/src/main/java/org/linphone/LinphoneService.java @@ -82,17 +82,12 @@ public final class LinphoneService extends Service { */ public static final String START_LINPHONE_LOGS = " ==== Phone information dump ===="; public static final int IC_LEVEL_ORANGE = 0; - /*private static final int IC_LEVEL_GREEN=1; - private static final int IC_LEVEL_RED=2;*/ - //public static final int IC_LEVEL_OFFLINE=3; private static LinphoneService instance; private final static int NOTIF_ID = 1; - private final static int INCALL_NOTIF_ID = 2; private final static int CUSTOM_NOTIF_ID = 4; private final static int MISSED_NOTIF_ID = 5; - private final static int SAS_NOTIF_ID = 6; public static boolean isReady() { return instance != null && instance.mTestDelayElapsed; @@ -114,9 +109,7 @@ public final class LinphoneService extends Service { private NotificationManager mNM; private Notification mNotif; - private Notification mIncallNotif; private Notification mCustomNotif; - private Notification mSasNotif; private PendingIntent mNotifContentIntent; private String mNotificationTitle; private boolean mDisableRegistrationStatus; @@ -131,7 +124,7 @@ public final class LinphoneService extends Service { int numberOfUnreadMessage; } - private HashMap mChatNotifMap; + private HashMap mChatNotifMap, mCallNotifMap; private int mLastNotificationId; public void setCurrentlyDisplayedChatRoom(String address) { @@ -327,6 +320,10 @@ public final class LinphoneService extends Service { return; } + if (getResources().getBoolean(R.bool.enable_call_notification)) { + displayCallNotification(call); + } + if (state == Call.State.IncomingReceived) { if (!LinphoneManager.getInstance().getCallGsmON()) onIncomingReceived(); @@ -335,7 +332,6 @@ public final class LinphoneService extends Service { if (state == State.End || state == State.Released || state == State.Error) { if (LinphoneManager.isInstanciated() && LinphoneManager.getLc() != null && LinphoneManager.getLc().getCallsNb() == 0) { if (LinphoneActivity.isInstanciated() && LinphoneActivity.instance().getStatusFragment() != null) { - removeSasNotification(); LinphoneActivity.instance().getStatusFragment().setisZrtpAsk(false); } } @@ -367,15 +363,6 @@ public final class LinphoneService extends Service { Notification notif = Compatibility.createMissedCallNotification(instance, getString(R.string.missed_calls_notif_title), body, intent); notifyWrapper(MISSED_NOTIF_ID, notif); } - - if (state == State.StreamsRunning) { - // Workaround bug current call seems to be updated after state changed to streams running - if (getResources().getBoolean(R.bool.enable_call_notification)) - refreshIncallIcon(call); - } else { - if (getResources().getBoolean(R.bool.enable_call_notification)) - refreshIncallIcon(LinphoneManager.getLc().getCurrentCall()); - } } @Override @@ -387,10 +374,6 @@ public final class LinphoneService extends Service { @Override public void onRegistrationStateChanged(Core lc, ProxyConfig cfg, RegistrationState state, String smessage) { -// if (instance == null) { -// Log.i("Service not ready, discarding registration state change to ",state.toString()); -// return; -// } if (!mDisableRegistrationStatus) { if (displayServiceNotification() && state == RegistrationState.Ok && LinphoneManager.getLc().getDefaultProxyConfig() != null && LinphoneManager.getLc().getDefaultProxyConfig().getState() == RegistrationState.Ok) { sendNotification(IC_LEVEL_ORANGE, R.string.notification_registered); @@ -446,6 +429,7 @@ public final class LinphoneService extends Service { super.onCreate(); mLastNotificationId = 8; // To not interfere with other notifs ids mChatNotifMap = new HashMap<>(); + mCallNotifMap = new HashMap<>(); setupActivityMonitor(); // In case restart after a crash. Main in LinphoneActivity @@ -469,7 +453,7 @@ public final class LinphoneService extends Service { } mNM = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); - mNM.cancel(INCALL_NOTIF_ID); // in case of crash the icon is not removed + mNM.cancelAll(); Compatibility.createNotificationChannels(this); Intent notifIntent = new Intent(this, incomingReceivedActivity); @@ -521,85 +505,79 @@ public final class LinphoneService extends Service { mOverlay = null; } - private enum IncallIconState {INCALL, PAUSE, VIDEO, IDLE} + public void displayCallNotification(Call call) { + if (call == null) return; - private IncallIconState mCurrentIncallIconState = IncallIconState.IDLE; + Address address = call.getRemoteAddress(); + String addressAsString = address.asStringUriOnly(); + Notified notif = mCallNotifMap.get(addressAsString); - private synchronized void setIncallIcon(IncallIconState state) { - if (state == mCurrentIncallIconState) return; - mCurrentIncallIconState = state; + if (notif == null) { + notif = new Notified(); + notif.notificationId = mLastNotificationId; + mLastNotificationId += 1; + mCallNotifMap.put(addressAsString, notif); + } int notificationTextId = 0; int inconId = 0; - - switch (state) { - case IDLE: + switch (call.getState()) { + case Released: + case End: if (!displayServiceNotification()) { - stopForegroundCompat(INCALL_NOTIF_ID); + stopForegroundCompat(notif.notificationId); } else { - mNM.cancel(INCALL_NOTIF_ID); + mNM.cancel(notif.notificationId); } - return; - case INCALL: - inconId = R.drawable.topbar_call_notification; - notificationTextId = R.string.incall_notif_active; + mCallNotifMap.remove(addressAsString); break; - case PAUSE: + case Paused: + case PausedByRemote: + case Pausing: inconId = R.drawable.topbar_call_notification; notificationTextId = R.string.incall_notif_paused; break; - case VIDEO: - inconId = R.drawable.topbar_videocall_notification; - notificationTextId = R.string.incall_notif_video; - break; default: - throw new IllegalArgumentException("Unknown state " + state); + if (call.getCurrentParams().videoEnabled()) { + inconId = R.drawable.topbar_videocall_notification; + notificationTextId = R.string.incall_notif_video; + } else { + inconId = R.drawable.topbar_call_notification; + notificationTextId = R.string.incall_notif_active; + } + break; } - if (LinphoneManager.getLc().getCallsNb() == 0) { - return; - } - - Call call = LinphoneManager.getLc().getCalls()[0]; - Address address = call.getRemoteAddress(); - LinphoneContact contact = ContactsManager.getInstance().findContactFromAddress(address); Uri pictureUri = contact != null ? contact.getPhotoUri() : null; - Bitmap bm = null; + Bitmap bm; try { bm = MediaStore.Images.Media.getBitmap(getContentResolver(), pictureUri); } catch (Exception e) { bm = BitmapFactory.decodeResource(getResources(), R.drawable.avatar); } - String name = address.getDisplayName() == null ? address.getUsername() : address.getDisplayName(); + String name = LinphoneUtils.getAddressDisplayName(address); + + boolean showActions = call.getState() == State.IncomingReceived || call.getState() == State.IncomingEarlyMedia; Intent notifIntent = new Intent(this, incomingReceivedActivity); notifIntent.putExtra("Notification", true); mNotifContentIntent = PendingIntent.getActivity(this, 0, notifIntent, PendingIntent.FLAG_UPDATE_CURRENT); - mIncallNotif = Compatibility.createInCallNotification(getApplicationContext(), mNotificationTitle, getString(notificationTextId), inconId, bm, name, mNotifContentIntent); + Notification notification = Compatibility.createInCallNotification(getApplicationContext(), notif.notificationId, showActions, mNotificationTitle, getString(notificationTextId), inconId, bm, name, mNotifContentIntent); if (!displayServiceNotification()) { - startForegroundCompat(INCALL_NOTIF_ID, mIncallNotif); + startForegroundCompat(notif.notificationId, notification); } else { - notifyWrapper(INCALL_NOTIF_ID, mIncallNotif); + notifyWrapper(notif.notificationId, notification); } } - public void refreshIncallIcon(Call currentCall) { - Core lc = LinphoneManager.getLc(); - if (currentCall != null) { - if (currentCall.getCurrentParams().videoEnabled() && currentCall.cameraEnabled()) { - // checking first current params is mandatory - setIncallIcon(IncallIconState.VIDEO); - } else { - setIncallIcon(IncallIconState.INCALL); + public String getSipUriForCallNotificationId(int notificationId) { + for (String addr : mCallNotifMap.keySet()) { + if (mCallNotifMap.get(addr).notificationId == notificationId) { + return addr; } - } else if (lc.getCallsNb() == 0) { - setIncallIcon(IncallIconState.IDLE); - } else if (lc.getConference() != null) { - setIncallIcon(IncallIconState.INCALL); - } else { - setIncallIcon(IncallIconState.PAUSE); } + return null; } @Deprecated @@ -719,10 +697,6 @@ public final class LinphoneService extends Service { notifyWrapper(NOTIF_ID, mNotif); } - public void removeSasNotification() { - mNM.cancel(SAS_NOTIF_ID); - } - private static final Class[] mSetFgSign = new Class[]{boolean.class}; private static final Class[] mStartFgSign = new Class[]{ int.class, Notification.class}; @@ -884,11 +858,7 @@ public final class LinphoneService extends Service { // Make sure our notification is gone. stopForegroundCompat(NOTIF_ID); - mNM.cancel(INCALL_NOTIF_ID); - for (Notified notif : mChatNotifMap.values()) { - mNM.cancel(notif.notificationId); - } - + mNM.cancelAll(); // This will prevent the app from crashing if the service gets killed in background mode if (LinphoneActivity.isInstanciated()) { diff --git a/app/src/main/java/org/linphone/call/CallActivity.java b/app/src/main/java/org/linphone/call/CallActivity.java index bbc28d3bc..ca349132d 100644 --- a/app/src/main/java/org/linphone/call/CallActivity.java +++ b/app/src/main/java/org/linphone/call/CallActivity.java @@ -187,7 +187,6 @@ public class CallActivity extends LinphoneGenericActivity implements OnClickList public void onCallStateChanged(Core lc, final Call call, Call.State state, String message) { if (LinphoneManager.getLc().getCallsNb() == 0) { if (status != null) { - LinphoneService.instance().removeSasNotification(); status.setisZrtpAsk(false); } finish(); diff --git a/app/src/main/java/org/linphone/call/CallIncomingActivity.java b/app/src/main/java/org/linphone/call/CallIncomingActivity.java index 84aae45bf..4b4563583 100644 --- a/app/src/main/java/org/linphone/call/CallIncomingActivity.java +++ b/app/src/main/java/org/linphone/call/CallIncomingActivity.java @@ -22,6 +22,7 @@ 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.ActivityInfo; import android.content.pm.PackageManager; import android.os.Bundle; @@ -199,8 +200,9 @@ public class CallIncomingActivity extends LinphoneGenericActivity { public void onCallStateChanged(Core lc, Call call, State state, String message) { if (call == mCall && State.End == state) { finish(); - } - if (state == State.StreamsRunning) { + } else if (state == State.Connected) { + startActivity(new Intent(CallIncomingActivity.this, CallActivity.class)); + } else if (state == State.StreamsRunning) { Log.e("CallIncommingActivity - onCreate - State.StreamsRunning - speaker = " + LinphoneManager.getInstance().isSpeakerEnabled()); // The following should not be needed except some devices need it (e.g. Galaxy S). LinphoneManager.getInstance().enableSpeaker(LinphoneManager.getInstance().isSpeakerEnabled()); diff --git a/app/src/main/java/org/linphone/compatibility/ApiTwentyFourPlus.java b/app/src/main/java/org/linphone/compatibility/ApiTwentyFourPlus.java index b7b7dda75..7abea8c4f 100644 --- a/app/src/main/java/org/linphone/compatibility/ApiTwentyFourPlus.java +++ b/app/src/main/java/org/linphone/compatibility/ApiTwentyFourPlus.java @@ -16,7 +16,11 @@ import android.view.ViewTreeObserver; import org.linphone.R; import org.linphone.receivers.NotificationBroadcastReceiver; +import static org.linphone.compatibility.Compatibility.INTENT_ANSWER_CALL_NOTIF_ACTION; +import static org.linphone.compatibility.Compatibility.INTENT_CALL_ID; +import static org.linphone.compatibility.Compatibility.INTENT_HANGUP_CALL_NOTIF_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; /* @@ -42,12 +46,10 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. public class ApiTwentyFourPlus { public static Notification createRepliedNotification(Context context, String reply) { - Notification repliedNotification = new Notification.Builder(context) + return new Notification.Builder(context) .setSmallIcon(R.drawable.topbar_chat_notification) .setContentText(context.getString(R.string.notification_replied_label).replace("%s", reply)) .build(); - - return repliedNotification; } public static Notification createMessageNotification(Context context, int notificationId, int msgCount, String msgSender, String msg, Bitmap contactIcon, PendingIntent intent) { @@ -62,7 +64,7 @@ public class ApiTwentyFourPlus { RemoteInput remoteInput = new RemoteInput.Builder(KEY_TEXT_REPLY).setLabel(replyLabel).build(); Intent replyIntent = new Intent(context, NotificationBroadcastReceiver.class); - replyIntent.setAction(context.getPackageName() + ".REPLY_ACTION"); + replyIntent.setAction(INTENT_REPLY_NOTIF_ACTION); replyIntent.putExtra(INTENT_NOTIF_ID, notificationId); PendingIntent replyPendingIntent = PendingIntent.getBroadcast(context, @@ -71,10 +73,10 @@ public class ApiTwentyFourPlus { Notification.Action action = new Notification.Action.Builder(R.drawable.chat_send_over, context.getString(R.string.notification_reply_label), replyPendingIntent) .addRemoteInput(remoteInput) + .setAllowGeneratedReplies(true) .build(); - Notification notif; - notif = new Notification.Builder(context) + return new Notification.Builder(context) .setContentTitle(title) .setContentText(msg) .setSmallIcon(R.drawable.topbar_chat_notification) @@ -91,7 +93,44 @@ public class ApiTwentyFourPlus { .setColor(context.getColor(R.color.notification_color_led)) .addAction(action) .build(); - - return notif; } + + public static Notification createInCallNotification(Context context, + int callId, boolean showActions, String msg, int iconID, Bitmap contactIcon, String contactName, PendingIntent intent) { + + Notification.Builder builder = new Notification.Builder(context) + .setContentTitle(contactName) + .setContentText(msg) + .setSmallIcon(iconID) + .setAutoCancel(false) + .setContentIntent(intent) + .setLargeIcon(contactIcon) + .setCategory(Notification.CATEGORY_CALL) + .setVisibility(Notification.VISIBILITY_PUBLIC) + .setPriority(Notification.PRIORITY_HIGH) + .setWhen(System.currentTimeMillis()) + .setShowWhen(true) + .setColor(context.getColor(R.color.notification_color_led)); + + if (showActions) { + Intent hangupIntent = new Intent(context, NotificationBroadcastReceiver.class); + hangupIntent.setAction(INTENT_HANGUP_CALL_NOTIF_ACTION); + hangupIntent.putExtra(INTENT_CALL_ID, callId); + + PendingIntent hangupPendingIntent = PendingIntent.getBroadcast(context, + callId, hangupIntent, PendingIntent.FLAG_UPDATE_CURRENT); + + Intent answerIntent = new Intent(context, NotificationBroadcastReceiver.class); + answerIntent.setAction(INTENT_ANSWER_CALL_NOTIF_ACTION); + answerIntent.putExtra(INTENT_CALL_ID, callId); + + PendingIntent answerPendingIntent = PendingIntent.getBroadcast(context, + callId, answerIntent, PendingIntent.FLAG_UPDATE_CURRENT); + + builder.addAction(R.drawable.call_hangup, context.getString(R.string.notification_call_hangup_label), hangupPendingIntent); + builder.addAction(R.drawable.call_audio_start, context.getString(R.string.notification_call_answer_label), answerPendingIntent); + } + + return builder.build(); + } } diff --git a/app/src/main/java/org/linphone/compatibility/ApiTwentySixPlus.java b/app/src/main/java/org/linphone/compatibility/ApiTwentySixPlus.java index eede346c8..7e549c1e9 100644 --- a/app/src/main/java/org/linphone/compatibility/ApiTwentySixPlus.java +++ b/app/src/main/java/org/linphone/compatibility/ApiTwentySixPlus.java @@ -17,7 +17,11 @@ import org.linphone.R; import org.linphone.mediastream.Log; import org.linphone.receivers.NotificationBroadcastReceiver; +import static org.linphone.compatibility.Compatibility.INTENT_ANSWER_CALL_NOTIF_ACTION; +import static org.linphone.compatibility.Compatibility.INTENT_CALL_ID; +import static org.linphone.compatibility.Compatibility.INTENT_HANGUP_CALL_NOTIF_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; /* @@ -42,12 +46,10 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @TargetApi(26) public class ApiTwentySixPlus { public static Notification createRepliedNotification(Context context, String reply) { - Notification repliedNotification = new Notification.Builder(context, context.getString(R.string.notification_channel_id)) + return new Notification.Builder(context, context.getString(R.string.notification_channel_id)) .setSmallIcon(R.drawable.topbar_chat_notification) .setContentText(context.getString(R.string.notification_replied_label).replace("%s", reply)) .build(); - - return repliedNotification; } public static void createServiceChannel(Context context) { @@ -93,7 +95,7 @@ public class ApiTwentySixPlus { RemoteInput remoteInput = new RemoteInput.Builder(KEY_TEXT_REPLY).setLabel(replyLabel).build(); Intent replyIntent = new Intent(context, NotificationBroadcastReceiver.class); - replyIntent.setAction(context.getPackageName() + ".REPLY_ACTION"); + replyIntent.setAction(INTENT_REPLY_NOTIF_ACTION); replyIntent.putExtra(INTENT_NOTIF_ID, notificationId); PendingIntent replyPendingIntent = PendingIntent.getBroadcast(context, @@ -102,10 +104,10 @@ public class ApiTwentySixPlus { Notification.Action action = new Notification.Action.Builder(R.drawable.chat_send_over, context.getString(R.string.notification_reply_label), replyPendingIntent) .addRemoteInput(remoteInput) + .setAllowGeneratedReplies(true) .build(); - Notification notif; - notif = new Notification.Builder(context, context.getString(R.string.notification_channel_id)) + return new Notification.Builder(context, context.getString(R.string.notification_channel_id)) .setContentTitle(title) .setContentText(msg) .setSmallIcon(R.drawable.topbar_chat_notification) @@ -122,15 +124,12 @@ public class ApiTwentySixPlus { .setColor(context.getColor(R.color.notification_color_led)) .addAction(action) .build(); - - return notif; } public static Notification createInCallNotification(Context context, - String title, String msg, int iconID, Bitmap contactIcon, - String contactName, PendingIntent intent) { + int callId, boolean showActions, String msg, int iconID, Bitmap contactIcon, String contactName, PendingIntent intent) { - Notification notif = new Notification.Builder(context, context.getString(R.string.notification_service_channel_id)) + Notification.Builder builder = new Notification.Builder(context, context.getString(R.string.notification_service_channel_id)) .setContentTitle(contactName) .setContentText(msg) .setSmallIcon(iconID) @@ -142,17 +141,35 @@ public class ApiTwentySixPlus { .setPriority(Notification.PRIORITY_HIGH) .setWhen(System.currentTimeMillis()) .setShowWhen(true) - .setColor(context.getColor(R.color.notification_color_led)) - .build(); + .setColor(context.getColor(R.color.notification_color_led)); - return notif; + if (showActions) { + + Intent hangupIntent = new Intent(context, NotificationBroadcastReceiver.class); + hangupIntent.setAction(INTENT_HANGUP_CALL_NOTIF_ACTION); + hangupIntent.putExtra(INTENT_CALL_ID, callId); + + PendingIntent hangupPendingIntent = PendingIntent.getBroadcast(context, + callId, hangupIntent, PendingIntent.FLAG_UPDATE_CURRENT); + + Intent answerIntent = new Intent(context, NotificationBroadcastReceiver.class); + answerIntent.setAction(INTENT_ANSWER_CALL_NOTIF_ACTION); + answerIntent.putExtra(INTENT_CALL_ID, callId); + + PendingIntent answerPendingIntent = PendingIntent.getBroadcast(context, + callId, answerIntent, PendingIntent.FLAG_UPDATE_CURRENT); + + builder.addAction(R.drawable.call_hangup, context.getString(R.string.notification_call_hangup_label), hangupPendingIntent); + builder.addAction(R.drawable.call_audio_start, context.getString(R.string.notification_call_answer_label), answerPendingIntent); + } + return builder.build(); } - public static Notification createNotification(Context context, String title, String message, int icon, int level, Bitmap largeIcon, PendingIntent intent, boolean isOngoingEvent,int priority) { - Notification notif; + public static Notification createNotification(Context context, String title, String message, int icon, int level, + Bitmap largeIcon, PendingIntent intent, boolean isOngoingEvent,int priority) { if (largeIcon != null) { - notif = new Notification.Builder(context, context.getString(R.string.notification_service_channel_id)) + return new Notification.Builder(context, context.getString(R.string.notification_service_channel_id)) .setContentTitle(title) .setContentText(message) .setSmallIcon(icon, level) @@ -166,7 +183,7 @@ public class ApiTwentySixPlus { .setColor(context.getColor(R.color.notification_color_led)) .build(); } else { - notif = new Notification.Builder(context, context.getString(R.string.notification_service_channel_id)) + return new Notification.Builder(context, context.getString(R.string.notification_service_channel_id)) .setContentTitle(title) .setContentText(message) .setSmallIcon(icon, level) @@ -179,16 +196,10 @@ public class ApiTwentySixPlus { .setColor(context.getColor(R.color.notification_color_led)) .build(); } - - return notif; - } - - public static void removeGlobalLayoutListener(ViewTreeObserver viewTreeObserver, ViewTreeObserver.OnGlobalLayoutListener keyboardListener) { - viewTreeObserver.removeOnGlobalLayoutListener(keyboardListener); } public static Notification createMissedCallNotification(Context context, String title, String text, PendingIntent intent) { - Notification notif = new Notification.Builder(context, context.getString(R.string.notification_channel_id)) + return new Notification.Builder(context, context.getString(R.string.notification_channel_id)) .setContentTitle(title) .setContentText(text) .setSmallIcon(R.drawable.call_status_missed) @@ -203,12 +214,10 @@ public class ApiTwentySixPlus { .setShowWhen(true) .setColor(context.getColor(R.color.notification_color_led)) .build(); - - return notif; } public static Notification createSimpleNotification(Context context, String title, String text, PendingIntent intent) { - Notification notif = new Notification.Builder(context, context.getString(R.string.notification_channel_id)) + return new Notification.Builder(context, context.getString(R.string.notification_channel_id)) .setContentTitle(title) .setContentText(text) .setSmallIcon(R.drawable.linphone_logo) @@ -224,8 +233,6 @@ public class ApiTwentySixPlus { .setColorized(true) .setColor(context.getColor(R.color.notification_color_led)) .build(); - - return notif; } public static void startService(Context context, Intent intent) { diff --git a/app/src/main/java/org/linphone/compatibility/Compatibility.java b/app/src/main/java/org/linphone/compatibility/Compatibility.java index 7c86bb17e..aaa055d4e 100644 --- a/app/src/main/java/org/linphone/compatibility/Compatibility.java +++ b/app/src/main/java/org/linphone/compatibility/Compatibility.java @@ -39,6 +39,10 @@ import org.linphone.mediastream.Version; public class Compatibility { public static final String KEY_TEXT_REPLY = "key_text_reply"; public static final String INTENT_NOTIF_ID = "NOTIFICATION_ID"; + public static final String INTENT_CALL_ID = "CALL_ID"; + public static final String INTENT_REPLY_NOTIF_ACTION = "org.linphone.REPLY_ACTION"; + public static final String INTENT_HANGUP_CALL_NOTIF_ACTION = "org.linphone.HANGUP_CALL_ACTION"; + public static final String INTENT_ANSWER_CALL_NOTIF_ACTION = "org.linphone.ANSWER_CALL_ACTION"; public static void createNotificationChannels(Context context) { if (Version.sdkAboveOrEqual(Version.API26_O_80)) { @@ -94,9 +98,11 @@ public class Compatibility { return null; } - public static Notification createInCallNotification(Context context, String title, String msg, int iconID, Bitmap contactIcon, String contactName, PendingIntent intent) { + public static Notification createInCallNotification(Context context, int callId, boolean showActions, String title, String msg, int iconID, Bitmap contactIcon, String contactName, PendingIntent intent) { if (Version.sdkAboveOrEqual(Version.API26_O_80)) { - return ApiTwentySixPlus.createInCallNotification(context, title, msg, iconID, contactIcon, contactName, intent); + return ApiTwentySixPlus.createInCallNotification(context, callId, showActions, msg, iconID, contactIcon, contactName, intent); + } else if (Version.sdkAboveOrEqual(Version.API24_NOUGAT_70)) { + return ApiTwentyFourPlus.createInCallNotification(context, callId, showActions, msg, iconID, contactIcon, contactName, intent); } else if (Version.sdkAboveOrEqual(Version.API21_LOLLIPOP_50)) { return ApiTwentyOnePlus.createInCallNotification(context, title, msg, iconID, contactIcon, contactName, intent); } else if (Version.sdkAboveOrEqual(Version.API16_JELLY_BEAN_41)) { diff --git a/app/src/main/java/org/linphone/fragments/StatusFragment.java b/app/src/main/java/org/linphone/fragments/StatusFragment.java index 7c4c33fce..fdf2ec72b 100644 --- a/app/src/main/java/org/linphone/fragments/StatusFragment.java +++ b/app/src/main/java/org/linphone/fragments/StatusFragment.java @@ -463,7 +463,6 @@ public class StatusFragment extends Fragment { } isZrtpAsk = false; ZRTPdialog.dismiss(); - LinphoneService.instance().removeSasNotification(); } }); @@ -476,7 +475,6 @@ public class StatusFragment extends Fragment { } isZrtpAsk = false; ZRTPdialog.dismiss(); - LinphoneService.instance().removeSasNotification(); } }); ZRTPdialog.show(); diff --git a/app/src/main/java/org/linphone/receivers/NotificationBroadcastReceiver.java b/app/src/main/java/org/linphone/receivers/NotificationBroadcastReceiver.java index 40c98c7fb..e13d4eaf7 100644 --- a/app/src/main/java/org/linphone/receivers/NotificationBroadcastReceiver.java +++ b/app/src/main/java/org/linphone/receivers/NotificationBroadcastReceiver.java @@ -31,36 +31,52 @@ import org.linphone.LinphoneManager; import org.linphone.LinphoneService; import org.linphone.compatibility.Compatibility; import org.linphone.core.Address; +import org.linphone.core.Call; import org.linphone.core.ChatMessage; import org.linphone.core.ChatRoom; import org.linphone.core.Core; import org.linphone.core.ProxyConfig; +import org.linphone.core.Reason; public class NotificationBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { - String reply = getMessageText(intent).toString(); - if (reply != null) { + if (intent.getAction() == Compatibility.INTENT_REPLY_NOTIF_ACTION) { + String reply = getMessageText(intent).toString(); + if (reply == null) return; Notification replied = Compatibility.createRepliedNotification(context, reply); - if (replied != null) { - int notifId = intent.getIntExtra(Compatibility.INTENT_NOTIF_ID, 0); - String remoteSipAddr = LinphoneService.instance().getSipUriForNotificationId(notifId); + if (replied == null) return; + int notifId = intent.getIntExtra(Compatibility.INTENT_NOTIF_ID, 0); + String remoteSipAddr = LinphoneService.instance().getSipUriForNotificationId(notifId); - Core core = LinphoneManager.getLc(); - if (core == null) return; - ProxyConfig proxyConfig = core.getDefaultProxyConfig(); - if (proxyConfig == null) return; - Address localAddr = proxyConfig.getIdentityAddress(); - Address remoteAddr = core.interpretUrl(remoteSipAddr); - if (localAddr == null || remoteAddr == null) return; - ChatRoom room = core.findChatRoom(remoteAddr, localAddr); - if (room == null) return; + Core core = LinphoneManager.getLc(); + if (core == null) return; + ProxyConfig proxyConfig = core.getDefaultProxyConfig(); + if (proxyConfig == null) return; + Address localAddr = proxyConfig.getIdentityAddress(); + Address remoteAddr = core.interpretUrl(remoteSipAddr); + if (localAddr == null || remoteAddr == null) return; + ChatRoom room = core.findChatRoom(remoteAddr, localAddr); + if (room == null) return; - room.markAsRead(); - ChatMessage msg = room.createMessage(reply); - msg.send(); + room.markAsRead(); + ChatMessage msg = room.createMessage(reply); + msg.send(); - LinphoneService.instance().sendNotification(replied, notifId); + LinphoneService.instance().sendNotification(replied, notifId); + } else if (intent.getAction() == Compatibility.INTENT_ANSWER_CALL_NOTIF_ACTION || intent.getAction() == Compatibility.INTENT_HANGUP_CALL_NOTIF_ACTION) { + int callId = intent.getIntExtra(Compatibility.INTENT_CALL_ID, 0); + String remoteAddr = LinphoneService.instance().getSipUriForCallNotificationId(callId); + + Core core = LinphoneManager.getLc(); + if (core == null) return; + Call call = core.findCallFromUri(remoteAddr); + if (call == null) return; + + if (intent.getAction() == Compatibility.INTENT_ANSWER_CALL_NOTIF_ACTION) { + call.accept(); + } else { + call.decline(Reason.None); } } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 45cba8ff4..b7def490e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -18,6 +18,8 @@ Reply Sent reply: %s + Hangup + Answer Username