Commit aa7eb67a authored by Yusuke Iwaki's avatar Yusuke Iwaki Committed by GitHub

Merge pull request #171 from RocketChat/remove_reactive_notifiation

remove Reactive Notification
parents ebd441ce d3d8bef0
...@@ -40,8 +40,6 @@ ...@@ -40,8 +40,6 @@
<service android:name=".service.RocketChatService" /> <service android:name=".service.RocketChatService" />
<service android:name=".service.notification.NotificationDismissalCallbackService" />
<receiver <receiver
android:name="com.google.android.gms.gcm.GcmReceiver" android:name="com.google.android.gms.gcm.GcmReceiver"
android:exported="true" android:exported="true"
......
package chat.rocket.android.model.internal;
import io.realm.RealmObject;
import io.realm.annotations.PrimaryKey;
/**
* ViewData model for notification.
*/
public class NotificationItem extends RealmObject {
@SuppressWarnings({"PMD.ShortVariable"})
public static final String ID = "roomId";
public static final String TITLE = "title";
public static final String DESCRIPTION = "description";
public static final String UNREAD_COUNT = "unreadCount";
public static final String SENDER_NAME = "senderName";
public static final String CONTENT_UPDATED_AT = "contentUpdatedAt";
public static final String LAST_SEEN_AT = "lastSeenAt";
@PrimaryKey private String roomId;
private String title;
private String description;
private int unreadCount;
private String senderName;
private long contentUpdatedAt; //subscription._updatedAt
private long lastSeenAt; //max(notification dismissed, subscription.ls)
public String getRoomId() {
return roomId;
}
public void setRoomId(String roomId) {
this.roomId = roomId;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public int getUnreadCount() {
return unreadCount;
}
public void setUnreadCount(int unreadCount) {
this.unreadCount = unreadCount;
}
public String getSenderName() {
return senderName;
}
public void setSenderName(String senderName) {
this.senderName = senderName;
}
public long getContentUpdatedAt() {
return contentUpdatedAt;
}
public void setContentUpdatedAt(long contentUpdatedAt) {
this.contentUpdatedAt = contentUpdatedAt;
}
public long getLastSeenAt() {
return lastSeenAt;
}
public void setLastSeenAt(long lastSeenAt) {
this.lastSeenAt = lastSeenAt;
}
}
...@@ -32,7 +32,6 @@ import chat.rocket.android.service.observer.LoadMessageProcedureObserver; ...@@ -32,7 +32,6 @@ import chat.rocket.android.service.observer.LoadMessageProcedureObserver;
import chat.rocket.android.service.observer.MethodCallObserver; import chat.rocket.android.service.observer.MethodCallObserver;
import chat.rocket.android.service.observer.NewMessageObserver; import chat.rocket.android.service.observer.NewMessageObserver;
import chat.rocket.android.service.observer.PushSettingsObserver; import chat.rocket.android.service.observer.PushSettingsObserver;
import chat.rocket.android.service.observer.ReactiveNotificationManager;
import chat.rocket.android.service.observer.SessionObserver; import chat.rocket.android.service.observer.SessionObserver;
import chat.rocket.android.service.observer.TokenLoginObserver; import chat.rocket.android.service.observer.TokenLoginObserver;
import chat.rocket.android_ddp.DDPClientCallback; import chat.rocket.android_ddp.DDPClientCallback;
...@@ -53,7 +52,6 @@ public class RocketChatWebSocketThread extends HandlerThread { ...@@ -53,7 +52,6 @@ public class RocketChatWebSocketThread extends HandlerThread {
GetUsersOfRoomsProcedureObserver.class, GetUsersOfRoomsProcedureObserver.class,
NewMessageObserver.class, NewMessageObserver.class,
CurrentUserObserver.class, CurrentUserObserver.class,
ReactiveNotificationManager.class,
FileUploadingToS3Observer.class, FileUploadingToS3Observer.class,
FileUploadingWithUfsObserver.class, FileUploadingWithUfsObserver.class,
PushSettingsObserver.class, PushSettingsObserver.class,
......
package chat.rocket.android.service.notification;
import android.app.IntentService;
import android.content.Intent;
import chat.rocket.android.model.internal.NotificationItem;
import chat.rocket.android.realm_helper.RealmHelper;
import chat.rocket.android.realm_helper.RealmStore;
/**
* triggered when notification is dismissed.
*/
public class NotificationDismissalCallbackService extends IntentService {
public NotificationDismissalCallbackService() {
super(NotificationDismissalCallbackService.class.getSimpleName());
}
@Override
protected void onHandleIntent(Intent intent) {
if (!intent.hasExtra("serverConfigId") || !intent.hasExtra("roomId")) {
return;
}
String serverConfigId = intent.getStringExtra("serverConfigId");
String roomId = intent.getStringExtra("roomId");
RealmHelper realmHelper = RealmStore.get(serverConfigId);
if (realmHelper == null) {
return;
}
realmHelper.executeTransaction(realm -> {
NotificationItem item =
realm.where(NotificationItem.class).equalTo(NotificationItem.ID, roomId).findFirst();
if (item != null) {
long currentTime = System.currentTimeMillis();
if (item.getLastSeenAt() <= currentTime) {
item.setLastSeenAt(currentTime);
}
}
return null;
});
}
}
package chat.rocket.android.service.observer;
import android.app.Notification;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationManagerCompat;
import android.support.v4.content.ContextCompat;
import io.realm.Realm;
import io.realm.RealmResults;
import java.util.List;
import bolts.Task;
import chat.rocket.android.R;
import chat.rocket.android.activity.MainActivity;
import chat.rocket.android.api.DDPClientWrapper;
import chat.rocket.android.helper.Avatar;
import chat.rocket.android.helper.TextUtils;
import chat.rocket.android.model.ServerConfig;
import chat.rocket.android.model.internal.NotificationItem;
import chat.rocket.android.realm_helper.RealmHelper;
import chat.rocket.android.realm_helper.RealmStore;
import chat.rocket.android.service.notification.NotificationDismissalCallbackService;
/**
* observes NotificationItem and notify/cancel notification.
*/
public class NotificationItemObserver extends AbstractModelObserver<NotificationItem> {
public NotificationItemObserver(Context context, String hostname, RealmHelper realmHelper,
DDPClientWrapper ddpClient) {
super(context, hostname, realmHelper, ddpClient);
}
@Override
public RealmResults<NotificationItem> queryItems(Realm realm) {
return realm.where(NotificationItem.class).findAll();
}
@Override
public void onUpdateResults(List<NotificationItem> results) {
if (results.isEmpty()) {
return;
}
for (NotificationItem item : results) {
final String notificationId = item.getRoomId();
if (item.getUnreadCount() > 0
&& item.getContentUpdatedAt() > item.getLastSeenAt()) {
generateNotificationFor(item)
.onSuccess(task -> {
Notification notification = task.getResult();
if (notification != null) {
NotificationManagerCompat.from(context)
.notify(notificationId.hashCode(), notification);
}
return null;
});
} else {
NotificationManagerCompat.from(context).cancel(notificationId.hashCode());
}
}
}
private Task<Notification> generateNotificationFor(NotificationItem item) {
final String username = item.getSenderName();
final String roomId = item.getRoomId();
final String title = item.getTitle();
final String description = TextUtils.or(item.getDescription(), "").toString();
final int unreadCount = item.getUnreadCount();
if (TextUtils.isEmpty(username)) {
return Task.forResult(generateNotification(roomId, title, description, unreadCount, null));
}
int size = context.getResources().getDimensionPixelSize(R.dimen.notification_avatar_size);
return new Avatar(hostname, username).getBitmap(context, size)
.continueWithTask(task -> {
Bitmap icon = task.isFaulted() ? null : task.getResult();
final Notification notification =
generateNotification(roomId, title, description, unreadCount, icon);
return Task.forResult(notification);
});
}
private PendingIntent getContentIntent(String roomId) {
Intent intent = new Intent(context, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_CLEAR_TOP);
ServerConfig config = RealmStore.getDefault().executeTransactionForRead(realm ->
realm.where(ServerConfig.class).equalTo(ServerConfig.HOSTNAME, hostname).findFirst());
if (config != null) {
intent.putExtra("serverConfigId", config.getServerConfigId());
intent.putExtra("roomId", roomId);
}
return PendingIntent.getActivity(context.getApplicationContext(),
(int) (System.currentTimeMillis() % Integer.MAX_VALUE),
intent, PendingIntent.FLAG_ONE_SHOT);
}
private PendingIntent getDeleteIntent(String roomId) {
Intent intent = new Intent(context, NotificationDismissalCallbackService.class);
ServerConfig config = RealmStore.getDefault().executeTransactionForRead(realm ->
realm.where(ServerConfig.class).equalTo(ServerConfig.HOSTNAME, hostname).findFirst());
if (config != null) {
intent.putExtra("serverConfigId", config.getServerConfigId());
intent.putExtra("roomId", roomId);
}
return PendingIntent.getService(context.getApplicationContext(),
(int) (System.currentTimeMillis() % Integer.MAX_VALUE),
intent, PendingIntent.FLAG_ONE_SHOT);
}
private Notification generateNotification(String roomId, String title,
@NonNull String description, int unreadCount,
@Nullable Bitmap icon) {
NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
.setContentTitle(title)
.setContentText(description)
.setNumber(unreadCount)
.setColor(ContextCompat.getColor(context, R.color.colorPrimary))
.setSmallIcon(R.drawable.rocket_chat_notification)
.setContentIntent(getContentIntent(roomId))
.setDeleteIntent(getDeleteIntent(roomId));
if (icon != null) {
builder.setLargeIcon(icon);
}
if (description.length() > 20) {
return new NotificationCompat.BigTextStyle(builder)
.bigText(description)
.build();
} else {
return builder.build();
}
}
}
package chat.rocket.android.service.observer;
import android.content.Context;
import io.realm.Realm;
import io.realm.RealmResults;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.List;
import chat.rocket.android.api.DDPClientWrapper;
import chat.rocket.android.helper.LogcatIfError;
import chat.rocket.android.log.RCLog;
import chat.rocket.android.model.ddp.RoomSubscription;
import chat.rocket.android.model.internal.NotificationItem;
import chat.rocket.android.realm_helper.RealmHelper;
/**
* observing room subscriptions with unread>0.
*/
public class ReactiveNotificationManager extends AbstractModelObserver<RoomSubscription> {
public ReactiveNotificationManager(Context context, String hostname,
RealmHelper realmHelper, DDPClientWrapper ddpClient) {
super(context, hostname, realmHelper, ddpClient);
}
@Override
public RealmResults<RoomSubscription> queryItems(Realm realm) {
return realm.where(RoomSubscription.class)
.equalTo(RoomSubscription.OPEN, true)
.findAll();
}
@Override
public void onUpdateResults(List<RoomSubscription> roomSubscriptions) {
JSONArray notifications = new JSONArray();
for (RoomSubscription roomSubscription : roomSubscriptions) {
final String roomId = roomSubscription.getRoomId();
NotificationItem item = realmHelper.executeTransactionForRead(realm ->
realm.where(NotificationItem.class).equalTo(NotificationItem.ID, roomId).findFirst());
long lastSeenAt = Math
.max(item != null ? item.getLastSeenAt() : 0, roomSubscription.getLastSeen());
try {
JSONObject notification = new JSONObject()
.put("roomId", roomSubscription.getRoomId())
.put("title", roomSubscription.getName())
.put("description", "new message")
.put("unreadCount", roomSubscription.getUnread())
.put("contentUpdatedAt", roomSubscription.getUpdatedAt())
.put("lastSeenAt", lastSeenAt);
if (RoomSubscription.TYPE_DIRECT_MESSAGE.equals(roomSubscription.getType())) {
notification.put("senderName", roomSubscription.getName());
} else {
notification.put("senderName", JSONObject.NULL);
}
notifications.put(notification);
} catch (JSONException exception) {
RCLog.w(exception);
}
}
realmHelper.executeTransaction(realm -> {
realm.createOrUpdateAllFromJson(NotificationItem.class, notifications);
return null;
}).continueWith(new LogcatIfError());
}
}
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