added combined notifications settings - you can now use separate notifications for mentions
This commit is contained in:
parent
29ffac03ef
commit
3e9e91e871
|
@ -132,6 +132,10 @@ public interface TwidereConstants extends SharedPreferenceConstants, IntentConst
|
|||
String QUERY_PARAM_RECIPIENT_ID = "recipient_id";
|
||||
String QUERY_PARAM_READ_POSITION = "param_read_position";
|
||||
String QUERY_PARAM_READ_POSITIONS = "param_read_positions";
|
||||
String QUERY_PARAM_LIMIT = "limit";
|
||||
String QUERY_PARAM_EXTRA_ID = "extra_id";
|
||||
String QUERY_PARAM_TIMESTAMP = "timestamp";
|
||||
String QUERY_PARAM_FROM_NOTIFICATION = "from_notification";
|
||||
|
||||
String DEFAULT_PROTOCOL = PROTOCOL_HTTPS;
|
||||
|
||||
|
|
|
@ -310,5 +310,5 @@ public interface SharedPreferenceConstants {
|
|||
@Preference(type = BOOLEAN, hasDefault = true, defaultBoolean = true)
|
||||
String KEY_BUG_REPORTS = "bug_reports";
|
||||
@Preference(type = BOOLEAN, hasDefault = true, defaultBoolean = true)
|
||||
String COMBINED_NOTIFICATIONS = "combined_notifications";
|
||||
String KEY_COMBINED_NOTIFICATIONS = "combined_notifications";
|
||||
}
|
||||
|
|
|
@ -48,6 +48,7 @@ import edu.tsinghua.hotmobi.model.LatLng;
|
|||
import edu.tsinghua.hotmobi.model.LinkEvent;
|
||||
import edu.tsinghua.hotmobi.model.MediaEvent;
|
||||
import edu.tsinghua.hotmobi.model.NetworkEvent;
|
||||
import edu.tsinghua.hotmobi.model.NotificationEvent;
|
||||
import edu.tsinghua.hotmobi.model.RefreshEvent;
|
||||
import edu.tsinghua.hotmobi.model.ScrollRecord;
|
||||
import edu.tsinghua.hotmobi.model.SessionEvent;
|
||||
|
@ -95,6 +96,8 @@ public class HotMobiLogger {
|
|||
return "scroll";
|
||||
} else if (event instanceof BatteryRecord) {
|
||||
return "battery";
|
||||
} else if (event instanceof NotificationEvent) {
|
||||
return "notification";
|
||||
}
|
||||
throw new UnsupportedOperationException("Unknown event type " + event);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,171 @@
|
|||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
*
|
||||
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package edu.tsinghua.hotmobi.model;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import com.bluelinelabs.logansquare.annotation.JsonField;
|
||||
import com.bluelinelabs.logansquare.annotation.JsonObject;
|
||||
import com.bluelinelabs.logansquare.typeconverters.StringBasedTypeConverter;
|
||||
import com.hannesdorfmann.parcelableplease.annotation.ParcelablePlease;
|
||||
import com.hannesdorfmann.parcelableplease.annotation.ParcelableThisPlease;
|
||||
|
||||
import java.util.TimeZone;
|
||||
|
||||
import edu.tsinghua.hotmobi.HotMobiLogger;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/10/10.
|
||||
*/
|
||||
@ParcelablePlease
|
||||
@JsonObject
|
||||
public class NotificationEvent extends BaseEvent implements Parcelable {
|
||||
public static final Creator<NotificationEvent> CREATOR = new Creator<NotificationEvent>() {
|
||||
@Override
|
||||
public NotificationEvent createFromParcel(Parcel in) {
|
||||
return new NotificationEvent(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NotificationEvent[] newArray(int size) {
|
||||
return new NotificationEvent[size];
|
||||
}
|
||||
};
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "item_id")
|
||||
long itemId;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "account_id")
|
||||
long accountId;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "type")
|
||||
String type;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "action", typeConverter = Action.NotificationActionConverter.class)
|
||||
Action action;
|
||||
|
||||
public NotificationEvent() {
|
||||
}
|
||||
|
||||
public NotificationEvent(Parcel in) {
|
||||
super(in);
|
||||
NotificationEventParcelablePlease.readFromParcel(this, in);
|
||||
}
|
||||
|
||||
public Action getAction() {
|
||||
return action;
|
||||
}
|
||||
|
||||
public void setAction(Action action) {
|
||||
this.action = action;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public long getItemId() {
|
||||
return itemId;
|
||||
}
|
||||
|
||||
public void setItemId(long itemId) {
|
||||
this.itemId = itemId;
|
||||
}
|
||||
|
||||
public long getAccountId() {
|
||||
return accountId;
|
||||
}
|
||||
|
||||
public void setAccountId(long accountId) {
|
||||
this.accountId = accountId;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
super.writeToParcel(dest, flags);
|
||||
NotificationEventParcelablePlease.writeToParcel(this, dest, flags);
|
||||
}
|
||||
|
||||
public static NotificationEvent create(Context context, Action action, long postTime, long respondTime, String type, long accountId, long itemId) {
|
||||
final NotificationEvent event = new NotificationEvent();
|
||||
event.setAction(action);
|
||||
event.setStartTime(postTime);
|
||||
event.setEndTime(respondTime);
|
||||
event.setTimeOffset(TimeZone.getDefault().getOffset(postTime));
|
||||
event.setLocation(HotMobiLogger.getCachedLatLng(context));
|
||||
event.setType(type);
|
||||
event.setAccountId(accountId);
|
||||
event.setItemId(itemId);
|
||||
return event;
|
||||
}
|
||||
|
||||
public static NotificationEvent deleted(Context context, long postTime, String type, long accountId, long itemId) {
|
||||
return create(context, Action.DELETE, System.currentTimeMillis(), postTime, type, accountId, itemId);
|
||||
}
|
||||
|
||||
public static NotificationEvent open(Context context, long postTime, String type, long accountId, long itemId) {
|
||||
return create(context, Action.OPEN, System.currentTimeMillis(), postTime, type, accountId, itemId);
|
||||
}
|
||||
|
||||
public enum Action {
|
||||
OPEN("open"), DELETE("delete"), UNKNOWN("unknown");
|
||||
|
||||
private final String value;
|
||||
|
||||
Action(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public static Action parse(String action) {
|
||||
if (OPEN.value.equalsIgnoreCase(action)) {
|
||||
return OPEN;
|
||||
} else if (DELETE.value.equalsIgnoreCase(action)) {
|
||||
return DELETE;
|
||||
}
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
|
||||
public static class NotificationActionConverter extends StringBasedTypeConverter<Action> {
|
||||
|
||||
@Override
|
||||
public Action getFromString(String string) {
|
||||
return Action.parse(string);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String convertToString(Action action) {
|
||||
if (action == null) return null;
|
||||
return action.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -238,6 +238,7 @@ public class LinkHandlerActivity extends BaseAppCompatActivity implements System
|
|||
mMainContent.setOnFitSystemWindowsListener(this);
|
||||
setStatusBarColor(linkId, data);
|
||||
setTaskInfo(linkId, data);
|
||||
Utils.logOpenNotificationFromUri(this, data);
|
||||
if (!showFragment(linkId, data)) {
|
||||
finish();
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ import android.content.Context;
|
|||
import android.content.SharedPreferences;
|
||||
import android.media.RingtoneManager;
|
||||
import android.net.Uri;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.text.TextUtils;
|
||||
|
||||
|
@ -147,9 +148,9 @@ public class AccountPreferences implements Constants {
|
|||
return enabledIds;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@NonNull
|
||||
public static AccountPreferences[] getNotificationEnabledPreferences(final Context context, final long[] accountIds) {
|
||||
if (context == null || accountIds == null) return null;
|
||||
if (context == null || accountIds == null) return new AccountPreferences[0];
|
||||
final AccountPreferences[] temp = new AccountPreferences[accountIds.length];
|
||||
int i = 0;
|
||||
for (final long accountId : accountIds) {
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
*
|
||||
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.mariotaku.twidere.model;
|
||||
|
||||
import com.bluelinelabs.logansquare.annotation.JsonField;
|
||||
import com.bluelinelabs.logansquare.annotation.JsonObject;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/10/10.
|
||||
*/
|
||||
@JsonObject
|
||||
public class PebbleMessage {
|
||||
@JsonField(name = "title")
|
||||
String title;
|
||||
@JsonField(name = "body")
|
||||
String body;
|
||||
|
||||
public PebbleMessage() {
|
||||
|
||||
}
|
||||
|
||||
public PebbleMessage(String title, String body) {
|
||||
this.title = title;
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
public String getBody() {
|
||||
return body;
|
||||
}
|
||||
|
||||
public void setBody(String body) {
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
}
|
|
@ -99,6 +99,7 @@ import org.mariotaku.twidere.provider.TwidereDataStore.UnreadCounts;
|
|||
import org.mariotaku.twidere.receiver.NotificationReceiver;
|
||||
import org.mariotaku.twidere.service.BackgroundOperationService;
|
||||
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
|
||||
import org.mariotaku.twidere.util.DatabaseQueryUtils;
|
||||
import org.mariotaku.twidere.util.ImagePreloader;
|
||||
import org.mariotaku.twidere.util.MediaPreviewUtils;
|
||||
import org.mariotaku.twidere.util.ParseUtils;
|
||||
|
@ -179,7 +180,11 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
|
|||
};
|
||||
private boolean mNameFirst;
|
||||
|
||||
private static PendingIntent getDeleteIntent(Context context, String type, long accountId, long position) {
|
||||
private static PendingIntent getMarkReadDeleteIntent(Context context, String type, long accountId, long position) {
|
||||
return getMarkReadDeleteIntent(context, type, accountId, position, -1);
|
||||
}
|
||||
|
||||
private static PendingIntent getMarkReadDeleteIntent(Context context, String type, long accountId, long position, long extraId) {
|
||||
// Setup delete intent
|
||||
final Intent recvIntent = new Intent(context, NotificationReceiver.class);
|
||||
recvIntent.setAction(BROADCAST_NOTIFICATION_DELETED);
|
||||
|
@ -189,11 +194,13 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
|
|||
recvLinkBuilder.appendPath(type);
|
||||
recvLinkBuilder.appendQueryParameter(QUERY_PARAM_ACCOUNT_ID, String.valueOf(accountId));
|
||||
recvLinkBuilder.appendQueryParameter(QUERY_PARAM_READ_POSITION, String.valueOf(position));
|
||||
recvLinkBuilder.appendQueryParameter(QUERY_PARAM_EXTRA_ID, String.valueOf(extraId));
|
||||
recvLinkBuilder.appendQueryParameter(QUERY_PARAM_TIMESTAMP, String.valueOf(System.currentTimeMillis()));
|
||||
recvIntent.setData(recvLinkBuilder.build());
|
||||
return PendingIntent.getBroadcast(context, 0, recvIntent, 0);
|
||||
}
|
||||
|
||||
private static PendingIntent getDeleteIntent(Context context, String type, long accountId, StringLongPair[] positions) {
|
||||
private static PendingIntent getMarkReadDeleteIntent(Context context, String type, long accountId, StringLongPair[] positions) {
|
||||
// Setup delete intent
|
||||
final Intent recvIntent = new Intent(context, NotificationReceiver.class);
|
||||
final Uri.Builder recvLinkBuilder = new Uri.Builder();
|
||||
|
@ -202,6 +209,7 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
|
|||
recvLinkBuilder.appendPath(type);
|
||||
recvLinkBuilder.appendQueryParameter(QUERY_PARAM_ACCOUNT_ID, String.valueOf(accountId));
|
||||
recvLinkBuilder.appendQueryParameter(QUERY_PARAM_READ_POSITIONS, StringLongPair.toString(positions));
|
||||
recvLinkBuilder.appendQueryParameter(QUERY_PARAM_TIMESTAMP, String.valueOf(System.currentTimeMillis()));
|
||||
recvIntent.setData(recvLinkBuilder.build());
|
||||
return PendingIntent.getBroadcast(context, 0, recvIntent, 0);
|
||||
}
|
||||
|
@ -1048,7 +1056,6 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
|
|||
case TABLE_ID_STATUSES: {
|
||||
final AccountPreferences[] prefs = AccountPreferences.getNotificationEnabledPreferences(context,
|
||||
getAccountIds(context));
|
||||
assert prefs != null;
|
||||
for (final AccountPreferences pref : prefs) {
|
||||
if (!pref.isHomeTimelineNotificationEnabled()) continue;
|
||||
showTimelineNotification(pref, getPositionTag(TAB_TYPE_HOME_TIMELINE, pref.getAccountId()));
|
||||
|
@ -1059,10 +1066,10 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
|
|||
case TABLE_ID_MENTIONS: {
|
||||
final AccountPreferences[] prefs = AccountPreferences.getNotificationEnabledPreferences(context,
|
||||
getAccountIds(context));
|
||||
assert prefs != null;
|
||||
final boolean combined = mPreferences.getBoolean(KEY_COMBINED_NOTIFICATIONS);
|
||||
for (final AccountPreferences pref : prefs) {
|
||||
if (!pref.isMentionsNotificationEnabled()) continue;
|
||||
showMentionsNotification(pref, getPositionTag(TAB_TYPE_MENTIONS_TIMELINE, pref.getAccountId()));
|
||||
showMentionsNotification(pref, getPositionTag(TAB_TYPE_MENTIONS_TIMELINE, pref.getAccountId()), combined);
|
||||
}
|
||||
notifyUnreadCountChanged(NOTIFICATION_ID_MENTIONS_TIMELINE);
|
||||
break;
|
||||
|
@ -1070,7 +1077,6 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
|
|||
case TABLE_ID_DIRECT_MESSAGES_INBOX: {
|
||||
final AccountPreferences[] prefs = AccountPreferences.getNotificationEnabledPreferences(context,
|
||||
getAccountIds(context));
|
||||
assert prefs != null;
|
||||
for (final AccountPreferences pref : prefs) {
|
||||
if (!pref.isDirectMessagesNotificationEnabled()) continue;
|
||||
final StringLongPair[] pairs = mReadStateManager.getPositionPairs(TAB_TYPE_DIRECT_MESSAGES);
|
||||
|
@ -1147,7 +1153,7 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
|
|||
builder.setContentText(notificationContent);
|
||||
builder.setCategory(NotificationCompat.CATEGORY_SOCIAL);
|
||||
builder.setContentIntent(getContentIntent(context, AUTHORITY_HOME, accountId));
|
||||
builder.setDeleteIntent(getDeleteIntent(context, AUTHORITY_HOME, accountId, statusId));
|
||||
builder.setDeleteIntent(getMarkReadDeleteIntent(context, AUTHORITY_HOME, accountId, statusId));
|
||||
builder.setNumber(statusesCount);
|
||||
builder.setColor(pref.getNotificationLightColor());
|
||||
setNotificationPreferences(builder, pref, pref.getHomeTimelineNotificationType());
|
||||
|
@ -1163,7 +1169,7 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
|
|||
}
|
||||
}
|
||||
|
||||
private void showMentionsNotification(AccountPreferences pref, long position) {
|
||||
private void showMentionsNotification(AccountPreferences pref, long position, boolean combined) {
|
||||
final long accountId = pref.getAccountId();
|
||||
final Context context = getContext();
|
||||
final Resources resources = context.getResources();
|
||||
|
@ -1177,37 +1183,111 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
|
|||
selection = Expression.and(Expression.equals(Statuses.ACCOUNT_ID, accountId),
|
||||
Expression.greaterThan(Statuses.STATUS_ID, position));
|
||||
}
|
||||
|
||||
final int itemsLimit = 5;
|
||||
|
||||
final String filteredSelection = Utils.buildStatusFilterWhereClause(Mentions.TABLE_NAME,
|
||||
selection).getSQL();
|
||||
final String[] userProjection = {Statuses.USER_ID, Statuses.USER_NAME, Statuses.USER_SCREEN_NAME};
|
||||
final String[] statusProjection = {Statuses.STATUS_ID, Statuses.USER_ID, Statuses.USER_NAME, Statuses.USER_SCREEN_NAME,
|
||||
Statuses.TEXT_UNESCAPED, Statuses.STATUS_TIMESTAMP};
|
||||
final Cursor statusCursor = mDatabaseWrapper.query(Mentions.TABLE_NAME, statusProjection,
|
||||
filteredSelection, null, null, null, Statuses.SORT_ORDER_TIMESTAMP_DESC);
|
||||
filteredSelection, null, null, null, Statuses.SORT_ORDER_TIMESTAMP_DESC,
|
||||
String.valueOf(itemsLimit));
|
||||
final int statusesCount = DatabaseQueryUtils.count(mDatabaseWrapper.getSQLiteDatabase(),
|
||||
Mentions.TABLE_NAME, filteredSelection, null, null, null, null);
|
||||
|
||||
try {
|
||||
if (combined) {
|
||||
displayGroupedMentionsNotifications(pref, accountId, context, resources, nm,
|
||||
filteredSelection, statusCursor, statusesCount);
|
||||
} else {
|
||||
displaySeparateMentionsNotifications(pref, accountId, context, resources, nm,
|
||||
filteredSelection, statusCursor, statusesCount);
|
||||
}
|
||||
} finally {
|
||||
statusCursor.close();
|
||||
}
|
||||
}
|
||||
|
||||
private void displaySeparateMentionsNotifications(AccountPreferences pref, long accountId,
|
||||
Context context, Resources resources, NotificationManager nm,
|
||||
String filteredSelection, Cursor statusCursor, int statusesCount) {
|
||||
//noinspection TryFinallyCanBeTryWithResources
|
||||
if (statusCursor.getCount() == 0 || statusesCount == 0) return;
|
||||
final String accountName = Utils.getAccountName(context, accountId);
|
||||
final String accountScreenName = Utils.getAccountScreenName(context, accountId);
|
||||
final ParcelableStatus.CursorIndices indices = new ParcelableStatus.CursorIndices(statusCursor);
|
||||
|
||||
final UserColorNameManager manager = mUserColorNameManager;
|
||||
|
||||
// Setup notification
|
||||
final NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
|
||||
builder.setAutoCancel(true);
|
||||
builder.setSmallIcon(R.drawable.ic_stat_mention);
|
||||
|
||||
// Add rich notification and get latest tweet timestamp
|
||||
for (int i = 0, j = Math.min(statusCursor.getCount(), 5); statusCursor.moveToPosition(i) && i < j; i++) {
|
||||
final long statusId = statusCursor.getLong(indices.status_id);
|
||||
final String text = statusCursor.getString(indices.text_unescaped);
|
||||
final NotificationCompat.BigTextStyle style = new NotificationCompat.BigTextStyle();
|
||||
builder.setTicker(text);
|
||||
builder.setContentTitle(resources.getString(R.string.user_mentioned_you,
|
||||
manager.getDisplayName(statusCursor.getLong(indices.user_id),
|
||||
statusCursor.getString(indices.user_name),
|
||||
statusCursor.getString(indices.user_screen_name),
|
||||
mNameFirst, false)));
|
||||
builder.setContentText(text);
|
||||
builder.setCategory(NotificationCompat.CATEGORY_SOCIAL);
|
||||
builder.setContentIntent(getStatusContentIntent(context, accountId, statusId));
|
||||
builder.setDeleteIntent(getMarkReadDeleteIntent(context, AUTHORITY_MENTIONS, accountId,
|
||||
statusId, statusId));
|
||||
builder.setWhen(statusCursor.getLong(indices.status_timestamp));
|
||||
builder.setStyle(style);
|
||||
style.bigText(text);
|
||||
style.setSummaryText(mNameFirst ? accountName : accountScreenName);
|
||||
//TODO show account info
|
||||
try {
|
||||
nm.notify("mentions_" + accountId + "_" + statusId, NOTIFICATION_ID_MENTIONS_TIMELINE,
|
||||
builder.build());
|
||||
Utils.sendPebbleNotification(context, text);
|
||||
} catch (SecurityException e) {
|
||||
// Silently ignore
|
||||
}
|
||||
}
|
||||
|
||||
setNotificationPreferences(builder, pref, pref.getMentionsNotificationType());
|
||||
|
||||
}
|
||||
|
||||
private void displayGroupedMentionsNotifications(AccountPreferences pref, long accountId,
|
||||
Context context, Resources resources, NotificationManager nm,
|
||||
String filteredSelection, Cursor statusCursor, int statusesCount) {
|
||||
final String[] userProjection = {Statuses.USER_ID, Statuses.USER_NAME, Statuses.USER_SCREEN_NAME};
|
||||
final Cursor userCursor = mDatabaseWrapper.query(Mentions.TABLE_NAME, userProjection,
|
||||
filteredSelection, null, Statuses.USER_ID, null, Statuses.SORT_ORDER_TIMESTAMP_DESC);
|
||||
filteredSelection, null, Statuses.USER_ID, null, Statuses.SORT_ORDER_TIMESTAMP_DESC,
|
||||
"1");
|
||||
//noinspection TryFinallyCanBeTryWithResources
|
||||
try {
|
||||
final int usersCount = userCursor.getCount();
|
||||
final int statusesCount = statusCursor.getCount();
|
||||
final int usersCount = DatabaseQueryUtils.count(mDatabaseWrapper.getSQLiteDatabase(),
|
||||
Mentions.TABLE_NAME, filteredSelection, null, Statuses.USER_ID, null, null);
|
||||
if (statusesCount == 0 || usersCount == 0) return;
|
||||
final String accountName = Utils.getAccountName(context, accountId);
|
||||
final String accountScreenName = Utils.getAccountScreenName(context, accountId);
|
||||
final int idxStatusText = statusCursor.getColumnIndex(Statuses.TEXT_UNESCAPED),
|
||||
idxStatusId = statusCursor.getColumnIndex(Statuses.STATUS_ID),
|
||||
idxStatusTimestamp = statusCursor.getColumnIndex(Statuses.STATUS_TIMESTAMP),
|
||||
idxStatusUserId = statusCursor.getColumnIndex(Statuses.USER_ID),
|
||||
idxStatusUserName = statusCursor.getColumnIndex(Statuses.USER_NAME),
|
||||
idxStatusUserScreenName = statusCursor.getColumnIndex(Statuses.USER_SCREEN_NAME),
|
||||
idxUserName = userCursor.getColumnIndex(Statuses.USER_NAME),
|
||||
idxUserScreenName = userCursor.getColumnIndex(Statuses.USER_NAME),
|
||||
idxUserId = userCursor.getColumnIndex(Statuses.USER_NAME);
|
||||
idxUserScreenName = userCursor.getColumnIndex(Statuses.USER_SCREEN_NAME),
|
||||
idxUserId = userCursor.getColumnIndex(Statuses.USER_ID);
|
||||
|
||||
final CharSequence notificationTitle = resources.getQuantityString(R.plurals.N_new_mentions,
|
||||
statusesCount, statusesCount);
|
||||
final String notificationContent;
|
||||
userCursor.moveToFirst();
|
||||
final UserColorNameManager manager = UserColorNameManager.getInstance(context);
|
||||
final String displayName = manager.getUserNickname(userCursor.getLong(idxUserId),
|
||||
final String displayName = mUserColorNameManager.getUserNickname(userCursor.getLong(idxUserId),
|
||||
mNameFirst ? userCursor.getString(idxUserName) : userCursor.getString(idxUserScreenName));
|
||||
if (usersCount == 1) {
|
||||
notificationContent = context.getString(R.string.notification_mention, displayName);
|
||||
|
@ -1219,7 +1299,7 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
|
|||
// Add rich notification and get latest tweet timestamp
|
||||
long when = -1, statusId = -1;
|
||||
final InboxStyle style = new InboxStyle();
|
||||
for (int i = 0, j = Math.min(statusesCount, 5); statusCursor.moveToPosition(i) && i < j; i++) {
|
||||
for (int i = 0, j = Math.min(statusCursor.getCount(), 5); statusCursor.moveToPosition(i) && i < j; i++) {
|
||||
if (when == -1) {
|
||||
when = statusCursor.getLong(idxStatusTimestamp);
|
||||
}
|
||||
|
@ -1227,7 +1307,7 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
|
|||
statusId = statusCursor.getLong(idxStatusId);
|
||||
}
|
||||
final SpannableStringBuilder sb = new SpannableStringBuilder();
|
||||
sb.append(manager.getUserNickname(statusCursor.getLong(idxUserId),
|
||||
sb.append(mUserColorNameManager.getUserNickname(statusCursor.getLong(idxStatusUserId),
|
||||
mNameFirst ? statusCursor.getString(idxStatusUserName) : statusCursor.getString(idxStatusUserScreenName)));
|
||||
sb.setSpan(new StyleSpan(Typeface.BOLD), 0, sb.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
sb.append(' ');
|
||||
|
@ -1249,11 +1329,10 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
|
|||
builder.setContentText(notificationContent);
|
||||
builder.setCategory(NotificationCompat.CATEGORY_SOCIAL);
|
||||
builder.setContentIntent(getContentIntent(context, AUTHORITY_MENTIONS, accountId));
|
||||
builder.setDeleteIntent(getDeleteIntent(context, AUTHORITY_MENTIONS, accountId, statusId));
|
||||
builder.setDeleteIntent(getMarkReadDeleteIntent(context, AUTHORITY_MENTIONS, accountId, statusId));
|
||||
builder.setNumber(statusesCount);
|
||||
builder.setWhen(when);
|
||||
builder.setStyle(style);
|
||||
builder.setColor(pref.getNotificationLightColor());
|
||||
setNotificationPreferences(builder, pref, pref.getMentionsNotificationType());
|
||||
try {
|
||||
nm.notify("mentions_" + accountId, NOTIFICATION_ID_MENTIONS_TIMELINE,
|
||||
|
@ -1263,7 +1342,6 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
|
|||
// Silently ignore
|
||||
}
|
||||
} finally {
|
||||
statusCursor.close();
|
||||
userCursor.close();
|
||||
}
|
||||
}
|
||||
|
@ -1275,6 +1353,24 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
|
|||
homeLinkBuilder.scheme(SCHEME_TWIDERE);
|
||||
homeLinkBuilder.authority(type);
|
||||
homeLinkBuilder.appendQueryParameter(QUERY_PARAM_ACCOUNT_ID, String.valueOf(accountId));
|
||||
homeLinkBuilder.appendQueryParameter(QUERY_PARAM_FROM_NOTIFICATION, String.valueOf(true));
|
||||
homeLinkBuilder.appendQueryParameter(QUERY_PARAM_TIMESTAMP, String.valueOf(System.currentTimeMillis()));
|
||||
homeIntent.setData(homeLinkBuilder.build());
|
||||
return PendingIntent.getActivity(context, 0, homeIntent, 0);
|
||||
}
|
||||
|
||||
private PendingIntent getStatusContentIntent(Context context, long accountId, long statusId) {
|
||||
// Setup click intent
|
||||
final Intent homeIntent = new Intent(Intent.ACTION_VIEW);
|
||||
homeIntent.setPackage(BuildConfig.APPLICATION_ID);
|
||||
final Uri.Builder homeLinkBuilder = new Uri.Builder();
|
||||
homeLinkBuilder.scheme(SCHEME_TWIDERE);
|
||||
homeLinkBuilder.authority(AUTHORITY_STATUS);
|
||||
homeLinkBuilder.appendQueryParameter(QUERY_PARAM_ACCOUNT_ID, String.valueOf(accountId));
|
||||
homeLinkBuilder.appendQueryParameter(QUERY_PARAM_STATUS_ID, String.valueOf(statusId));
|
||||
homeLinkBuilder.appendQueryParameter(QUERY_PARAM_EXTRA_ID, String.valueOf(statusId));
|
||||
homeLinkBuilder.appendQueryParameter(QUERY_PARAM_FROM_NOTIFICATION, String.valueOf(true));
|
||||
homeLinkBuilder.appendQueryParameter(QUERY_PARAM_TIMESTAMP, String.valueOf(System.currentTimeMillis()));
|
||||
homeIntent.setData(homeLinkBuilder.build());
|
||||
return PendingIntent.getActivity(context, 0, homeIntent, 0);
|
||||
}
|
||||
|
@ -1297,6 +1393,7 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
|
|||
} else {
|
||||
notificationDefaults &= ~(NotificationCompat.DEFAULT_VIBRATE | NotificationCompat.DEFAULT_SOUND);
|
||||
}
|
||||
builder.setColor(pref.getNotificationLightColor());
|
||||
builder.setDefaults(notificationDefaults);
|
||||
}
|
||||
|
||||
|
@ -1421,7 +1518,7 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
|
|||
builder.setContentText(notificationContent);
|
||||
builder.setCategory(NotificationCompat.CATEGORY_SOCIAL);
|
||||
builder.setContentIntent(getContentIntent(context, AUTHORITY_DIRECT_MESSAGES, accountId));
|
||||
builder.setDeleteIntent(getDeleteIntent(context, AUTHORITY_DIRECT_MESSAGES, accountId, positions));
|
||||
builder.setDeleteIntent(getMarkReadDeleteIntent(context, AUTHORITY_DIRECT_MESSAGES, accountId, positions));
|
||||
builder.setNumber(messagesCount);
|
||||
builder.setWhen(when);
|
||||
builder.setStyle(style);
|
||||
|
|
|
@ -33,6 +33,9 @@ import org.mariotaku.twidere.util.ReadStateManager;
|
|||
import org.mariotaku.twidere.util.Utils;
|
||||
import org.mariotaku.twidere.util.dagger.ApplicationModule;
|
||||
|
||||
import edu.tsinghua.hotmobi.HotMobiLogger;
|
||||
import edu.tsinghua.hotmobi.model.NotificationEvent;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/4/4.
|
||||
*/
|
||||
|
@ -45,12 +48,19 @@ public class NotificationReceiver extends BroadcastReceiver implements Constants
|
|||
case BROADCAST_NOTIFICATION_DELETED: {
|
||||
final Uri uri = intent.getData();
|
||||
if (uri == null) return;
|
||||
final String tag = getPositionTag(uri.getLastPathSegment());
|
||||
if (tag == null) return;
|
||||
final String type = uri.getLastPathSegment();
|
||||
final long accountId = ParseUtils.parseLong(uri.getQueryParameter(QUERY_PARAM_ACCOUNT_ID), -1);
|
||||
final ReadStateManager manager = ApplicationModule.get(context).getReadStateManager();
|
||||
final long extraId = ParseUtils.parseLong(uri.getQueryParameter(QUERY_PARAM_EXTRA_ID), -1);
|
||||
final long timestamp = ParseUtils.parseLong(uri.getQueryParameter(QUERY_PARAM_TIMESTAMP), -1);
|
||||
final ApplicationModule module = ApplicationModule.get(context);
|
||||
if (AUTHORITY_MENTIONS.equals(type) && accountId != -1 && extraId != -1 && timestamp != -1) {
|
||||
final HotMobiLogger logger = module.getHotMobiLogger();
|
||||
logger.log(accountId, NotificationEvent.deleted(context, timestamp, type, accountId, extraId));
|
||||
}
|
||||
final ReadStateManager manager = module.getReadStateManager();
|
||||
final String paramReadPosition, paramReadPositions;
|
||||
if (!TextUtils.isEmpty(paramReadPosition = uri.getQueryParameter(QUERY_PARAM_READ_POSITION))) {
|
||||
final String tag = getPositionTag(type);
|
||||
if (tag != null && !TextUtils.isEmpty(paramReadPosition = uri.getQueryParameter(QUERY_PARAM_READ_POSITION))) {
|
||||
manager.setPosition(Utils.getReadPositionTagWithAccounts(tag, accountId),
|
||||
ParseUtils.parseLong(paramReadPosition, -1));
|
||||
} else if (!TextUtils.isEmpty(paramReadPositions = uri.getQueryParameter(QUERY_PARAM_READ_POSITIONS))) {
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
*
|
||||
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.mariotaku.twidere.util;
|
||||
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
|
||||
import org.mariotaku.sqliteqb.library.SQLFunctions;
|
||||
|
||||
public class DatabaseQueryUtils {
|
||||
|
||||
public static int count(final SQLiteDatabase db, final String table, final String selection,
|
||||
final String[] selectionArgs, final String groupBy, final String having, final String orderBy) {
|
||||
if (db == null) return -1;
|
||||
final Cursor c = db.query(table, new String[]{SQLFunctions.COUNT()}, selection, selectionArgs, groupBy, having, orderBy);
|
||||
try {
|
||||
if (c.moveToFirst()) return c.getInt(0);
|
||||
return -1;
|
||||
} finally {
|
||||
c.close();
|
||||
}
|
||||
}
|
||||
|
||||
public static int count(final SQLiteDatabase db, boolean distinct, String table, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit) {
|
||||
if (db == null) return -1;
|
||||
final Cursor c = db.query(distinct, table, new String[]{SQLFunctions.COUNT()}, selection, selectionArgs, groupBy, having, orderBy, limit);
|
||||
try {
|
||||
if (c.moveToFirst()) return c.getInt(0);
|
||||
return -1;
|
||||
} finally {
|
||||
c.close();
|
||||
}
|
||||
}
|
||||
|
||||
public static int count(final SQLiteDatabase db, String table, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit) {
|
||||
if (db == null) return -1;
|
||||
final Cursor c = db.query(table, new String[]{SQLFunctions.COUNT()}, selection, selectionArgs, groupBy, having, orderBy, limit);
|
||||
try {
|
||||
if (c.moveToFirst()) return c.getInt(0);
|
||||
return -1;
|
||||
} finally {
|
||||
c.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
*
|
||||
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.mariotaku.twidere.util;
|
||||
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import com.bluelinelabs.logansquare.LoganSquare;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/8/6.
|
||||
*/
|
||||
public class JsonSerializer {
|
||||
@Nullable
|
||||
public static <T> String serialize(@Nullable final List<T> list, final Class<T> cls) {
|
||||
if (list == null) return null;
|
||||
try {
|
||||
return LoganSquare.serialize(list, cls);
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static <T> String serialize(@Nullable final T object, final Class<T> cls) {
|
||||
if (object == null) return null;
|
||||
try {
|
||||
return LoganSquare.mapperFor(cls).serialize(object);
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static <T> String serializeArray(@Nullable final T[] object, final Class<T> cls) {
|
||||
if (object == null) return null;
|
||||
try {
|
||||
return LoganSquare.mapperFor(cls).serialize(Arrays.asList(object));
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static <T> List<T> parseList(@Nullable final String string, final Class<T> cls) {
|
||||
if (string == null) return null;
|
||||
try {
|
||||
return LoganSquare.mapperFor(cls).parseList(string);
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static <T> T[] parseArray(@Nullable final String string, final Class<T> cls) {
|
||||
if (string == null) return null;
|
||||
try {
|
||||
final List<T> list = LoganSquare.mapperFor(cls).parseList(string);
|
||||
//noinspection unchecked
|
||||
return list.toArray((T[]) Array.newInstance(cls, list.size()));
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static <T> T parse(@Nullable final String string, final Class<T> cls) {
|
||||
if (string == null) return null;
|
||||
try {
|
||||
return LoganSquare.mapperFor(cls).parse(string);
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static <T> String serialize(@Nullable final T obj) {
|
||||
if (obj == null) return null;
|
||||
//noinspection unchecked
|
||||
return serialize(obj, (Class<T>) obj.getClass());
|
||||
}
|
||||
}
|
|
@ -48,10 +48,10 @@ public class PermissionsManager implements Constants {
|
|||
mPackageManager = context.getPackageManager();
|
||||
}
|
||||
|
||||
public boolean accept(final String package_name, final String[] permissions) {
|
||||
if (package_name == null || permissions == null) return false;
|
||||
public boolean accept(final String packageName, final String[] permissions) {
|
||||
if (packageName == null || permissions == null) return false;
|
||||
final SharedPreferences.Editor editor = mPreferences.edit();
|
||||
editor.putString(package_name, TwidereArrayUtils.toString(permissions, '|', false));
|
||||
editor.putString(packageName, TwidereArrayUtils.toString(permissions, '|', false));
|
||||
return editor.commit();
|
||||
}
|
||||
|
||||
|
|
|
@ -115,9 +115,7 @@ import android.widget.Toast;
|
|||
import com.bluelinelabs.logansquare.LoganSquare;
|
||||
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.mariotaku.restfu.RestAPIFactory;
|
||||
import org.mariotaku.restfu.RestClient;
|
||||
import org.mariotaku.restfu.http.Authorization;
|
||||
|
@ -199,6 +197,7 @@ import org.mariotaku.twidere.model.ParcelableMedia;
|
|||
import org.mariotaku.twidere.model.ParcelableStatus;
|
||||
import org.mariotaku.twidere.model.ParcelableUser;
|
||||
import org.mariotaku.twidere.model.ParcelableUserList;
|
||||
import org.mariotaku.twidere.model.PebbleMessage;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.Accounts;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.Activities;
|
||||
|
@ -228,6 +227,7 @@ import org.mariotaku.twidere.provider.TwidereDataStore.UnreadCounts;
|
|||
import org.mariotaku.twidere.service.RefreshService;
|
||||
import org.mariotaku.twidere.util.TwidereLinkify.HighlightStyle;
|
||||
import org.mariotaku.twidere.util.content.ContentResolverUtils;
|
||||
import org.mariotaku.twidere.util.dagger.ApplicationModule;
|
||||
import org.mariotaku.twidere.util.menu.TwidereMenuInfo;
|
||||
import org.mariotaku.twidere.view.CardMediaContainer.OnMediaClickListener;
|
||||
import org.mariotaku.twidere.view.CardMediaContainer.PreviewStyle;
|
||||
|
@ -248,7 +248,6 @@ import java.util.ArrayList;
|
|||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map.Entry;
|
||||
|
@ -258,6 +257,9 @@ import java.util.zip.CRC32;
|
|||
|
||||
import javax.net.ssl.SSLException;
|
||||
|
||||
import edu.tsinghua.hotmobi.HotMobiLogger;
|
||||
import edu.tsinghua.hotmobi.model.NotificationEvent;
|
||||
|
||||
import static android.text.TextUtils.isEmpty;
|
||||
import static android.text.format.DateUtils.getRelativeTimeSpanString;
|
||||
import static org.mariotaku.twidere.provider.TwidereDataStore.CACHE_URIS;
|
||||
|
@ -3944,6 +3946,21 @@ public final class Utils implements Constants {
|
|||
return isOutOfMemory(cause);
|
||||
}
|
||||
|
||||
public static void logOpenNotificationFromUri(Context context, Uri uri) {
|
||||
if (!uri.getBooleanQueryParameter(QUERY_PARAM_FROM_NOTIFICATION, false)) return;
|
||||
String type = uri.getLastPathSegment();
|
||||
if (type == null) {
|
||||
type = uri.getAuthority();
|
||||
}
|
||||
final long accountId = ParseUtils.parseLong(uri.getQueryParameter(QUERY_PARAM_ACCOUNT_ID), -1);
|
||||
final long extraId = ParseUtils.parseLong(uri.getQueryParameter(QUERY_PARAM_EXTRA_ID), -1);
|
||||
final long timestamp = ParseUtils.parseLong(uri.getQueryParameter(QUERY_PARAM_TIMESTAMP), -1);
|
||||
if (!AUTHORITY_STATUS.equals(type) || accountId < 0 || extraId < 0 || timestamp < 0) return;
|
||||
final ApplicationModule module = ApplicationModule.get(context);
|
||||
final HotMobiLogger logger = module.getHotMobiLogger();
|
||||
logger.log(accountId, NotificationEvent.open(context, timestamp, type, accountId, extraId));
|
||||
}
|
||||
|
||||
static class UtilsL {
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
|
@ -3995,20 +4012,15 @@ public final class Utils implements Constants {
|
|||
|
||||
if (prefs.getBoolean(KEY_PEBBLE_NOTIFICATIONS, false)) {
|
||||
|
||||
final String app_name = context.getString(R.string.app_name);
|
||||
final String appName = context.getString(R.string.app_name);
|
||||
|
||||
final HashMap<String, String> data = new HashMap<>();
|
||||
data.put("title", app_name);
|
||||
data.put("body", message);
|
||||
|
||||
final JSONObject jsonData = new JSONObject(data);
|
||||
|
||||
final String notificationData = new JSONArray().put(jsonData).toString();
|
||||
final List<PebbleMessage> messages = new ArrayList<>();
|
||||
messages.add(new PebbleMessage(appName, message));
|
||||
|
||||
final Intent intent = new Intent(INTENT_ACTION_PEBBLE_NOTIFICATION);
|
||||
intent.putExtra("messageType", "PEBBLE_ALERT");
|
||||
intent.putExtra("sender", app_name);
|
||||
intent.putExtra("notificationData", notificationData);
|
||||
intent.putExtra("sender", appName);
|
||||
intent.putExtra("notificationData", JsonSerializer.serialize(messages, PebbleMessage.class));
|
||||
|
||||
context.getApplicationContext().sendBroadcast(intent);
|
||||
}
|
||||
|
|
|
@ -791,4 +791,5 @@
|
|||
<string name="combined_notifications_summary_on">Notifications will be grouped</string>
|
||||
<string name="combined_notifications_summary_off">Notifications will be displayed separately</string>
|
||||
<string name="save_media_no_storage_permission_message">Storage permission is needed to save media.</string>
|
||||
<string name="user_mentioned_you"><xliff:g id="name">%s</xliff:g> mentioned you</string>
|
||||
</resources>
|
|
@ -18,7 +18,7 @@
|
|||
android:title="@string/silent_notifications" />
|
||||
|
||||
<org.mariotaku.twidere.preference.AutoFixCheckBoxPreference
|
||||
android:defaultValue="false"
|
||||
android:defaultValue="true"
|
||||
android:key="combined_notifications"
|
||||
android:summaryOff="@string/combined_notifications_summary_off"
|
||||
android:summaryOn="@string/combined_notifications_summary_on"
|
||||
|
|
Loading…
Reference in New Issue