Commit 11cd2ff3 authored by Grigory Fedorov's avatar Grigory Fedorov

NotificationManager: persistent notification and message notifications. NotificationBuilder used.

chat_notification layouts removed.
parent e643f083
...@@ -23,7 +23,7 @@ import android.media.AudioManager; ...@@ -23,7 +23,7 @@ import android.media.AudioManager;
import android.net.Uri; import android.net.Uri;
import android.os.Handler; import android.os.Handler;
import android.os.Vibrator; import android.os.Vibrator;
import android.widget.RemoteViews; import android.support.v4.app.NotificationCompat;
import com.xabber.android.data.Application; import com.xabber.android.data.Application;
import com.xabber.android.data.LogManager; import com.xabber.android.data.LogManager;
...@@ -69,7 +69,6 @@ public class NotificationManager implements OnInitializedListener, OnAccountChan ...@@ -69,7 +69,6 @@ public class NotificationManager implements OnInitializedListener, OnAccountChan
OnAccountArchiveModeChangedListener { OnAccountArchiveModeChangedListener {
public static final int PERSISTENT_NOTIFICATION_ID = 1; public static final int PERSISTENT_NOTIFICATION_ID = 1;
private static final int CHAT_NOTIFICATION_ID = 2;
private static final int BASE_NOTIFICATION_PROVIDER_ID = 0x10; private static final int BASE_NOTIFICATION_PROVIDER_ID = 0x10;
private static final long VIBRATION_DURATION = 500; private static final long VIBRATION_DURATION = 500;
...@@ -77,10 +76,11 @@ public class NotificationManager implements OnInitializedListener, OnAccountChan ...@@ -77,10 +76,11 @@ public class NotificationManager implements OnInitializedListener, OnAccountChan
private final long startTime; private final long startTime;
private final Application application; private final Application application;
private final android.app.NotificationManager notificationManager; private final android.app.NotificationManager notificationManager;
private final Notification persistentNotification;
private final PendingIntent clearNotifications; private final PendingIntent clearNotifications;
private final Handler handler; private final Handler handler;
private NotificationCompat.Builder persistentNotificationBuilder;
/** /**
* Runnable to start vibration. * Runnable to start vibration.
*/ */
...@@ -118,7 +118,6 @@ public class NotificationManager implements OnInitializedListener, OnAccountChan ...@@ -118,7 +118,6 @@ public class NotificationManager implements OnInitializedListener, OnAccountChan
notificationManager = (android.app.NotificationManager) notificationManager = (android.app.NotificationManager)
application.getSystemService(Context.NOTIFICATION_SERVICE); application.getSystemService(Context.NOTIFICATION_SERVICE);
persistentNotification = new Notification();
handler = new Handler(); handler = new Handler();
providers = new ArrayList<>(); providers = new ArrayList<>();
...@@ -150,6 +149,8 @@ public class NotificationManager implements OnInitializedListener, OnAccountChan ...@@ -150,6 +149,8 @@ public class NotificationManager implements OnInitializedListener, OnAccountChan
handler.postDelayed(stopVibration, VIBRATION_DURATION); handler.postDelayed(stopVibration, VIBRATION_DURATION);
} }
}; };
persistentNotificationBuilder = new NotificationCompat.Builder(application);
} }
@Override @Override
...@@ -198,8 +199,7 @@ public class NotificationManager implements OnInitializedListener, OnAccountChan ...@@ -198,8 +199,7 @@ public class NotificationManager implements OnInitializedListener, OnAccountChan
* *
* @param provider * @param provider
*/ */
public void registerNotificationProvider( public void registerNotificationProvider(NotificationProvider<? extends NotificationItem> provider) {
NotificationProvider<? extends NotificationItem> provider) {
providers.add(provider); providers.add(provider);
} }
...@@ -239,6 +239,9 @@ public class NotificationManager implements OnInitializedListener, OnAccountChan ...@@ -239,6 +239,9 @@ public class NotificationManager implements OnInitializedListener, OnAccountChan
} }
Intent intent = top.getIntent(); Intent intent = top.getIntent();
Notification notification = new Notification(provider.getIcon(), Notification notification = new Notification(provider.getIcon(),
ticker, System.currentTimeMillis()); ticker, System.currentTimeMillis());
...@@ -249,8 +252,7 @@ public class NotificationManager implements OnInitializedListener, OnAccountChan ...@@ -249,8 +252,7 @@ public class NotificationManager implements OnInitializedListener, OnAccountChan
notification.setLatestEventInfo(application, top.getTitle(), top.getText(), notification.setLatestEventInfo(application, top.getTitle(), top.getText(),
PendingIntent.getActivity(application, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)); PendingIntent.getActivity(application, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
if (ticker != null) { if (ticker != null) {
setNotificationDefaults(notification, setNotificationDefaults(SettingsManager.eventsVibro(), provider.getSound(), provider.getStreamType());
SettingsManager.eventsVibro(), provider.getSound(), provider.getStreamType());
} }
notification.deleteIntent = clearNotifications; notification.deleteIntent = clearNotifications;
...@@ -260,27 +262,28 @@ public class NotificationManager implements OnInitializedListener, OnAccountChan ...@@ -260,27 +262,28 @@ public class NotificationManager implements OnInitializedListener, OnAccountChan
/** /**
* Sound, vibration and lightning flags. * Sound, vibration and lightning flags.
* *
* @param notification
* @param streamType * @param streamType
*/ */
private void setNotificationDefaults( private void setNotificationDefaults(boolean vibration, Uri sound, int streamType) {
Notification notification, boolean vibration, Uri sound, int streamType) { persistentNotificationBuilder.setSound(sound, streamType);
notification.audioStreamType = streamType; persistentNotificationBuilder.setDefaults(0);
notification.defaults = 0;
notification.sound = sound; int defaults = 0;
if (vibration) { if (vibration) {
if (SettingsManager.eventsIgnoreSystemVibro()) { if (SettingsManager.eventsIgnoreSystemVibro()) {
handler.post(startVibration); handler.post(startVibration);
} else { } else {
notification.defaults |= Notification.DEFAULT_VIBRATE; defaults |= Notification.DEFAULT_VIBRATE;
} }
} }
if (SettingsManager.eventsLightning()) { if (SettingsManager.eventsLightning()) {
notification.defaults |= Notification.DEFAULT_LIGHTS; defaults |= Notification.DEFAULT_LIGHTS;
notification.flags |= Notification.FLAG_SHOW_LIGHTS;
} }
persistentNotificationBuilder.setDefaults(defaults);
} }
/** /**
...@@ -365,52 +368,54 @@ public class NotificationManager implements OnInitializedListener, OnAccountChan ...@@ -365,52 +368,54 @@ public class NotificationManager implements OnInitializedListener, OnAccountChan
persistentIntent = ContactList.createPersistentIntent(application); persistentIntent = ContactList.createPersistentIntent(application);
} }
if (messageNotifications.isEmpty()) { persistentNotificationBuilder.setSmallIcon(R.drawable.ic_stat_normal);
notificationManager.cancel(CHAT_NOTIFICATION_ID);
} else { persistentNotificationBuilder.setContentTitle(application.getString(R.string.application_name));
notifyMessageNotification(ticker, connected); persistentNotificationBuilder.setContentText(connectionState);
} persistentNotificationBuilder.setContentIntent(PendingIntent.getActivity(application, 0, persistentIntent,
PendingIntent.FLAG_UPDATE_CURRENT));
persistentNotificationBuilder.setOngoing(true);
persistentNotificationBuilder.setDefaults(0);
persistentNotificationBuilder.setSound(null);
persistentNotificationBuilder.setTicker(null);
persistentNotification.icon = R.drawable.ic_stat_normal;
persistentNotification.setLatestEventInfo(application, application
.getString(R.string.application_name), connectionState,
PendingIntent.getActivity(application, 0, persistentIntent,
PendingIntent.FLAG_UPDATE_CURRENT));
persistentNotification.flags = Notification.FLAG_ONGOING_EVENT
| Notification.FLAG_NO_CLEAR;
persistentNotification.defaults = 0;
persistentNotification.sound = null;
persistentNotification.tickerText = null;
if (SettingsManager.eventsPersistent()) { if (SettingsManager.eventsPersistent()) {
// Ongoing icons are in the left side, so always use it. // Ongoing icons are in the left side, so always use it.
persistentNotification.when = startTime; persistentNotificationBuilder.setWhen(startTime);
if (messageNotifications.isEmpty()) { if (messageNotifications.isEmpty()) {
persistentNotification.icon = connected > 0 ? R.drawable.ic_stat_normal persistentNotificationBuilder.setSmallIcon(connected > 0 ? R.drawable.ic_stat_normal
: R.drawable.ic_stat_offline; : R.drawable.ic_stat_offline);
} else { } else {
persistentNotification.icon = connected > 0 ? R.drawable.ic_stat_message persistentNotificationBuilder.setSmallIcon(connected > 0 ? R.drawable.ic_stat_message
: R.drawable.ic_stat_message_offline; : R.drawable.ic_stat_message_offline);
} }
updateNotification(persistentNotification, ticker); updateNotification(ticker);
} else { } else {
// Ongoing icons are in the right side, so hide it if necessary. // Ongoing icons are in the right side, so hide it if necessary.
if (messageNotifications.isEmpty()) { if (messageNotifications.isEmpty()) {
persistentNotification.icon = connected > 0 ? R.drawable.ic_stat_normal persistentNotificationBuilder.setSmallIcon(connected > 0 ? R.drawable.ic_stat_normal
: R.drawable.ic_stat_offline; : R.drawable.ic_stat_offline);
persistentNotification.when = startTime; persistentNotificationBuilder.setWhen(startTime);
// Show ticker for the messages in active chat. // Show ticker for the messages in active chat.
updateNotification(persistentNotification, ticker); updateNotification(ticker);
} else { } else {
persistentNotification.icon = R.drawable.ic_placeholder; persistentNotificationBuilder.setSmallIcon(R.drawable.ic_placeholder);
persistentNotification.when = -Long.MAX_VALUE; persistentNotificationBuilder.setWhen(-Long.MAX_VALUE);
} }
} }
if (SettingsManager.eventsPersistent()) { if (SettingsManager.eventsPersistent()) {
notify(PERSISTENT_NOTIFICATION_ID, persistentNotification); notify(PERSISTENT_NOTIFICATION_ID, persistentNotificationBuilder.build());
} else { } else {
notificationManager.cancel(PERSISTENT_NOTIFICATION_ID); notificationManager.cancel(PERSISTENT_NOTIFICATION_ID);
} }
if (!messageNotifications.isEmpty()) {
notifyMessageNotification(ticker, connected);
}
} }
private void notifyMessageNotification(MessageItem ticker, int connected) { private void notifyMessageNotification(MessageItem ticker, int connected) {
...@@ -422,70 +427,58 @@ public class NotificationManager implements OnInitializedListener, OnAccountChan ...@@ -422,70 +427,58 @@ public class NotificationManager implements OnInitializedListener, OnAccountChan
MessageNotification message = messageNotifications.get(messageNotifications.size() - 1); MessageNotification message = messageNotifications.get(messageNotifications.size() - 1);
RemoteViews chatViews
= new RemoteViews(application.getPackageName(), R.layout.chat_notification);
Intent chatIntent Intent chatIntent
= ChatViewer.createClearTopIntent(application, message.getAccount(), message.getUser()); = ChatViewer.createClearTopIntent(application, message.getAccount(), message.getUser());
if (MUCManager.getInstance().hasRoom(message.getAccount(), message.getUser())) { if (messageCount == 1) {
chatViews.setImageViewBitmap( persistentNotificationBuilder.setContentTitle(RosterManager.getInstance().getName(message.getAccount(), message.getUser()));
R.id.icon, AvatarManager.getInstance().getRoomBitmap(message.getUser()));
} else {
chatViews.setImageViewBitmap(
R.id.icon, AvatarManager.getInstance().getUserBitmap(message.getUser()));
}
chatViews.setTextViewText(R.id.title, String text;
RosterManager.getInstance().getName(message.getAccount(), message.getUser()));
String text; if (ChatManager.getInstance().isShowText(message.getAccount(), message.getUser())) {
text = trimText(message.getText());
} else {
text = "";
}
if (ChatManager.getInstance().isShowText(message.getAccount(), message.getUser())) { persistentNotificationBuilder.setContentText(Emoticons.getSmiledText(application, text));
text = trimText(message.getText());
} else { if (MUCManager.getInstance().hasRoom(message.getAccount(), message.getUser())) {
text = ""; persistentNotificationBuilder.setLargeIcon(AvatarManager.getInstance().getRoomBitmap(message.getUser()));
} } else {
persistentNotificationBuilder.setLargeIcon(AvatarManager.getInstance().getUserBitmap(message.getUser()));
}
chatViews.setTextViewText(R.id.text2, Emoticons.getSmiledText(application, text)); } else {
chatViews.setTextViewText(R.id.time, StringUtils.getSmartTimeText(message.getTimestamp())); String messageText = StringUtils.getQuantityString(
application.getResources(), R.array.chat_message_quantity, messageCount);
String contactText = StringUtils.getQuantityString(application.getResources(),
R.array.chat_contact_quantity, messageNotifications.size());
String status = application.getString(R.string.chat_status,
messageCount, messageText, messageNotifications.size(), contactText);
String messageText = StringUtils.getQuantityString(
application.getResources(), R.array.chat_message_quantity, messageCount);
String contactText = StringUtils.getQuantityString(application.getResources(),
R.array.chat_contact_quantity, messageNotifications.size());
String status = application.getString(R.string.chat_status,
messageCount, messageText, messageNotifications.size(), contactText);
chatViews.setTextViewText(R.id.text, status); persistentNotificationBuilder.setContentTitle(status);
Notification notification = new Notification(); persistentNotificationBuilder.setLargeIcon(null);
if (SettingsManager.eventsPersistent()) {
// Ongoing icons are in the left side, so hide this one.
notification.icon = R.drawable.ic_placeholder;
notification.when = Long.MIN_VALUE;
} else {
// Ongoing icons are in the right side, so show this one.
updateNotification(notification, ticker);
notification.icon
= connected > 0 ? R.drawable.ic_stat_message : R.drawable.ic_stat_message_offline;
notification.when = System.currentTimeMillis();
} }
notification.contentView = chatViews; persistentNotificationBuilder.setWhen(message.getTimestamp().getTime());
notification.contentIntent = PendingIntent.getActivity(
application, 0, chatIntent, PendingIntent.FLAG_UPDATE_CURRENT); updateNotification(ticker);
notification.deleteIntent = clearNotifications;
persistentNotificationBuilder.setSmallIcon(connected > 0 ? R.drawable.ic_stat_message
: R.drawable.ic_stat_message_offline);
persistentNotificationBuilder.setContentIntent(PendingIntent.getActivity(
application, 0, chatIntent, PendingIntent.FLAG_UPDATE_CURRENT));
persistentNotificationBuilder.setDeleteIntent(clearNotifications);
try { try {
notify(CHAT_NOTIFICATION_ID, notification); notify(PERSISTENT_NOTIFICATION_ID, persistentNotificationBuilder.build());
} catch (RuntimeException e) { } catch (RuntimeException e) {
LogManager.exception(this, e); LogManager.exception(this, e);
// Try to remove avatar in order to avoid
// OutOfMemoryError on the Android system side.
chatViews.setImageViewResource(R.id.icon, R.drawable.ic_placeholder);
notify(CHAT_NOTIFICATION_ID, notification);
} }
} }
...@@ -499,30 +492,28 @@ public class NotificationManager implements OnInitializedListener, OnAccountChan ...@@ -499,30 +492,28 @@ public class NotificationManager implements OnInitializedListener, OnAccountChan
try { try {
notificationManager.notify(id, notification); notificationManager.notify(id, notification);
} catch (SecurityException e) { } catch (SecurityException e) {
LogManager.exception(this, e);
} }
} }
/** /**
* Update notification according to ticker. * Update notification according to ticker.
* *
* @param notification
* @param ticker * @param ticker
*/ */
private void updateNotification(Notification notification, private void updateNotification(MessageItem ticker) {
MessageItem ticker) {
if (ticker == null) { if (ticker == null) {
return; return;
} }
if (ticker.getChat().getFirstNotification() || !SettingsManager.eventsFirstOnly()) { if (ticker.getChat().getFirstNotification() || !SettingsManager.eventsFirstOnly()) {
setNotificationDefaults(notification, setNotificationDefaults(ChatManager.getInstance().isMakeVibro(ticker.getChat().getAccount(),
ChatManager.getInstance().isMakeVibro(ticker.getChat().getAccount(),
ticker.getChat().getUser()), ticker.getChat().getUser()),
PhraseManager.getInstance().getSound(ticker.getChat().getAccount(), PhraseManager.getInstance().getSound(ticker.getChat().getAccount(),
ticker.getChat().getUser(), ticker.getText()), ticker.getChat().getUser(), ticker.getText()),
AudioManager.STREAM_NOTIFICATION); AudioManager.STREAM_NOTIFICATION);
} }
if (ChatManager.getInstance().isShowText(ticker.getChat().getAccount(), ticker.getChat().getUser())) { if (ChatManager.getInstance().isShowText(ticker.getChat().getAccount(), ticker.getChat().getUser())) {
notification.tickerText = trimText(ticker.getText()); persistentNotificationBuilder.setTicker(ticker.getText());
} }
} }
...@@ -656,7 +647,7 @@ public class NotificationManager implements OnInitializedListener, OnAccountChan ...@@ -656,7 +647,7 @@ public class NotificationManager implements OnInitializedListener, OnAccountChan
} }
public Notification getPersistentNotification() { public Notification getPersistentNotification() {
return persistentNotification; return persistentNotificationBuilder.build();
} }
@Override @Override
......
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/status_bar_latest_event_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<LinearLayout
android:layout_width="@dimen/notification_large_icon_width"
android:layout_height="@dimen/notification_large_icon_height"
android:background="@drawable/notify_panel_notification_icon_bg_tile"
android:gravity="center"
>
<ImageView
android:id="@+id/icon"
android:layout_width="48dip"
android:layout_height="48dip"
android:src="@drawable/avatar_1_1" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:orientation="vertical"
android:paddingLeft="12dp"
android:paddingRight="12dp"
>
<LinearLayout
android:id="@+id/line1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<TextView android:id="@+id/title"
android:textAppearance="@style/NotificationTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:ellipsize="marquee"
android:fadingEdge="horizontal"
android:layout_weight="1"
/>
<TextView
android:id="@+id/time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0"
android:singleLine="true"
android:gravity="center"
android:paddingLeft="8dp"
android:text="22:11:00"
android:textAppearance="@style/NotificationText"
/>
</LinearLayout>
<TextView android:id="@+id/text2"
android:textAppearance="@style/NotificationText2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="-2dp"
android:layout_marginBottom="-2dp"
android:singleLine="true"
android:fadingEdge="horizontal"
android:ellipsize="marquee"
/>
<LinearLayout
android:id="@+id/line3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<TextView android:id="@+id/text"
android:textAppearance="@style/NotificationText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_gravity="center"
android:singleLine="true"
android:ellipsize="marquee"
android:fadingEdge="horizontal"
/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2013, Redsolution LTD. All rights reserved.
This file is part of Xabber project; you can redistribute it and/or
modify it under the terms of the GNU General Public License, Version 3.
Xabber 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, see http://www.gnu.org/licenses/.
-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="3dp">
<ImageView
android:id="@+id/icon"
android:layout_width="48dip"
android:layout_height="48dip"
android:layout_marginRight="6dip"
android:layout_centerVertical="true"
android:src="@drawable/avatar_1_1"
/>
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textStyle="bold"
android:singleLine="true"
android:gravity="bottom"
android:layout_toRightOf="@id/icon"
android:text="name"
style="@style/NotificationTitle"
/>
<TextView
android:id="@+id/time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:singleLine="true"
android:ellipsize="marquee"
android:layout_toRightOf="@id/icon"
android:layout_below="@id/title"
android:layout_marginRight="10dip"
android:text="22:11:00"
style="@style/NotificationText"
/>
<TextView
android:id="@+id/text2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:singleLine="true"
android:layout_below="@id/title"
android:layout_toRightOf="@id/time"
android:ellipsize="marquee"
android:text="text text text text text text text text text text text"
style="@style/NotificationText"
/>
<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:singleLine="true"
android:layout_below="@id/time"
android:layout_toRightOf="@id/icon"
android:text="1 message from 1 contact"
style="@style/NotificationText"
/>
</RelativeLayout>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment