Cleaned LinphoneService a bit, moved all notifications related code to another class
This commit is contained in:
parent
886b5a36c0
commit
1e6fb279c0
22 changed files with 595 additions and 525 deletions
|
@ -294,7 +294,7 @@
|
|||
<activity android:name=".activities.LinphoneGenericActivity"/>
|
||||
|
||||
<receiver
|
||||
android:name=".receivers.NotificationBroadcastReceiver"
|
||||
android:name=".notifications.NotificationBroadcastReceiver"
|
||||
android:enabled="true"
|
||||
android:exported="false" />
|
||||
|
||||
|
|
|
@ -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().displayCallNotification(mLc.getCurrentCall());
|
||||
LinphoneService.instance().getNotificationManager().displayCallNotification(mLc.getCurrentCall());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1075,16 +1075,16 @@ public class LinphoneManager implements CoreListener, SensorEventListener, Accou
|
|||
if (!mServiceContext.getResources().getBoolean(R.bool.disable_chat_message_notification) && !message.isOutgoing()) {
|
||||
if (cr.hasCapability(ChatRoomCapabilities.OneToOne.toInt())) {
|
||||
if (contact != null) {
|
||||
LinphoneService.instance().displayMessageNotification(cr.getPeerAddress().asStringUriOnly(), contact.getFullName(), contact.getThumbnailUri(), textMessage, cr.getLocalAddress().asString());
|
||||
LinphoneService.instance().getNotificationManager().displayMessageNotification(cr.getPeerAddress().asStringUriOnly(), contact.getFullName(), contact.getThumbnailUri(), textMessage, cr.getLocalAddress());
|
||||
} else {
|
||||
LinphoneService.instance().displayMessageNotification(cr.getPeerAddress().asStringUriOnly(), from.getUsername(), null, textMessage, cr.getLocalAddress().asString());
|
||||
LinphoneService.instance().getNotificationManager().displayMessageNotification(cr.getPeerAddress().asStringUriOnly(), from.getUsername(), null, textMessage, cr.getLocalAddress());
|
||||
}
|
||||
} else {
|
||||
String subject = cr.getSubject();
|
||||
if (contact != null) {
|
||||
LinphoneService.instance().displayGroupChatMessageNotification(subject, cr.getPeerAddress().asStringUriOnly(), contact.getFullName(), contact.getThumbnailUri(), textMessage, cr.getLocalAddress().asString());
|
||||
LinphoneService.instance().getNotificationManager().displayGroupChatMessageNotification(subject, cr.getPeerAddress().asStringUriOnly(), contact.getFullName(), contact.getThumbnailUri(), textMessage, cr.getLocalAddress());
|
||||
} else {
|
||||
LinphoneService.instance().displayGroupChatMessageNotification(subject, cr.getPeerAddress().asStringUriOnly(), from.getUsername(), null, textMessage, cr.getLocalAddress().asString());
|
||||
LinphoneService.instance().getNotificationManager().displayGroupChatMessageNotification(subject, cr.getPeerAddress().asStringUriOnly(), from.getUsername(), null, textMessage, cr.getLocalAddress());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,31 +23,22 @@ import android.annotation.TargetApi;
|
|||
import android.app.Activity;
|
||||
import android.app.AlarmManager;
|
||||
import android.app.Application;
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.SystemClock;
|
||||
import android.provider.ContactsContract;
|
||||
import android.provider.MediaStore;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import org.linphone.activities.LinphoneActivity;
|
||||
import org.linphone.compatibility.Compatibility;
|
||||
import org.linphone.contacts.ContactsManager;
|
||||
import org.linphone.contacts.LinphoneContact;
|
||||
import org.linphone.core.Address;
|
||||
import org.linphone.core.Call;
|
||||
import org.linphone.core.Call.State;
|
||||
import org.linphone.core.Core;
|
||||
|
@ -58,14 +49,12 @@ import org.linphone.core.ProxyConfig;
|
|||
import org.linphone.core.RegistrationState;
|
||||
import org.linphone.mediastream.Log;
|
||||
import org.linphone.mediastream.Version;
|
||||
import org.linphone.notifications.NotificationsManager;
|
||||
import org.linphone.receivers.BluetoothManager;
|
||||
import org.linphone.receivers.KeepAliveReceiver;
|
||||
import org.linphone.ui.LinphoneOverlay;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* Linphone service, reacting to Incoming calls, ...<br />
|
||||
|
@ -81,14 +70,9 @@ public final class LinphoneService extends Service {
|
|||
* setLatestEventInfo and startActivity() which needs a context.
|
||||
*/
|
||||
public static final String START_LINPHONE_LOGS = " ==== Phone information dump ====";
|
||||
public static final int IC_LEVEL_ORANGE = 0;
|
||||
|
||||
private static LinphoneService instance;
|
||||
|
||||
private final static int NOTIF_ID = 1;
|
||||
private final static int CUSTOM_NOTIF_ID = 4;
|
||||
private final static int MISSED_NOTIF_ID = 5;
|
||||
|
||||
public static boolean isReady() {
|
||||
return instance != null && instance.mTestDelayElapsed;
|
||||
}
|
||||
|
@ -106,38 +90,28 @@ public final class LinphoneService extends Service {
|
|||
|
||||
// private boolean mTestDelayElapsed; // add a timer for testing
|
||||
private boolean mTestDelayElapsed = true; // no timer
|
||||
private NotificationManager mNM;
|
||||
|
||||
private Notification mNotif;
|
||||
private Notification mCustomNotif;
|
||||
private PendingIntent mNotifContentIntent;
|
||||
private String mNotificationTitle;
|
||||
private boolean mDisableRegistrationStatus;
|
||||
private CoreListenerStub mListener;
|
||||
public static int notifcationsPriority = (Version.sdkAboveOrEqual(Version.API16_JELLY_BEAN_41) ? Notification.PRIORITY_MIN : 0);
|
||||
private WindowManager mWindowManager;
|
||||
private LinphoneOverlay mOverlay;
|
||||
private Application.ActivityLifecycleCallbacks activityCallbacks;
|
||||
|
||||
private class Notified {
|
||||
int notificationId;
|
||||
int numberOfUnreadMessage;
|
||||
private NotificationsManager mNotificationManager;
|
||||
|
||||
public NotificationsManager getNotificationManager() {
|
||||
return mNotificationManager;
|
||||
}
|
||||
|
||||
private HashMap<String, Notified> mChatNotifMap, mCallNotifMap;
|
||||
private int mLastNotificationId;
|
||||
private String incomingReceivedActivityName;
|
||||
private Class<? extends Activity> incomingReceivedActivity = LinphoneActivity.class;
|
||||
|
||||
public Class<? extends Activity> getIncomingReceivedActivity() {
|
||||
return incomingReceivedActivity;
|
||||
}
|
||||
|
||||
public void setCurrentlyDisplayedChatRoom(String address) {
|
||||
if (address != null) {
|
||||
resetMessageNotifCount(address);
|
||||
}
|
||||
}
|
||||
|
||||
private void resetMessageNotifCount(String address) {
|
||||
Notified notif = mChatNotifMap.get(address);
|
||||
if (notif != null) {
|
||||
notif.numberOfUnreadMessage = 0;
|
||||
mNM.cancel(notif.notificationId);
|
||||
mNotificationManager.resetMessageNotifCount(address);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -169,8 +143,6 @@ public final class LinphoneService extends Service {
|
|||
}
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
private InactivityChecker mLastChecker;
|
||||
|
||||
@Override
|
||||
|
@ -275,31 +247,6 @@ public final class LinphoneService extends Service {
|
|||
getApplication().registerActivityLifecycleCallbacks(activityCallbacks = new ActivityMonitor());
|
||||
}
|
||||
|
||||
public boolean displayServiceNotification() {
|
||||
return LinphonePreferences.instance().getServiceNotificationVisibility();
|
||||
}
|
||||
|
||||
public void showServiceNotification() {
|
||||
startForegroundCompat(NOTIF_ID, mNotif);
|
||||
|
||||
Core lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
|
||||
if (lc == null) return;
|
||||
ProxyConfig lpc = lc.getDefaultProxyConfig();
|
||||
if (lpc != null) {
|
||||
if (lpc.getState() == RegistrationState.Ok) {
|
||||
sendNotification(IC_LEVEL_ORANGE, R.string.notification_registered);
|
||||
} else {
|
||||
sendNotification(IC_LEVEL_ORANGE, R.string.notification_register_failure);
|
||||
}
|
||||
} else {
|
||||
sendNotification(IC_LEVEL_ORANGE, R.string.notification_started);
|
||||
}
|
||||
}
|
||||
|
||||
public void hideServiceNotification() {
|
||||
stopForegroundCompat(NOTIF_ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
super.onStartCommand(intent, flags, startId);
|
||||
|
@ -309,9 +256,10 @@ public final class LinphoneService extends Service {
|
|||
return START_REDELIVER_INTENT;
|
||||
}
|
||||
|
||||
LinphoneManager.createAndStart(LinphoneService.this);
|
||||
LinphoneManager.createAndStart(this);
|
||||
|
||||
instance = this; // instance is ready once linphone manager has been created
|
||||
mNotificationManager = new NotificationsManager(this);
|
||||
LinphoneManager.getLc().addListener(mListener = new CoreListenerStub() {
|
||||
@Override
|
||||
public void onCallStateChanged(Core lc, Call call, Call.State state, String message) {
|
||||
|
@ -321,7 +269,7 @@ public final class LinphoneService extends Service {
|
|||
}
|
||||
|
||||
if (getResources().getBoolean(R.bool.enable_call_notification)) {
|
||||
displayCallNotification(call);
|
||||
mNotificationManager.displayCallNotification(call);
|
||||
}
|
||||
|
||||
if (state == Call.State.IncomingReceived) {
|
||||
|
@ -339,58 +287,23 @@ public final class LinphoneService extends Service {
|
|||
}
|
||||
|
||||
if (state == State.End && call.getCallLog().getStatus() == Call.Status.Missed) {
|
||||
int missedCallCount = LinphoneManager.getLcIfManagerNotDestroyedOrNull().getMissedCallsCount();
|
||||
String body;
|
||||
if (missedCallCount > 1) {
|
||||
body = getString(R.string.missed_calls_notif_body).replace("%i", String.valueOf(missedCallCount));
|
||||
} else {
|
||||
Address address = call.getRemoteAddress();
|
||||
LinphoneContact c = ContactsManager.getInstance().findContactFromAddress(address);
|
||||
if (c != null) {
|
||||
body = c.getFullName();
|
||||
} else {
|
||||
body = address.getDisplayName();
|
||||
if (body == null) {
|
||||
body = address.asStringUriOnly();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Intent missedCallNotifIntent = new Intent(LinphoneService.this, incomingReceivedActivity);
|
||||
missedCallNotifIntent.putExtra("GoToHistory", true);
|
||||
PendingIntent intent = PendingIntent.getActivity(LinphoneService.this, 0, missedCallNotifIntent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
Notification notif = Compatibility.createMissedCallNotification(instance, getString(R.string.missed_calls_notif_title), body, intent);
|
||||
notifyWrapper(MISSED_NOTIF_ID, notif);
|
||||
mNotificationManager.displayMissedCallNotification(call);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGlobalStateChanged(Core lc, GlobalState state, String message) {
|
||||
if (!mDisableRegistrationStatus && state == GlobalState.On && displayServiceNotification()) {
|
||||
sendNotification(IC_LEVEL_ORANGE, R.string.notification_started);
|
||||
}
|
||||
//TODO global state if ON
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRegistrationStateChanged(Core lc, ProxyConfig cfg, RegistrationState state, String smessage) {
|
||||
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);
|
||||
}
|
||||
|
||||
if (displayServiceNotification() && (state == RegistrationState.Failed || state == RegistrationState.Cleared) && (LinphoneManager.getLc().getDefaultProxyConfig() == null || !(LinphoneManager.getLc().getDefaultProxyConfig().getState() == RegistrationState.Ok))) {
|
||||
sendNotification(IC_LEVEL_ORANGE, R.string.notification_register_failure);
|
||||
}
|
||||
|
||||
if (displayServiceNotification() && state == RegistrationState.None) {
|
||||
sendNotification(IC_LEVEL_ORANGE, R.string.notification_started);
|
||||
}
|
||||
}
|
||||
//TODO registration status
|
||||
}
|
||||
});
|
||||
|
||||
if (displayServiceNotification() || (Version.sdkAboveOrEqual(Version.API26_O_80) && intent.getBooleanExtra("ForceStartForeground", false))) {
|
||||
startForegroundCompat(NOTIF_ID, mNotif);
|
||||
if (Version.sdkAboveOrEqual(Version.API26_O_80) && intent.getBooleanExtra("ForceStartForeground", false)) {
|
||||
mNotificationManager.startForeground();
|
||||
}
|
||||
|
||||
if (!Version.sdkAboveOrEqual(Version.API26_O_80)
|
||||
|
@ -426,13 +339,8 @@ public final class LinphoneService extends Service {
|
|||
@Override
|
||||
public void onCreate() {
|
||||
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
|
||||
mNotificationTitle = getString(R.string.service_name);
|
||||
|
||||
// Needed in order for the two next calls to succeed, libraries must have been loaded first
|
||||
LinphonePreferences.instance().setContext(getBaseContext());
|
||||
|
@ -445,27 +353,6 @@ public final class LinphoneService extends Service {
|
|||
dumpDeviceInformation();
|
||||
dumpInstalledLinphoneInformation();
|
||||
|
||||
//Disable service notification for Android O
|
||||
if ((Version.sdkAboveOrEqual(Version.API26_O_80))) {
|
||||
LinphonePreferences.instance().setServiceNotificationVisibility(false);
|
||||
mDisableRegistrationStatus = true;
|
||||
}
|
||||
|
||||
mNM = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
|
||||
mNM.cancelAll();
|
||||
Compatibility.createNotificationChannels(this);
|
||||
|
||||
Intent notifIntent = new Intent(this, incomingReceivedActivity);
|
||||
notifIntent.putExtra("Notification", true);
|
||||
mNotifContentIntent = PendingIntent.getActivity(this, 0, notifIntent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
|
||||
Bitmap bm = null;
|
||||
try {
|
||||
bm = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
mNotif = Compatibility.createNotification(this, mNotificationTitle, "", R.drawable.linphone_notification_icon, R.mipmap.ic_launcher, bm, mNotifContentIntent, true, notifcationsPriority);
|
||||
|
||||
incomingReceivedActivityName = LinphonePreferences.instance().getActivityToLaunchOnIncomingReceived();
|
||||
try {
|
||||
incomingReceivedActivity = (Class<? extends Activity>) Class.forName(incomingReceivedActivityName);
|
||||
|
@ -473,13 +360,6 @@ public final class LinphoneService extends Service {
|
|||
Log.e(e);
|
||||
}
|
||||
|
||||
try {
|
||||
mStartForeground = getClass().getMethod("startForeground", mStartFgSign);
|
||||
mStopForeground = getClass().getMethod("stopForeground", mStopFgSign);
|
||||
} catch (NoSuchMethodException e) {
|
||||
Log.e(e, "Couldn't find startForeground or stopForeground");
|
||||
}
|
||||
|
||||
mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
|
||||
}
|
||||
|
||||
|
@ -504,249 +384,6 @@ public final class LinphoneService extends Service {
|
|||
mOverlay = null;
|
||||
}
|
||||
|
||||
public void displayCallNotification(Call call) {
|
||||
if (call == null) return;
|
||||
|
||||
Address address = call.getRemoteAddress();
|
||||
String addressAsString = address.asStringUriOnly();
|
||||
Notified notif = mCallNotifMap.get(addressAsString);
|
||||
if (notif == null) {
|
||||
notif = new Notified();
|
||||
notif.notificationId = mLastNotificationId;
|
||||
mLastNotificationId += 1;
|
||||
mCallNotifMap.put(addressAsString, notif);
|
||||
}
|
||||
|
||||
if (!displayServiceNotification()) {
|
||||
if (call.getCore().getCallsNb() == 0) {
|
||||
hideServiceNotification();
|
||||
} else {
|
||||
showServiceNotification();
|
||||
}
|
||||
}
|
||||
|
||||
int notificationTextId;
|
||||
int iconId;
|
||||
switch (call.getState()) {
|
||||
case Released:
|
||||
case End:
|
||||
mNM.cancel(notif.notificationId);
|
||||
mCallNotifMap.remove(addressAsString);
|
||||
return;
|
||||
case Paused:
|
||||
case PausedByRemote:
|
||||
case Pausing:
|
||||
iconId = R.drawable.topbar_call_notification;
|
||||
notificationTextId = R.string.incall_notif_paused;
|
||||
break;
|
||||
default:
|
||||
if (call.getCurrentParams().videoEnabled()) {
|
||||
iconId = R.drawable.topbar_videocall_notification;
|
||||
notificationTextId = R.string.incall_notif_video;
|
||||
} else {
|
||||
iconId = R.drawable.topbar_call_notification;
|
||||
notificationTextId = R.string.incall_notif_active;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
LinphoneContact contact = ContactsManager.getInstance().findContactFromAddress(address);
|
||||
Uri pictureUri = contact != null ? contact.getPhotoUri() : null;
|
||||
Bitmap bm;
|
||||
try {
|
||||
bm = MediaStore.Images.Media.getBitmap(getContentResolver(), pictureUri);
|
||||
} catch (Exception e) {
|
||||
bm = BitmapFactory.decodeResource(getResources(), R.drawable.avatar);
|
||||
}
|
||||
String name = LinphoneUtils.getAddressDisplayName(address);
|
||||
|
||||
boolean showAnswerAction = 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);
|
||||
Notification notification = Compatibility.createInCallNotification(getApplicationContext(), notif.notificationId, showAnswerAction, mNotificationTitle, getString(notificationTextId), iconId, bm, name, mNotifContentIntent);
|
||||
|
||||
notifyWrapper(notif.notificationId, notification);
|
||||
}
|
||||
|
||||
public String getSipUriForCallNotificationId(int notificationId) {
|
||||
for (String addr : mCallNotifMap.keySet()) {
|
||||
if (mCallNotifMap.get(addr).notificationId == notificationId) {
|
||||
return addr;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void addNotification(Intent onClickIntent, int iconResourceID, String title, String message) {
|
||||
addCustomNotification(onClickIntent, iconResourceID, title, message, true);
|
||||
}
|
||||
|
||||
public void addCustomNotification(Intent onClickIntent, int iconResourceID, String title, String message, boolean isOngoingEvent) {
|
||||
PendingIntent notifContentIntent = PendingIntent.getActivity(this, 0, onClickIntent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
|
||||
Bitmap bm = null;
|
||||
try {
|
||||
bm = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
mCustomNotif = Compatibility.createNotification(this, title, message, iconResourceID, 0, bm, notifContentIntent, isOngoingEvent, notifcationsPriority);
|
||||
|
||||
mCustomNotif.defaults |= Notification.DEFAULT_VIBRATE;
|
||||
mCustomNotif.defaults |= Notification.DEFAULT_SOUND;
|
||||
mCustomNotif.defaults |= Notification.DEFAULT_LIGHTS;
|
||||
|
||||
notifyWrapper(CUSTOM_NOTIF_ID, mCustomNotif);
|
||||
}
|
||||
|
||||
public void displayGroupChatMessageNotification(String subject, String conferenceAddress, String fromName, Uri fromPictureUri, String message, String localIdentity) {
|
||||
Intent notifIntent = new Intent(this, LinphoneActivity.class);
|
||||
notifIntent.putExtra("GoToChat", true);
|
||||
notifIntent.putExtra("ChatContactSipUri", conferenceAddress);
|
||||
notifIntent.putExtra("LocalIdentity", localIdentity);
|
||||
|
||||
PendingIntent notifContentIntent = PendingIntent.getActivity(this, 0, notifIntent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
|
||||
Notified notif = mChatNotifMap.get(conferenceAddress);
|
||||
if (notif != null) {
|
||||
notif.numberOfUnreadMessage += 1;
|
||||
} else {
|
||||
notif = new Notified();
|
||||
notif.numberOfUnreadMessage = 1;
|
||||
notif.notificationId = mLastNotificationId;
|
||||
mLastNotificationId += 1;
|
||||
mChatNotifMap.put(conferenceAddress, notif);
|
||||
}
|
||||
|
||||
Bitmap bm;
|
||||
if (fromPictureUri != null) {
|
||||
try {
|
||||
bm = MediaStore.Images.Media.getBitmap(getContentResolver(), fromPictureUri);
|
||||
} catch (Exception e) {
|
||||
bm = BitmapFactory.decodeResource(getResources(), R.drawable.chat_group_avatar);
|
||||
}
|
||||
} else {
|
||||
bm = BitmapFactory.decodeResource(getResources(), R.drawable.topbar_avatar);
|
||||
}
|
||||
Notification notification = Compatibility.createMessageNotification(getApplicationContext(), notif.notificationId, notif.numberOfUnreadMessage, subject,
|
||||
getString(R.string.group_chat_notif).replace("%1", fromName).replace("%2", message), bm, notifContentIntent);
|
||||
|
||||
notifyWrapper(notif.notificationId, notification);
|
||||
}
|
||||
|
||||
public void displayMessageNotification(String fromSipUri, String fromName, Uri fromPictureUri, String message, String localIdentity) {
|
||||
Intent notifIntent = new Intent(this, LinphoneActivity.class);
|
||||
notifIntent.putExtra("GoToChat", true);
|
||||
notifIntent.putExtra("ChatContactSipUri", fromSipUri);
|
||||
notifIntent.putExtra("LocalIdentity", localIdentity);
|
||||
PendingIntent notifContentIntent = PendingIntent.getActivity(this, 0, notifIntent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
|
||||
if (fromName == null) {
|
||||
fromName = fromSipUri;
|
||||
}
|
||||
|
||||
Notified notif = mChatNotifMap.get(fromSipUri);
|
||||
if (notif != null) {
|
||||
notif.numberOfUnreadMessage += 1;
|
||||
} else {
|
||||
notif = new Notified();
|
||||
notif.numberOfUnreadMessage = 1;
|
||||
notif.notificationId = mLastNotificationId;
|
||||
mLastNotificationId += 1;
|
||||
mChatNotifMap.put(fromSipUri, notif);
|
||||
}
|
||||
|
||||
Bitmap bm;
|
||||
if (fromPictureUri != null) {
|
||||
try {
|
||||
bm = MediaStore.Images.Media.getBitmap(getContentResolver(), fromPictureUri);
|
||||
} catch (Exception e) {
|
||||
bm = BitmapFactory.decodeResource(getResources(), R.drawable.topbar_avatar);
|
||||
}
|
||||
} else {
|
||||
bm = BitmapFactory.decodeResource(getResources(), R.drawable.topbar_avatar);
|
||||
}
|
||||
Notification notification = Compatibility.createMessageNotification(getApplicationContext(), notif.notificationId, notif.numberOfUnreadMessage, fromName, message, bm, notifContentIntent);
|
||||
|
||||
notifyWrapper(notif.notificationId, notification);
|
||||
}
|
||||
|
||||
public void sendNotification(Notification notif, int notificationId) {
|
||||
notifyWrapper(notificationId, notif);
|
||||
}
|
||||
|
||||
public String getSipUriForNotificationId(int notificationId) {
|
||||
for (String addr : mChatNotifMap.keySet()) {
|
||||
if (mChatNotifMap.get(addr).notificationId == notificationId) {
|
||||
return addr;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void displayInappNotification(String message) {
|
||||
Intent notifIntent = new Intent(this, LinphoneActivity.class);
|
||||
notifIntent.putExtra("GoToInapp", true);
|
||||
|
||||
PendingIntent notifContentIntent = PendingIntent.getActivity(this, 0, notifIntent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
mNotif = Compatibility.createSimpleNotification(getApplicationContext(), getString(R.string.inapp_notification_title), message, notifContentIntent);
|
||||
|
||||
notifyWrapper(NOTIF_ID, mNotif);
|
||||
}
|
||||
|
||||
private static final Class<?>[] mSetFgSign = new Class[]{boolean.class};
|
||||
private static final Class<?>[] mStartFgSign = new Class[]{
|
||||
int.class, Notification.class};
|
||||
private static final Class<?>[] mStopFgSign = new Class[]{boolean.class};
|
||||
|
||||
private Method mStartForeground;
|
||||
private Method mStopForeground;
|
||||
private Object[] mSetForegroundArgs = new Object[1];
|
||||
private Object[] mStartForegroundArgs = new Object[2];
|
||||
private Object[] mStopForegroundArgs = new Object[1];
|
||||
private String incomingReceivedActivityName;
|
||||
private Class<? extends Activity> incomingReceivedActivity = LinphoneActivity.class;
|
||||
|
||||
void invokeMethod(Method method, Object[] args) {
|
||||
try {
|
||||
method.invoke(this, args);
|
||||
} catch (InvocationTargetException e) {
|
||||
// Should not happen.
|
||||
Log.w(e, "Unable to invoke method");
|
||||
} catch (IllegalAccessException e) {
|
||||
// Should not happen.
|
||||
Log.w(e, "Unable to invoke method");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a wrapper around the new startForeground method, using the older
|
||||
* APIs if it is not available.
|
||||
*/
|
||||
void startForegroundCompat(int id, Notification notification) {
|
||||
// If we have the new startForeground API, then use it.
|
||||
if (mStartForeground != null) {
|
||||
mStartForegroundArgs[0] = Integer.valueOf(id);
|
||||
mStartForegroundArgs[1] = notification;
|
||||
invokeMethod(mStartForeground, mStartForegroundArgs);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a wrapper around the new stopForeground method, using the older
|
||||
* APIs if it is not available.
|
||||
*/
|
||||
void stopForegroundCompat(int id) {
|
||||
// If we have the new stopForeground API, then use it.
|
||||
if (mStopForeground != null) {
|
||||
mStopForegroundArgs[0] = Boolean.TRUE;
|
||||
invokeMethod(mStopForeground, mStopForegroundArgs);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private void dumpDeviceInformation() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("DEVICE=").append(Build.DEVICE).append("\n");
|
||||
|
@ -775,38 +412,6 @@ public final class LinphoneService extends Service {
|
|||
}
|
||||
}
|
||||
|
||||
private synchronized void sendNotification(int level, int textId) {
|
||||
String text = getString(textId);
|
||||
if (text.contains("%s") && LinphoneManager.getLc() != null) {
|
||||
// Test for null lc is to avoid a NPE when Android mess up badly with the String resources.
|
||||
ProxyConfig lpc = LinphoneManager.getLc().getDefaultProxyConfig();
|
||||
String id = lpc != null ? lpc.getIdentityAddress().asString() : "";
|
||||
text = String.format(text, id);
|
||||
}
|
||||
|
||||
Bitmap bm = null;
|
||||
try {
|
||||
bm = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
mNotif = Compatibility.createNotification(this, mNotificationTitle, text, R.drawable.status_level, 0, bm, mNotifContentIntent, true, notifcationsPriority);
|
||||
notifyWrapper(NOTIF_ID, mNotif);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap notifier to avoid setting the linphone icons while the service
|
||||
* is stopping. When the (rare) bug is triggered, the linphone icon is
|
||||
* present despite the service is not running. To trigger it one could
|
||||
* stop linphone as soon as it is started. Transport configured with TLS.
|
||||
*/
|
||||
private synchronized void notifyWrapper(int id, Notification notification) {
|
||||
if (instance != null && notification != null) {
|
||||
mNM.notify(id, notification);
|
||||
} else {
|
||||
Log.i("Service not ready, discarding notification");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return null;
|
||||
|
@ -849,8 +454,7 @@ public final class LinphoneService extends Service {
|
|||
LinphoneManager.destroy();
|
||||
|
||||
// Make sure our notification is gone.
|
||||
stopForegroundCompat(NOTIF_ID);
|
||||
mNM.cancelAll();
|
||||
mNotificationManager.destroy();
|
||||
|
||||
// This will prevent the app from crashing if the service gets killed in background mode
|
||||
if (LinphoneActivity.isInstanciated()) {
|
||||
|
|
|
@ -698,10 +698,9 @@ public class LinphoneActivity extends LinphoneGenericActivity implements OnClick
|
|||
changeCurrentFragment(FragmentsAvailable.CREATE_CHAT, extras);
|
||||
}
|
||||
|
||||
public void goToChat(String sipUri, Bundle shareInfos, String localIdentity) {
|
||||
public void goToChat(String sipUri, Bundle shareInfos) {
|
||||
Bundle extras = new Bundle();
|
||||
extras.putString("SipUri", sipUri);
|
||||
extras.putString("LocalIdentity", localIdentity);
|
||||
|
||||
if (shareInfos != null) {
|
||||
if (shareInfos.getString("fileSharedUri") != null)
|
||||
|
@ -1382,9 +1381,6 @@ public class LinphoneActivity extends LinphoneGenericActivity implements OnClick
|
|||
Core lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
|
||||
if (lc != null) {
|
||||
lc.addListener(mListener);
|
||||
if (!LinphoneService.instance().displayServiceNotification()) {
|
||||
lc.refreshRegisters();
|
||||
}
|
||||
}
|
||||
|
||||
if (isTablet()) {
|
||||
|
@ -1483,12 +1479,11 @@ public class LinphoneActivity extends LinphoneGenericActivity implements OnClick
|
|||
Bundle extras = intent.getExtras();
|
||||
if (extras != null && extras.getBoolean("GoToChat", false)) {
|
||||
String sipUri = extras.getString("ChatContactSipUri");
|
||||
String localIdentity = extras.getString("LocalIdentity");
|
||||
intent.putExtra("DoNotGoToCallActivity", true);
|
||||
if (sipUri == null) {
|
||||
goToChatList();
|
||||
} else {
|
||||
goToChat(sipUri, extras, localIdentity);
|
||||
goToChat(sipUri, extras);
|
||||
}
|
||||
} else if (extras != null && extras.getBoolean("GoToHistory", false)) {
|
||||
intent.putExtra("DoNotGoToCallActivity", true);
|
||||
|
@ -1496,7 +1491,7 @@ public class LinphoneActivity extends LinphoneGenericActivity implements OnClick
|
|||
} else if (extras != null && extras.getBoolean("GoToInapp", false)) {
|
||||
intent.putExtra("DoNotGoToCallActivity", true);
|
||||
displayInapp();
|
||||
} else if (extras != null && extras.getBoolean("Notification", false)) {
|
||||
} else if (extras != null && extras.getBoolean("Notifiable", false)) {
|
||||
if (LinphoneManager.getLc().getCallsNb() > 0) {
|
||||
startIncallActivity();
|
||||
}
|
||||
|
@ -1840,9 +1835,9 @@ public class LinphoneActivity extends LinphoneGenericActivity implements OnClick
|
|||
LinphonePreferences.instance().setInappPopupTime(String.valueOf(newDate));
|
||||
}
|
||||
if (isTrialAccount) {
|
||||
LinphoneService.instance().displayInappNotification(String.format(getString(R.string.inapp_notification_trial_expire), date));
|
||||
LinphoneService.instance().getNotificationManager().displayInappNotification(String.format(getString(R.string.inapp_notification_trial_expire), date));
|
||||
} else {
|
||||
LinphoneService.instance().displayInappNotification(String.format(getString(R.string.inapp_notification_account_expire), date));
|
||||
LinphoneService.instance().getNotificationManager().displayInappNotification(String.format(getString(R.string.inapp_notification_account_expire), date));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -213,7 +213,7 @@ public class ChatCreationFragment extends Fragment implements View.OnClickListen
|
|||
public void onStateChanged(ChatRoom cr, ChatRoom.State newState) {
|
||||
if (newState == ChatRoom.State.Created) {
|
||||
mWaitLayout.setVisibility(View.GONE);
|
||||
LinphoneActivity.instance().goToChat(cr.getPeerAddress().asStringUriOnly(), mShareInfos, cr.getLocalAddress().asString());
|
||||
LinphoneActivity.instance().goToChat(cr.getPeerAddress().asStringUriOnly(), mShareInfos);
|
||||
} else if (newState == ChatRoom.State.CreationFailed) {
|
||||
mWaitLayout.setVisibility(View.GONE);
|
||||
LinphoneActivity.instance().displayChatRoomError();
|
||||
|
@ -468,7 +468,7 @@ public class ChatCreationFragment extends Fragment implements View.OnClickListen
|
|||
if (createEncryptedChatRoom && lpc != null && lpc.getConferenceFactoryUri() != null) {
|
||||
mChatRoom = lc.findOneToOneChatRoom(lpc.getIdentityAddress(), ca.getAddress(), true);
|
||||
if (mChatRoom != null) {
|
||||
LinphoneActivity.instance().goToChat(mChatRoom.getPeerAddress().asStringUriOnly(), mShareInfos, mChatRoom.getLocalAddress().asString());
|
||||
LinphoneActivity.instance().goToChat(mChatRoom.getPeerAddress().asStringUriOnly(), mShareInfos);
|
||||
} else {
|
||||
mChatRoom = lc.createClientGroupChatRoom(getString(R.string.dummy_group_chat_subject), !createEncryptedChatRoom, createEncryptedChatRoom);
|
||||
mChatRoom.addListener(mChatRoomCreationListener);
|
||||
|
@ -487,11 +487,11 @@ public class ChatCreationFragment extends Fragment implements View.OnClickListen
|
|||
participants[0] = ca.getAddress();
|
||||
mChatRoom.addParticipants(participants);
|
||||
} else {
|
||||
LinphoneActivity.instance().goToChat(mChatRoom.getPeerAddress().asStringUriOnly(), mShareInfos, mChatRoom.getLocalAddress().asString());
|
||||
LinphoneActivity.instance().goToChat(mChatRoom.getPeerAddress().asStringUriOnly(), mShareInfos);
|
||||
}
|
||||
} else {
|
||||
ChatRoom chatRoom = lc.getChatRoom(ca.getAddress());
|
||||
LinphoneActivity.instance().goToChat(chatRoom.getPeerAddress().asStringUriOnly(), mShareInfos, chatRoom.getLocalAddress().asString());
|
||||
LinphoneActivity.instance().goToChat(chatRoom.getPeerAddress().asStringUriOnly(), mShareInfos);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -161,7 +161,7 @@ public class ChatListFragment extends Fragment implements ContactsUpdatedListene
|
|||
mChatRoomsAdapter.toggleSelection(position);
|
||||
} else {
|
||||
ChatRoom room = (ChatRoom) mChatRoomsAdapter.getItem(position);
|
||||
LinphoneActivity.instance().goToChat(room.getPeerAddress().asString(), null, room.getLocalAddress().asString());
|
||||
LinphoneActivity.instance().goToChat(room.getPeerAddress().asString(), null);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -183,7 +183,7 @@ public class ChatListFragment extends Fragment implements ContactsUpdatedListene
|
|||
ChatRoomsAdapter adapter = (ChatRoomsAdapter) mChatRoomsList.getAdapter();
|
||||
if (adapter != null && adapter.getItemCount() > 0) {
|
||||
ChatRoom room = (ChatRoom) adapter.getItem(0);
|
||||
LinphoneActivity.instance().goToChat(room.getPeerAddress().asStringUriOnly(), null, room.getLocalAddress().asString());
|
||||
LinphoneActivity.instance().goToChat(room.getPeerAddress().asStringUriOnly(), null);
|
||||
} else {
|
||||
LinphoneActivity.instance().displayEmptyFragment();
|
||||
}
|
||||
|
|
|
@ -106,7 +106,7 @@ public class DevicesFragment extends Fragment {
|
|||
@Override
|
||||
public void onClick(View view) {
|
||||
if (LinphoneActivity.instance().isTablet()) {
|
||||
LinphoneActivity.instance().goToChat(mRoomUri, null, mRoom.getLocalAddress().asString());
|
||||
LinphoneActivity.instance().goToChat(mRoomUri, null);
|
||||
} else {
|
||||
LinphoneActivity.instance().onBackPressed();
|
||||
}
|
||||
|
|
|
@ -951,11 +951,11 @@ public class GroupChatFragment extends Fragment implements ChatRoomListener, Con
|
|||
if (LinphoneActivity.instance().isOnBackground()) {
|
||||
if (!getResources().getBoolean(R.bool.disable_chat_message_notification)) {
|
||||
if (contact != null) {
|
||||
LinphoneService.instance().displayMessageNotification(from.asStringUriOnly(),
|
||||
contact.getFullName(), contact.getThumbnailUri(), getString(R.string.message_cant_be_decrypted_notif), cr.getLocalAddress().asString());
|
||||
LinphoneService.instance().getNotificationManager().displayMessageNotification(from.asStringUriOnly(),
|
||||
contact.getFullName(), contact.getThumbnailUri(), getString(R.string.message_cant_be_decrypted_notif), cr.getLocalAddress());
|
||||
} else {
|
||||
LinphoneService.instance().displayMessageNotification(from.asStringUriOnly(),
|
||||
from.getUsername(), null, getString(R.string.message_cant_be_decrypted_notif), cr.getLocalAddress().asString());
|
||||
LinphoneService.instance().getNotificationManager().displayMessageNotification(from.asStringUriOnly(),
|
||||
from.getUsername(), null, getString(R.string.message_cant_be_decrypted_notif), cr.getLocalAddress());
|
||||
}
|
||||
}
|
||||
} else if (LinphoneManager.getLc().limeEnabled() == LimeState.Mandatory) {
|
||||
|
|
|
@ -159,7 +159,7 @@ public class GroupInfoFragment extends Fragment implements ChatRoomListener {
|
|||
public void onClick(View view) {
|
||||
if (mIsAlreadyCreatedGroup) {
|
||||
if (LinphoneActivity.instance().isTablet()) {
|
||||
LinphoneActivity.instance().goToChat(mGroupChatRoomAddress.asStringUriOnly(), mShareInfos, mChatRoom.getLocalAddress().asString());
|
||||
LinphoneActivity.instance().goToChat(mGroupChatRoomAddress.asStringUriOnly(), mShareInfos);
|
||||
} else {
|
||||
getFragmentManager().popBackStack();
|
||||
}
|
||||
|
@ -185,7 +185,7 @@ public class GroupInfoFragment extends Fragment implements ChatRoomListener {
|
|||
public void onClick(View view) {
|
||||
if (mChatRoom != null) {
|
||||
mChatRoom.leave();
|
||||
LinphoneActivity.instance().goToChat(mGroupChatRoomAddress.asString(), null, mChatRoom.getLocalAddress().asString());
|
||||
LinphoneActivity.instance().goToChat(mGroupChatRoomAddress.asString(), null);
|
||||
} else {
|
||||
Log.e("Can't leave, chatRoom for address " + mGroupChatRoomAddress.asString() + " is null...");
|
||||
}
|
||||
|
@ -251,7 +251,7 @@ public class GroupInfoFragment extends Fragment implements ChatRoomListener {
|
|||
// This will remove both the creation fragment and the group info fragment from the back stack
|
||||
getFragmentManager().popBackStack();
|
||||
getFragmentManager().popBackStack();
|
||||
LinphoneActivity.instance().goToChat(cr.getPeerAddress().asStringUriOnly(), mShareInfos, cr.getLocalAddress().asString());
|
||||
LinphoneActivity.instance().goToChat(cr.getPeerAddress().asStringUriOnly(), mShareInfos);
|
||||
} else if (newState == ChatRoom.State.CreationFailed) {
|
||||
mWaitLayout.setVisibility(View.GONE);
|
||||
LinphoneActivity.instance().displayChatRoomError();
|
||||
|
@ -322,7 +322,7 @@ public class GroupInfoFragment extends Fragment implements ChatRoomListener {
|
|||
toAdd.toArray(participantsToAdd);
|
||||
mChatRoom.addParticipants(participantsToAdd);
|
||||
|
||||
LinphoneActivity.instance().goToChat(mGroupChatRoomAddress.asString(), null, mChatRoom.getLocalAddress().asString());
|
||||
LinphoneActivity.instance().goToChat(mGroupChatRoomAddress.asString(), null);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -85,7 +85,7 @@ public class ImdnFragment extends Fragment {
|
|||
@Override
|
||||
public void onClick(View view) {
|
||||
if (LinphoneActivity.instance().isTablet()) {
|
||||
LinphoneActivity.instance().goToChat(mRoomUri, null, mRoom.getLocalAddress().asString());
|
||||
LinphoneActivity.instance().goToChat(mRoomUri, null);
|
||||
} else {
|
||||
LinphoneActivity.instance().onBackPressed();
|
||||
}
|
||||
|
|
|
@ -2,23 +2,22 @@ package org.linphone.compatibility;
|
|||
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.FragmentTransaction;
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.RemoteInput;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.view.ViewTreeObserver;
|
||||
|
||||
import org.linphone.R;
|
||||
import org.linphone.receivers.NotificationBroadcastReceiver;
|
||||
import org.linphone.notifications.Notifiable;
|
||||
import org.linphone.notifications.NotifiableMessage;
|
||||
import org.linphone.notifications.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_LOCAL_IDENTITY;
|
||||
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;
|
||||
|
@ -52,23 +51,17 @@ public class ApiTwentyFourPlus {
|
|||
.build();
|
||||
}
|
||||
|
||||
public static Notification createMessageNotification(Context context, int notificationId, int msgCount, String msgSender, String msg, Bitmap contactIcon, PendingIntent intent) {
|
||||
String title;
|
||||
if (msgCount == 1) {
|
||||
title = msgSender;
|
||||
} else {
|
||||
title = context.getString(R.string.unread_messages).replace("%i", String.valueOf(msgCount));
|
||||
}
|
||||
|
||||
public static Notification createMessageNotification(Context context, Notifiable notif, Bitmap contactIcon, PendingIntent intent) {
|
||||
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, notificationId);
|
||||
replyIntent.putExtra(INTENT_NOTIF_ID, notif.getNotificationId());
|
||||
replyIntent.putExtra(INTENT_LOCAL_IDENTITY, notif.getLocalIdentity());
|
||||
|
||||
PendingIntent replyPendingIntent = PendingIntent.getBroadcast(context,
|
||||
notificationId, replyIntent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
notif.getNotificationId(), replyIntent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
|
||||
Notification.Action action = new Notification.Action.Builder(R.drawable.chat_send_over,
|
||||
context.getString(R.string.notification_reply_label), replyPendingIntent)
|
||||
|
@ -76,9 +69,13 @@ public class ApiTwentyFourPlus {
|
|||
.setAllowGeneratedReplies(true)
|
||||
.build();
|
||||
|
||||
Notification.MessagingStyle style = new Notification.MessagingStyle(notif.getMyself());
|
||||
for (NotifiableMessage message : notif.getMessages()) {
|
||||
style.addMessage(message.getMessage(), message.getTime(), message.getSender());
|
||||
}
|
||||
style.setConversationTitle(notif.getGroupTitle());
|
||||
|
||||
return new Notification.Builder(context)
|
||||
.setContentTitle(title)
|
||||
.setContentText(msg)
|
||||
.setSmallIcon(R.drawable.topbar_chat_notification)
|
||||
.setAutoCancel(true)
|
||||
.setContentIntent(intent)
|
||||
|
@ -87,10 +84,11 @@ public class ApiTwentyFourPlus {
|
|||
.setCategory(Notification.CATEGORY_MESSAGE)
|
||||
.setVisibility(Notification.VISIBILITY_PRIVATE)
|
||||
.setPriority(Notification.PRIORITY_HIGH)
|
||||
.setNumber(msgCount)
|
||||
.setNumber(notif.getMessages().size())
|
||||
.setWhen(System.currentTimeMillis())
|
||||
.setShowWhen(true)
|
||||
.setColor(context.getColor(R.color.notification_color_led))
|
||||
.setStyle(style)
|
||||
.addAction(action)
|
||||
.build();
|
||||
}
|
||||
|
|
|
@ -11,15 +11,16 @@ import android.app.RemoteInput;
|
|||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.view.ViewTreeObserver;
|
||||
|
||||
import org.linphone.R;
|
||||
import org.linphone.mediastream.Log;
|
||||
import org.linphone.receivers.NotificationBroadcastReceiver;
|
||||
import org.linphone.notifications.Notifiable;
|
||||
import org.linphone.notifications.NotifiableMessage;
|
||||
import org.linphone.notifications.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_LOCAL_IDENTITY;
|
||||
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;
|
||||
|
@ -83,23 +84,17 @@ public class ApiTwentySixPlus {
|
|||
notificationManager.createNotificationChannel(channel);
|
||||
}
|
||||
|
||||
public static Notification createMessageNotification(Context context, int notificationId, int msgCount, String msgSender, String msg, Bitmap contactIcon, PendingIntent intent) {
|
||||
String title;
|
||||
if (msgCount == 1) {
|
||||
title = msgSender;
|
||||
} else {
|
||||
title = context.getString(R.string.unread_messages).replace("%i", String.valueOf(msgCount));
|
||||
}
|
||||
|
||||
public static Notification createMessageNotification(Context context, Notifiable notif, Bitmap contactIcon, PendingIntent intent) {
|
||||
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, notificationId);
|
||||
replyIntent.putExtra(INTENT_NOTIF_ID, notif.getNotificationId());
|
||||
replyIntent.putExtra(INTENT_LOCAL_IDENTITY, notif.getLocalIdentity());
|
||||
|
||||
PendingIntent replyPendingIntent = PendingIntent.getBroadcast(context,
|
||||
notificationId, replyIntent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
notif.getNotificationId(), replyIntent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
|
||||
Notification.Action action = new Notification.Action.Builder(R.drawable.chat_send_over,
|
||||
context.getString(R.string.notification_reply_label), replyPendingIntent)
|
||||
|
@ -107,9 +102,13 @@ public class ApiTwentySixPlus {
|
|||
.setAllowGeneratedReplies(true)
|
||||
.build();
|
||||
|
||||
Notification.MessagingStyle style = new Notification.MessagingStyle(notif.getMyself());
|
||||
for (NotifiableMessage message : notif.getMessages()) {
|
||||
style.addMessage(message.getMessage(), message.getTime(), message.getSender());
|
||||
}
|
||||
style.setConversationTitle(notif.getGroupTitle());
|
||||
|
||||
return new Notification.Builder(context, context.getString(R.string.notification_channel_id))
|
||||
.setContentTitle(title)
|
||||
.setContentText(msg)
|
||||
.setSmallIcon(R.drawable.topbar_chat_notification)
|
||||
.setAutoCancel(true)
|
||||
.setContentIntent(intent)
|
||||
|
@ -118,10 +117,11 @@ public class ApiTwentySixPlus {
|
|||
.setCategory(Notification.CATEGORY_MESSAGE)
|
||||
.setVisibility(Notification.VISIBILITY_PRIVATE)
|
||||
.setPriority(Notification.PRIORITY_HIGH)
|
||||
.setNumber(msgCount)
|
||||
.setNumber(notif.getMessages().size())
|
||||
.setWhen(System.currentTimeMillis())
|
||||
.setShowWhen(true)
|
||||
.setColor(context.getColor(R.color.notification_color_led))
|
||||
.setStyle(style)
|
||||
.addAction(action)
|
||||
.build();
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@ along with this program; if not, write to the Free Software
|
|||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
import android.app.AlarmManager;
|
||||
import android.app.FragmentTransaction;
|
||||
import android.app.Notification;
|
||||
import android.app.PendingIntent;
|
||||
|
@ -26,15 +25,11 @@ import android.content.Context;
|
|||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.os.Build;
|
||||
import android.os.PowerManager;
|
||||
import android.provider.Settings;
|
||||
import android.text.Html;
|
||||
import android.text.Spanned;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.linphone.mediastream.Version;
|
||||
import org.linphone.notifications.Notifiable;
|
||||
|
||||
public class Compatibility {
|
||||
public static final String KEY_TEXT_REPLY = "key_text_reply";
|
||||
|
@ -43,6 +38,7 @@ public class Compatibility {
|
|||
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 final String INTENT_LOCAL_IDENTITY = "LOCAL_IDENTITY";
|
||||
|
||||
public static void createNotificationChannels(Context context) {
|
||||
if (Version.sdkAboveOrEqual(Version.API26_O_80)) {
|
||||
|
@ -65,13 +61,13 @@ public class Compatibility {
|
|||
return ApiTwentyOnePlus.createMissedCallNotification(context, title, text, intent);
|
||||
}
|
||||
|
||||
public static Notification createMessageNotification(Context context, int notificationId, int msgCount, String msgSender, String msg, Bitmap contactIcon, PendingIntent intent) {
|
||||
public static Notification createMessageNotification(Context context, Notifiable notif, String msgSender, String msg, Bitmap contactIcon, PendingIntent intent) {
|
||||
if (Version.sdkAboveOrEqual(Version.API26_O_80)) {
|
||||
return ApiTwentySixPlus.createMessageNotification(context, notificationId, msgCount, msgSender, msg, contactIcon, intent);
|
||||
return ApiTwentySixPlus.createMessageNotification(context, notif, contactIcon, intent);
|
||||
} else if (Version.sdkAboveOrEqual(Version.API24_NOUGAT_70)) {
|
||||
return ApiTwentyFourPlus.createMessageNotification(context, notificationId, msgCount, msgSender, msg, contactIcon, intent);
|
||||
return ApiTwentyFourPlus.createMessageNotification(context, notif, contactIcon, intent);
|
||||
}
|
||||
return ApiTwentyOnePlus.createMessageNotification(context, msgCount, msgSender, msg, contactIcon, intent);
|
||||
return ApiTwentyOnePlus.createMessageNotification(context, notif.getMessages().size(), msgSender, msg, contactIcon, intent);
|
||||
}
|
||||
|
||||
public static Notification createRepliedNotification(Context context, String reply) {
|
||||
|
|
|
@ -85,7 +85,7 @@ public class ContactDetailsFragment extends Fragment implements OnClickListener
|
|||
if (defaultProxyConfig != null) {
|
||||
ChatRoom room = lc.findOneToOneChatRoom(defaultProxyConfig.getContact(), participant, isSecured);
|
||||
if (room != null) {
|
||||
LinphoneActivity.instance().goToChat(room.getPeerAddress().asStringUriOnly(), null, room.getLocalAddress().asString());
|
||||
LinphoneActivity.instance().goToChat(room.getPeerAddress().asStringUriOnly(), null);
|
||||
} else {
|
||||
if (defaultProxyConfig.getConferenceFactoryUri() != null && (isSecured || !LinphonePreferences.instance().useBasicChatRoomFor1To1())) {
|
||||
mWaitLayout.setVisibility(View.VISIBLE);
|
||||
|
@ -96,7 +96,7 @@ public class ContactDetailsFragment extends Fragment implements OnClickListener
|
|||
mChatRoom.addParticipants(participants);
|
||||
} else {
|
||||
room = lc.getChatRoom(participant);
|
||||
LinphoneActivity.instance().goToChat(room.getPeerAddress().asStringUriOnly(), null, room.getLocalAddress().asString());
|
||||
LinphoneActivity.instance().goToChat(room.getPeerAddress().asStringUriOnly(), null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -144,7 +144,7 @@ public class ContactDetailsFragment extends Fragment implements OnClickListener
|
|||
public void onStateChanged(ChatRoom cr, ChatRoom.State newState) {
|
||||
if (newState == ChatRoom.State.Created) {
|
||||
mWaitLayout.setVisibility(View.GONE);
|
||||
LinphoneActivity.instance().goToChat(cr.getPeerAddress().asStringUriOnly(), null, cr.getLocalAddress().asString());
|
||||
LinphoneActivity.instance().goToChat(cr.getPeerAddress().asStringUriOnly(), null);
|
||||
} else if (newState == ChatRoom.State.CreationFailed) {
|
||||
mWaitLayout.setVisibility(View.GONE);
|
||||
LinphoneActivity.instance().displayChatRoomError();
|
||||
|
|
|
@ -30,7 +30,7 @@ public class FirebaseIdService extends FirebaseInstanceIdService {
|
|||
public void onTokenRefresh() {
|
||||
// Get updated InstanceID token.
|
||||
final String refreshedToken = FirebaseInstanceId.getInstance().getToken();
|
||||
android.util.Log.i("FirebaseIdService", "[Push Notification] Refreshed token: " + refreshedToken);
|
||||
android.util.Log.i("FirebaseIdService", "[Push Notifiable] Refreshed token: " + refreshedToken);
|
||||
|
||||
LinphoneUtils.dispatchOnUIThread(new Runnable() {
|
||||
@Override
|
||||
|
|
|
@ -36,10 +36,10 @@ public class FirebaseMessaging extends FirebaseMessagingService {
|
|||
|
||||
@Override
|
||||
public void onMessageReceived(RemoteMessage remoteMessage) {
|
||||
android.util.Log.i("FirebaseMessaging", "[Push Notification] Received");
|
||||
android.util.Log.i("FirebaseMessaging", "[Push Notifiable] Received");
|
||||
|
||||
if (!LinphoneService.isReady()) {
|
||||
android.util.Log.i("FirebaseMessaging", "[Push Notification] Starting Service");
|
||||
android.util.Log.i("FirebaseMessaging", "[Push Notifiable] Starting Service");
|
||||
startService(new Intent(ACTION_MAIN).setClass(this, LinphoneService.class));
|
||||
} else if (LinphoneManager.isInstanciated() && LinphoneManager.getLc().getCallsNb() == 0) {
|
||||
LinphoneUtils.dispatchOnUIThread(new Runnable() {
|
||||
|
|
|
@ -109,7 +109,7 @@ public class HistoryDetailFragment extends Fragment implements OnClickListener {
|
|||
public void onStateChanged(ChatRoom cr, ChatRoom.State newState) {
|
||||
if (newState == ChatRoom.State.Created) {
|
||||
mWaitLayout.setVisibility(View.GONE);
|
||||
LinphoneActivity.instance().goToChat(cr.getPeerAddress().asStringUriOnly(), null, cr.getLocalAddress().asString());
|
||||
LinphoneActivity.instance().goToChat(cr.getPeerAddress().asStringUriOnly(), null);
|
||||
} else if (newState == ChatRoom.State.CreationFailed) {
|
||||
mWaitLayout.setVisibility(View.GONE);
|
||||
LinphoneActivity.instance().displayChatRoomError();
|
||||
|
@ -198,7 +198,7 @@ public class HistoryDetailFragment extends Fragment implements OnClickListener {
|
|||
Address participant = Factory.instance().createAddress(sipUri);
|
||||
ChatRoom room = lc.findOneToOneChatRoom(lc.getDefaultProxyConfig().getContact(), participant, false);
|
||||
if (room != null) {
|
||||
LinphoneActivity.instance().goToChat(room.getPeerAddress().asStringUriOnly(), null, room.getLocalAddress().asString());
|
||||
LinphoneActivity.instance().goToChat(room.getPeerAddress().asStringUriOnly(), null);
|
||||
} else {
|
||||
ProxyConfig lpc = lc.getDefaultProxyConfig();
|
||||
if (lpc != null && lpc.getConferenceFactoryUri() != null && !LinphonePreferences.instance().useBasicChatRoomFor1To1()) {
|
||||
|
@ -208,7 +208,7 @@ public class HistoryDetailFragment extends Fragment implements OnClickListener {
|
|||
mChatRoom.addParticipant(participant);
|
||||
} else {
|
||||
room = lc.getChatRoom(participant);
|
||||
LinphoneActivity.instance().goToChat(room.getPeerAddress().asStringUriOnly(), null, room.getLocalAddress().asString());
|
||||
LinphoneActivity.instance().goToChat(room.getPeerAddress().asStringUriOnly(), null);
|
||||
}
|
||||
}
|
||||
} else if (id == R.id.add_contact) {
|
||||
|
|
|
@ -1362,9 +1362,9 @@ public class SettingsFragment extends PreferencesListFragment {
|
|||
boolean value = (Boolean) newValue;
|
||||
mPrefs.setServiceNotificationVisibility(value);
|
||||
if (value) {
|
||||
LinphoneService.instance().showServiceNotification();
|
||||
LinphoneService.instance().getNotificationManager().startForeground();
|
||||
} else {
|
||||
LinphoneService.instance().hideServiceNotification();
|
||||
LinphoneService.instance().getNotificationManager().stopForeground();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
86
app/src/main/java/org/linphone/notifications/Notifiable.java
Normal file
86
app/src/main/java/org/linphone/notifications/Notifiable.java
Normal file
|
@ -0,0 +1,86 @@
|
|||
package org.linphone.notifications;
|
||||
|
||||
/*
|
||||
Notifiable.java
|
||||
Copyright (C) 2018 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 java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Notifiable {
|
||||
int mNotificationId;
|
||||
List<NotifiableMessage> mMessages;
|
||||
boolean mIsGroup;
|
||||
String mGroupTitle;
|
||||
String mLocalIdentity;
|
||||
String mMyself;
|
||||
|
||||
public Notifiable(int id) {
|
||||
mNotificationId = id;
|
||||
mMessages = new ArrayList<>();
|
||||
mIsGroup = false;
|
||||
}
|
||||
|
||||
public int getNotificationId() {
|
||||
return mNotificationId;
|
||||
}
|
||||
|
||||
public void resetMessages() {
|
||||
mMessages = new ArrayList<>();
|
||||
}
|
||||
|
||||
public void addMessage(NotifiableMessage notifMessage) {
|
||||
mMessages.add(notifMessage);
|
||||
}
|
||||
|
||||
public List<NotifiableMessage> getMessages() {
|
||||
return mMessages;
|
||||
}
|
||||
|
||||
public boolean isGroup() {
|
||||
return mIsGroup;
|
||||
}
|
||||
|
||||
public void setIsGroup(boolean isGroup) {
|
||||
mIsGroup = isGroup;
|
||||
}
|
||||
|
||||
public String getGroupTitle() {
|
||||
return mGroupTitle;
|
||||
}
|
||||
|
||||
public void setGroupTitle(String title) {
|
||||
mGroupTitle = title;
|
||||
}
|
||||
|
||||
public String getMyself() {
|
||||
return mMyself;
|
||||
}
|
||||
|
||||
public void setMyself(String myself) {
|
||||
mMyself = myself;
|
||||
}
|
||||
|
||||
public String getLocalIdentity() {
|
||||
return mLocalIdentity;
|
||||
}
|
||||
|
||||
public void setLocalIdentity(String localIdentity) {
|
||||
mLocalIdentity = localIdentity;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
package org.linphone.notifications;
|
||||
|
||||
/*
|
||||
NotifiableMessage.java
|
||||
Copyright (C) 2018 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.
|
||||
*/
|
||||
|
||||
public class NotifiableMessage {
|
||||
String mMessage;
|
||||
String mSender;
|
||||
long mTime;
|
||||
|
||||
public NotifiableMessage(String message, String sender, long time) {
|
||||
mMessage = message;
|
||||
mSender = sender;
|
||||
mTime = time;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return mMessage;
|
||||
}
|
||||
|
||||
public String getSender() {
|
||||
return mSender;
|
||||
}
|
||||
|
||||
public long getTime() {
|
||||
return mTime;
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package org.linphone.receivers;
|
||||
package org.linphone.notifications;
|
||||
|
||||
/*
|
||||
NotificationBroadcastReceiver.java
|
||||
|
@ -29,48 +29,82 @@ import android.os.Bundle;
|
|||
|
||||
import org.linphone.LinphoneManager;
|
||||
import org.linphone.LinphoneService;
|
||||
import org.linphone.R;
|
||||
import org.linphone.activities.LinphoneActivity;
|
||||
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.ProxyConfig;
|
||||
import org.linphone.core.Reason;
|
||||
import org.linphone.mediastream.Log;
|
||||
|
||||
public class NotificationBroadcastReceiver extends BroadcastReceiver {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
public void onReceive(final Context context, Intent intent) {
|
||||
final int notifId = intent.getIntExtra(Compatibility.INTENT_NOTIF_ID, 0);
|
||||
final String localyIdentity = intent.getStringExtra(Compatibility.INTENT_LOCAL_IDENTITY);
|
||||
|
||||
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) return;
|
||||
int notifId = intent.getIntExtra(Compatibility.INTENT_NOTIF_ID, 0);
|
||||
String remoteSipAddr = LinphoneService.instance().getSipUriForNotificationId(notifId);
|
||||
final String reply = getMessageText(intent).toString();
|
||||
if (reply == null) {
|
||||
Log.e("Couldn't get reply text");
|
||||
onError(context, notifId);
|
||||
return;
|
||||
}
|
||||
String remoteSipAddr = LinphoneService.instance().getNotificationManager().getSipUriForNotificationId(notifId);
|
||||
|
||||
Core core = LinphoneManager.getLc();
|
||||
if (core == null) return;
|
||||
ProxyConfig proxyConfig = core.getDefaultProxyConfig();
|
||||
if (proxyConfig == null) return;
|
||||
Address localAddr = proxyConfig.getIdentityAddress();
|
||||
if (core == null) {
|
||||
Log.e("Couldn't get Core instance");
|
||||
onError(context, notifId);
|
||||
return;
|
||||
}
|
||||
|
||||
Address remoteAddr = core.interpretUrl(remoteSipAddr);
|
||||
if (localAddr == null || remoteAddr == null) return;
|
||||
if (remoteAddr == null) {
|
||||
Log.e("Couldn't interpret remote address " + remoteSipAddr);
|
||||
onError(context, notifId);
|
||||
return;
|
||||
}
|
||||
|
||||
Address localAddr = core.interpretUrl(localyIdentity);
|
||||
if (localAddr == null) {
|
||||
Log.e("Couldn't interpret local address " + localyIdentity);
|
||||
onError(context, notifId);
|
||||
return;
|
||||
}
|
||||
|
||||
ChatRoom room = core.findChatRoom(remoteAddr, localAddr);
|
||||
if (room == null) return;
|
||||
if (room == null) {
|
||||
Log.e("Couldn't find chat room for remote address " + remoteSipAddr + " and local address " + localyIdentity);
|
||||
onError(context, notifId);
|
||||
return;
|
||||
}
|
||||
|
||||
room.markAsRead();
|
||||
if (LinphoneActivity.isInstanciated()) {
|
||||
LinphoneActivity.instance().displayMissedChats(LinphoneManager.getInstance().getUnreadMessageCount());
|
||||
}
|
||||
|
||||
ChatMessage msg = room.createMessage(reply);
|
||||
msg.send();
|
||||
|
||||
LinphoneService.instance().sendNotification(replied, notifId);
|
||||
msg.setListener(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("Couldn't send reply, message is not delivered");
|
||||
onError(context, 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);
|
||||
String remoteAddr = LinphoneService.instance().getNotificationManager().getSipUriForCallNotificationId(notifId);
|
||||
|
||||
Core core = LinphoneManager.getLc();
|
||||
if (core == null) return;
|
||||
|
@ -85,6 +119,11 @@ public class NotificationBroadcastReceiver extends BroadcastReceiver {
|
|||
}
|
||||
}
|
||||
|
||||
private void onError(Context context, int notifId) {
|
||||
Notification replyError = Compatibility.createRepliedNotification(context, context.getString(R.string.error));
|
||||
LinphoneService.instance().getNotificationManager().sendNotification(notifId, replyError);
|
||||
}
|
||||
|
||||
@TargetApi(20)
|
||||
private CharSequence getMessageText(Intent intent) {
|
||||
Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);
|
|
@ -0,0 +1,308 @@
|
|||
package org.linphone.notifications;
|
||||
|
||||
/*
|
||||
NotificationsManager.java
|
||||
Copyright (C) 2018 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 android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.net.Uri;
|
||||
import android.provider.MediaStore;
|
||||
|
||||
import org.linphone.LinphoneManager;
|
||||
import org.linphone.LinphonePreferences;
|
||||
import org.linphone.LinphoneService;
|
||||
import org.linphone.LinphoneUtils;
|
||||
import org.linphone.R;
|
||||
import org.linphone.activities.LinphoneActivity;
|
||||
import org.linphone.compatibility.Compatibility;
|
||||
import org.linphone.contacts.ContactsManager;
|
||||
import org.linphone.contacts.LinphoneContact;
|
||||
import org.linphone.core.Address;
|
||||
import org.linphone.core.Call;
|
||||
import org.linphone.mediastream.Version;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import static android.content.Context.NOTIFICATION_SERVICE;
|
||||
|
||||
public class NotificationsManager {
|
||||
private static final int SERVICE_NOTIF_ID = 1;
|
||||
private static final int MISSED_CALLS_NOTIF_ID = 2;
|
||||
private static final int IN_APP_NOTIF_ID = 3;
|
||||
|
||||
private Context mContext;
|
||||
private NotificationManager mNM;
|
||||
private HashMap<String, Notifiable> mChatNotifMap, mCallNotifMap;
|
||||
private int mLastNotificationId;
|
||||
private PendingIntent mPendingIntent;
|
||||
private Notification mServiceNotification;
|
||||
|
||||
public NotificationsManager(Context context) {
|
||||
mContext = context;
|
||||
mChatNotifMap = new HashMap<>();
|
||||
mCallNotifMap = new HashMap<>();
|
||||
|
||||
mNM = (NotificationManager) mContext.getSystemService(NOTIFICATION_SERVICE);
|
||||
mNM.cancelAll();
|
||||
|
||||
mLastNotificationId = 5; // Do not conflict with hardcoded notifications ids !
|
||||
|
||||
Compatibility.createNotificationChannels(mContext);
|
||||
|
||||
Intent notifIntent = new Intent(mContext, LinphoneService.instance().getIncomingReceivedActivity());
|
||||
notifIntent.putExtra("Notifiable", true);
|
||||
mPendingIntent = PendingIntent.getActivity(mContext, 0, notifIntent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
|
||||
//Disable service notification for Android O
|
||||
if (Version.sdkAboveOrEqual(Version.API26_O_80)) {
|
||||
LinphonePreferences.instance().setServiceNotificationVisibility(false);
|
||||
}
|
||||
|
||||
Bitmap bm = null;
|
||||
try {
|
||||
bm = BitmapFactory.decodeResource(mContext.getResources(), R.mipmap.ic_launcher);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
mServiceNotification = Compatibility.createNotification(mContext, mContext.getString(R.string.service_name), "",
|
||||
R.drawable.linphone_notification_icon, R.mipmap.ic_launcher, bm, mPendingIntent, true,
|
||||
Notification.PRIORITY_MIN);
|
||||
|
||||
if (isServiceNotificationDisplayed()) {
|
||||
startForeground();
|
||||
}
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
mNM.cancelAll();
|
||||
}
|
||||
|
||||
public void startForeground() {
|
||||
LinphoneService.instance().startForeground(SERVICE_NOTIF_ID, mServiceNotification);
|
||||
}
|
||||
|
||||
public void stopForeground() {
|
||||
LinphoneService.instance().stopForeground(true);
|
||||
}
|
||||
|
||||
public void sendNotification(int id, Notification notif) {
|
||||
mNM.notify(id, notif);
|
||||
}
|
||||
|
||||
public void resetMessageNotifCount(String address) {
|
||||
Notifiable notif = mChatNotifMap.get(address);
|
||||
if (notif != null) {
|
||||
notif.resetMessages();
|
||||
mNM.cancel(notif.getNotificationId());
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isServiceNotificationDisplayed() {
|
||||
return LinphonePreferences.instance().getServiceNotificationVisibility();
|
||||
}
|
||||
|
||||
public String getSipUriForNotificationId(int notificationId) {
|
||||
for (String addr : mChatNotifMap.keySet()) {
|
||||
if (mChatNotifMap.get(addr).getNotificationId() == notificationId) {
|
||||
return addr;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void displayGroupChatMessageNotification(String subject, String conferenceAddress, String fromName, Uri fromPictureUri, String message, Address localIdentity) {
|
||||
Intent notifIntent = new Intent(mContext, LinphoneActivity.class);
|
||||
notifIntent.putExtra("GoToChat", true);
|
||||
notifIntent.putExtra("ChatContactSipUri", conferenceAddress);
|
||||
PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, notifIntent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
|
||||
Notifiable notif = mChatNotifMap.get(conferenceAddress);
|
||||
NotifiableMessage notifMessage = new NotifiableMessage(message, fromName, 0);
|
||||
if (notif == null) {
|
||||
notif = new Notifiable(mLastNotificationId);
|
||||
mLastNotificationId += 1;
|
||||
mChatNotifMap.put(conferenceAddress, notif);
|
||||
}
|
||||
notif.addMessage(notifMessage);
|
||||
notif.setIsGroup(true);
|
||||
notif.setGroupTitle(subject);
|
||||
notif.setMyself(LinphoneUtils.getAddressDisplayName(localIdentity));
|
||||
notif.setLocalIdentity(localIdentity.asString());
|
||||
|
||||
Bitmap bm;
|
||||
if (fromPictureUri != null) {
|
||||
try {
|
||||
bm = MediaStore.Images.Media.getBitmap(mContext.getContentResolver(), fromPictureUri);
|
||||
} catch (Exception e) {
|
||||
bm = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.chat_group_avatar);
|
||||
}
|
||||
} else {
|
||||
bm = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.topbar_avatar);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
public void displayMessageNotification(String fromSipUri, String fromName, Uri fromPictureUri, String message, Address localIdentity) {
|
||||
Intent notifIntent = new Intent(mContext, LinphoneActivity.class);
|
||||
notifIntent.putExtra("GoToChat", true);
|
||||
notifIntent.putExtra("ChatContactSipUri", fromSipUri);
|
||||
PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, notifIntent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
|
||||
if (fromName == null) {
|
||||
fromName = fromSipUri;
|
||||
}
|
||||
|
||||
Notifiable notif = mChatNotifMap.get(fromSipUri);
|
||||
NotifiableMessage notifMessage = new NotifiableMessage(message, fromName, 0);
|
||||
if (notif == null) {
|
||||
notif = new Notifiable(mLastNotificationId);
|
||||
mLastNotificationId += 1;
|
||||
mChatNotifMap.put(fromSipUri, notif);
|
||||
}
|
||||
notif.addMessage(notifMessage);
|
||||
notif.setIsGroup(false);
|
||||
notif.setMyself(LinphoneUtils.getAddressDisplayName(localIdentity));
|
||||
notif.setLocalIdentity(localIdentity.asString());
|
||||
|
||||
Bitmap bm;
|
||||
if (fromPictureUri != null) {
|
||||
try {
|
||||
bm = MediaStore.Images.Media.getBitmap(mContext.getContentResolver(), fromPictureUri);
|
||||
} catch (Exception e) {
|
||||
bm = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.topbar_avatar);
|
||||
}
|
||||
} else {
|
||||
bm = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.topbar_avatar);
|
||||
}
|
||||
Notification notification = Compatibility.createMessageNotification(mContext, notif, fromName, message, bm, pendingIntent);
|
||||
sendNotification(notif.getNotificationId(), notification);
|
||||
}
|
||||
|
||||
public void displayMissedCallNotification(Call call) {
|
||||
Intent missedCallNotifIntent = new Intent(mContext, LinphoneService.instance().getIncomingReceivedActivity());
|
||||
missedCallNotifIntent.putExtra("GoToHistory", true);
|
||||
PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, missedCallNotifIntent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
|
||||
int missedCallCount = LinphoneManager.getLcIfManagerNotDestroyedOrNull().getMissedCallsCount();
|
||||
String body;
|
||||
if (missedCallCount > 1) {
|
||||
body = mContext.getString(R.string.missed_calls_notif_body).replace("%i", String.valueOf(missedCallCount));
|
||||
} else {
|
||||
Address address = call.getRemoteAddress();
|
||||
LinphoneContact c = ContactsManager.getInstance().findContactFromAddress(address);
|
||||
if (c != null) {
|
||||
body = c.getFullName();
|
||||
} else {
|
||||
body = address.getDisplayName();
|
||||
if (body == null) {
|
||||
body = address.asStringUriOnly();
|
||||
}
|
||||
}
|
||||
}
|
||||
Notification notif = Compatibility.createMissedCallNotification(mContext, mContext.getString(R.string.missed_calls_notif_title), body, pendingIntent);
|
||||
sendNotification(MISSED_CALLS_NOTIF_ID, notif);
|
||||
}
|
||||
|
||||
public void displayCallNotification(Call call) {
|
||||
if (call == null) return;
|
||||
|
||||
Address address = call.getRemoteAddress();
|
||||
String addressAsString = address.asStringUriOnly();
|
||||
Notifiable notif = mCallNotifMap.get(addressAsString);
|
||||
if (notif == null) {
|
||||
notif = new Notifiable(mLastNotificationId);
|
||||
mLastNotificationId += 1;
|
||||
mCallNotifMap.put(addressAsString, notif);
|
||||
}
|
||||
|
||||
if (!isServiceNotificationDisplayed()) {
|
||||
if (call.getCore().getCallsNb() == 0) {
|
||||
stopForeground();
|
||||
} else {
|
||||
startForeground();
|
||||
}
|
||||
}
|
||||
|
||||
int notificationTextId;
|
||||
int iconId;
|
||||
switch (call.getState()) {
|
||||
case Released:
|
||||
case End:
|
||||
mNM.cancel(notif.getNotificationId());
|
||||
mCallNotifMap.remove(addressAsString);
|
||||
return;
|
||||
case Paused:
|
||||
case PausedByRemote:
|
||||
case Pausing:
|
||||
iconId = R.drawable.topbar_call_notification;
|
||||
notificationTextId = R.string.incall_notif_paused;
|
||||
break;
|
||||
default:
|
||||
if (call.getCurrentParams().videoEnabled()) {
|
||||
iconId = R.drawable.topbar_videocall_notification;
|
||||
notificationTextId = R.string.incall_notif_video;
|
||||
} else {
|
||||
iconId = R.drawable.topbar_call_notification;
|
||||
notificationTextId = R.string.incall_notif_active;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
LinphoneContact contact = ContactsManager.getInstance().findContactFromAddress(address);
|
||||
Uri pictureUri = contact != null ? contact.getPhotoUri() : null;
|
||||
Bitmap bm;
|
||||
try {
|
||||
bm = MediaStore.Images.Media.getBitmap(mContext.getContentResolver(), pictureUri);
|
||||
} catch (Exception e) {
|
||||
bm = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.avatar);
|
||||
}
|
||||
String name = LinphoneUtils.getAddressDisplayName(address);
|
||||
|
||||
boolean showAnswerAction = call.getState() == Call.State.IncomingReceived || call.getState() == Call.State.IncomingEarlyMedia;
|
||||
Notification notification = Compatibility.createInCallNotification(mContext, notif.getNotificationId(),
|
||||
showAnswerAction, mContext.getString(R.string.service_name),
|
||||
mContext.getString(notificationTextId), iconId, bm, name, mPendingIntent);
|
||||
|
||||
sendNotification(notif.getNotificationId(), notification);
|
||||
}
|
||||
|
||||
public String getSipUriForCallNotificationId(int notificationId) {
|
||||
for (String addr : mCallNotifMap.keySet()) {
|
||||
if (mCallNotifMap.get(addr).getNotificationId() == notificationId) {
|
||||
return addr;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void displayInappNotification(String message) {
|
||||
Intent notifIntent = new Intent(mContext, LinphoneActivity.class);
|
||||
notifIntent.putExtra("GoToInapp", true);
|
||||
PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, notifIntent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
Notification notif = Compatibility.createSimpleNotification(mContext, mContext.getString(R.string.inapp_notification_title), message, pendingIntent);
|
||||
|
||||
sendNotification(IN_APP_NOTIF_ID, notif);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue