notifications alpha 2

This commit is contained in:
dosiecki 2017-02-08 00:41:08 -08:00
parent 7b8795af15
commit 21228501ee
11 changed files with 157 additions and 49 deletions

View file

@ -2,7 +2,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.newsblur" package="com.newsblur"
android:versionCode="133" android:versionCode="133"
android:versionName="5.0.0" > android:versionName="5.1.0b1" >
<uses-sdk <uses-sdk
android:minSdkVersion="16" android:minSdkVersion="16"

View file

@ -977,16 +977,12 @@ public class BlurDatabaseHelper {
return c; return c;
} }
public Cursor getNotifyStoriesCursor() { public Cursor getNotifyFocusStoriesCursor() {
return rawQuery(DatabaseConstants.NOTIFY_STORY_QUERY_BASE, null, null); return rawQuery(DatabaseConstants.NOTIFY_FOCUS_STORY_QUERY, null, null);
} }
public void markNotifications() { public Cursor getNotifyUnreadStoriesCursor() {
synchronized (RW_MUTEX) { return rawQuery(DatabaseConstants.NOTIFY_UNREAD_STORY_QUERY, null, null);
ContentValues values = new ContentValues();
values.put(DatabaseConstants.STORY_NOTIFIED, 1);
dbRW.update(DatabaseConstants.STORY_TABLE, values, DatabaseConstants.STORY_NOTIFY + " > 0", null);
}
} }
public Loader<Cursor> getActiveStoriesLoader(final FeedSet fs) { public Loader<Cursor> getActiveStoriesLoader(final FeedSet fs) {

View file

@ -8,6 +8,7 @@ import android.provider.BaseColumns;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;
import com.newsblur.domain.Feed;
import com.newsblur.util.ReadFilter; import com.newsblur.util.ReadFilter;
import com.newsblur.util.StateFilter; import com.newsblur.util.StateFilter;
import com.newsblur.util.StoryOrder; import com.newsblur.util.StoryOrder;
@ -42,6 +43,7 @@ public class DatabaseConstants {
public static final String FEED_NEUTRAL_COUNT = "nt"; public static final String FEED_NEUTRAL_COUNT = "nt";
public static final String FEED_NEGATIVE_COUNT = "ng"; public static final String FEED_NEGATIVE_COUNT = "ng";
public static final String FEED_NOTIFICATION_TYPES = "notification_types"; public static final String FEED_NOTIFICATION_TYPES = "notification_types";
public static final String FEED_NOTIFICATION_FILTER = "notification_filter";
public static final String SOCIALFEED_TABLE = "social_feeds"; public static final String SOCIALFEED_TABLE = "social_feeds";
public static final String SOCIAL_FEED_ID = BaseColumns._ID; public static final String SOCIAL_FEED_ID = BaseColumns._ID;
@ -97,8 +99,6 @@ public class DatabaseConstants {
public static final String STORY_LAST_READ_DATE = "last_read_date"; public static final String STORY_LAST_READ_DATE = "last_read_date";
public static final String STORY_SEARCH_HIT = "search_hit"; public static final String STORY_SEARCH_HIT = "search_hit";
public static final String STORY_THUMBNAIL_URL = "thumbnail_url"; public static final String STORY_THUMBNAIL_URL = "thumbnail_url";
public static final String STORY_NOTIFY = "notify";
public static final String STORY_NOTIFIED = "notified";
public static final String READING_SESSION_TABLE = "reading_session"; public static final String READING_SESSION_TABLE = "reading_session";
public static final String READING_SESSION_STORY_HASH = "session_story_hash"; public static final String READING_SESSION_STORY_HASH = "session_story_hash";
@ -170,7 +170,8 @@ public class DatabaseConstants {
FEED_SUBSCRIBERS + TEXT + ", " + FEED_SUBSCRIBERS + TEXT + ", " +
FEED_TITLE + TEXT + ", " + FEED_TITLE + TEXT + ", " +
FEED_UPDATED_SECONDS + INTEGER + ", " + FEED_UPDATED_SECONDS + INTEGER + ", " +
FEED_NOTIFICATION_TYPES + TEXT + FEED_NOTIFICATION_TYPES + TEXT + ", " +
FEED_NOTIFICATION_FILTER + TEXT +
")"; ")";
static final String USER_SQL = "CREATE TABLE " + USER_TABLE + " (" + static final String USER_SQL = "CREATE TABLE " + USER_TABLE + " (" +
@ -235,8 +236,6 @@ public class DatabaseConstants {
STORY_PERMALINK + TEXT + ", " + STORY_PERMALINK + TEXT + ", " +
STORY_READ + INTEGER + ", " + STORY_READ + INTEGER + ", " +
STORY_STARRED + INTEGER + ", " + STORY_STARRED + INTEGER + ", " +
STORY_NOTIFY + INTEGER + ", " +
STORY_NOTIFIED + INTEGER + ", " +
STORY_STARRED_DATE + INTEGER + ", " + STORY_STARRED_DATE + INTEGER + ", " +
STORY_TITLE + TEXT + ", " + STORY_TITLE + TEXT + ", " +
STORY_IMAGE_URLS + TEXT + ", " + STORY_IMAGE_URLS + TEXT + ", " +
@ -295,7 +294,7 @@ public class DatabaseConstants {
STORY_INTELLIGENCE_AUTHORS, STORY_INTELLIGENCE_FEED, STORY_INTELLIGENCE_TAGS, STORY_INTELLIGENCE_TOTAL, STORY_INTELLIGENCE_AUTHORS, STORY_INTELLIGENCE_FEED, STORY_INTELLIGENCE_TAGS, STORY_INTELLIGENCE_TOTAL,
STORY_INTELLIGENCE_TITLE, STORY_PERMALINK, STORY_READ, STORY_STARRED, STORY_STARRED_DATE, STORY_TAGS, STORY_USER_TAGS, STORY_TITLE, STORY_INTELLIGENCE_TITLE, STORY_PERMALINK, STORY_READ, STORY_STARRED, STORY_STARRED_DATE, STORY_TAGS, STORY_USER_TAGS, STORY_TITLE,
STORY_SOCIAL_USER_ID, STORY_SOURCE_USER_ID, STORY_SHARED_USER_IDS, STORY_FRIEND_USER_IDS, STORY_HASH, STORY_SOCIAL_USER_ID, STORY_SOURCE_USER_ID, STORY_SHARED_USER_IDS, STORY_FRIEND_USER_IDS, STORY_HASH,
STORY_LAST_READ_DATE, STORY_THUMBNAIL_URL, STORY_NOTIFY, STORY_NOTIFIED, STORY_LAST_READ_DATE, STORY_THUMBNAIL_URL,
}; };
private static final String STORY_COLUMNS = private static final String STORY_COLUMNS =
@ -320,10 +319,19 @@ public class DatabaseConstants {
")" + ")" +
STORY_QUERY_BASE_2; STORY_QUERY_BASE_2;
public static final String NOTIFY_STORY_QUERY_BASE = public static String NOTIFY_FOCUS_STORY_QUERY =
STORY_QUERY_BASE_1 + STORY_QUERY_BASE_1 +
STORY_NOTIFY + " > 0 AND " + STORY_NOTIFIED + " < 1" + STORY_FEED_ID + " IN (SELECT " + FEED_ID + " FROM " + FEED_TABLE + " WHERE " + FEED_NOTIFICATION_FILTER + " = '" + Feed.NOTIFY_FILTER_FOCUS + "')" +
STORY_QUERY_BASE_2; " AND " + STORY_INTELLIGENCE_TOTAL + " > 0 " +
STORY_QUERY_BASE_2 +
" ORDER BY " + STORY_TIMESTAMP + " DESC";
public static String NOTIFY_UNREAD_STORY_QUERY =
STORY_QUERY_BASE_1 +
STORY_FEED_ID + " IN (SELECT " + FEED_ID + " FROM " + FEED_TABLE + " WHERE " + FEED_NOTIFICATION_FILTER + " = '" + Feed.NOTIFY_FILTER_UNREAD + "')" +
" AND " + STORY_INTELLIGENCE_TOTAL + " >= 0 " +
STORY_QUERY_BASE_2 +
" ORDER BY " + STORY_TIMESTAMP + " DESC";
public static final String JOIN_STORIES_ON_SOCIALFEED_MAP = public static final String JOIN_STORIES_ON_SOCIALFEED_MAP =
" INNER JOIN " + STORY_TABLE + " ON " + STORY_TABLE + "." + STORY_ID + " = " + SOCIALFEED_STORY_MAP_TABLE + "." + SOCIALFEED_STORY_STORYID; " INNER JOIN " + STORY_TABLE + " ON " + STORY_TABLE + "." + STORY_ID + " = " + SOCIALFEED_STORY_MAP_TABLE + "." + SOCIALFEED_STORY_STORYID;

View file

@ -59,9 +59,14 @@ public class Feed implements Comparable<Feed>, Serializable {
@SerializedName("updated_seconds_ago") @SerializedName("updated_seconds_ago")
public int lastUpdated; public int lastUpdated;
// NB: deserialized but not stored
@SerializedName("notification_types") @SerializedName("notification_types")
public List<String> notificationTypes; public List<String> notificationTypes;
// NB: only stored if notificationTypes was set to include android
@SerializedName("notification_filter")
public String notificationFilter;
public ContentValues getValues() { public ContentValues getValues() {
ContentValues values = new ContentValues(); ContentValues values = new ContentValues();
values.put(DatabaseConstants.FEED_ID, feedId); values.put(DatabaseConstants.FEED_ID, feedId);
@ -79,7 +84,9 @@ public class Feed implements Comparable<Feed>, Serializable {
values.put(DatabaseConstants.FEED_SUBSCRIBERS, subscribers); values.put(DatabaseConstants.FEED_SUBSCRIBERS, subscribers);
values.put(DatabaseConstants.FEED_TITLE, title); values.put(DatabaseConstants.FEED_TITLE, title);
values.put(DatabaseConstants.FEED_UPDATED_SECONDS, lastUpdated); values.put(DatabaseConstants.FEED_UPDATED_SECONDS, lastUpdated);
values.put(DatabaseConstants.FEED_NOTIFICATION_TYPES, DatabaseConstants.flattenStringList(notificationTypes)); if (isNotifyAndroid()) {
values.put(DatabaseConstants.FEED_NOTIFICATION_FILTER, notificationFilter);
}
return values; return values;
} }
@ -103,7 +110,7 @@ public class Feed implements Comparable<Feed>, Serializable {
feed.subscribers = cursor.getString(cursor.getColumnIndex(DatabaseConstants.FEED_SUBSCRIBERS)); feed.subscribers = cursor.getString(cursor.getColumnIndex(DatabaseConstants.FEED_SUBSCRIBERS));
feed.title = cursor.getString(cursor.getColumnIndex(DatabaseConstants.FEED_TITLE)); feed.title = cursor.getString(cursor.getColumnIndex(DatabaseConstants.FEED_TITLE));
feed.lastUpdated = cursor.getInt(cursor.getColumnIndex(DatabaseConstants.FEED_UPDATED_SECONDS)); feed.lastUpdated = cursor.getInt(cursor.getColumnIndex(DatabaseConstants.FEED_UPDATED_SECONDS));
feed.notificationTypes = DatabaseConstants.unflattenStringList(cursor.getString(cursor.getColumnIndex(DatabaseConstants.FEED_NOTIFICATION_TYPES))); feed.notificationFilter = cursor.getString(cursor.getColumnIndex(DatabaseConstants.FEED_NOTIFICATION_FILTER));
return feed; return feed;
} }
@ -135,13 +142,16 @@ public class Feed implements Comparable<Feed>, Serializable {
return title.compareToIgnoreCase(f.title); return title.compareToIgnoreCase(f.title);
} }
public boolean isNotify() { private boolean isNotifyAndroid() {
// the API vends more info on notifications than we need. distill it to a boolean
if (notificationTypes == null) return false; if (notificationTypes == null) return false;
for (String type : notificationTypes) { for (String type : notificationTypes) {
if (type.equals("android")) return true; if (type.equals(NOTIFY_TYPE_ANDROID)) return true;
} }
return false; return false;
} }
private static final String NOTIFY_TYPE_ANDROID = "android";
public static final String NOTIFY_FILTER_UNREAD = "unread";
public static final String NOTIFY_FILTER_FOCUS = "focus";
} }

View file

@ -97,10 +97,6 @@ public class Story implements Serializable {
// non-API, though it probably could/should be. populated on first story ingest if thumbnails are turned on // non-API, though it probably could/should be. populated on first story ingest if thumbnails are turned on
public String thumbnailUrl; public String thumbnailUrl;
// non-API
public boolean notify;
public boolean notified;
public ContentValues getValues() { public ContentValues getValues() {
final ContentValues values = new ContentValues(); final ContentValues values = new ContentValues();
values.put(DatabaseConstants.STORY_ID, id); values.put(DatabaseConstants.STORY_ID, id);
@ -130,8 +126,6 @@ public class Story implements Serializable {
values.put(DatabaseConstants.STORY_LAST_READ_DATE, lastReadTimestamp); values.put(DatabaseConstants.STORY_LAST_READ_DATE, lastReadTimestamp);
values.put(DatabaseConstants.STORY_SEARCH_HIT, searchHit); values.put(DatabaseConstants.STORY_SEARCH_HIT, searchHit);
values.put(DatabaseConstants.STORY_THUMBNAIL_URL, thumbnailUrl); values.put(DatabaseConstants.STORY_THUMBNAIL_URL, thumbnailUrl);
values.put(DatabaseConstants.STORY_NOTIFY, notify);
values.put(DatabaseConstants.STORY_NOTIFIED, notified);
return values; return values;
} }
@ -163,8 +157,6 @@ public class Story implements Serializable {
story.storyHash = cursor.getString(cursor.getColumnIndex(DatabaseConstants.STORY_HASH)); story.storyHash = cursor.getString(cursor.getColumnIndex(DatabaseConstants.STORY_HASH));
story.lastReadTimestamp = cursor.getLong(cursor.getColumnIndex(DatabaseConstants.STORY_LAST_READ_DATE)); story.lastReadTimestamp = cursor.getLong(cursor.getColumnIndex(DatabaseConstants.STORY_LAST_READ_DATE));
story.thumbnailUrl = cursor.getString(cursor.getColumnIndex(DatabaseConstants.STORY_THUMBNAIL_URL)); story.thumbnailUrl = cursor.getString(cursor.getColumnIndex(DatabaseConstants.STORY_THUMBNAIL_URL));
story.notify = cursor.getInt(cursor.getColumnIndex(DatabaseConstants.STORY_NOTIFY)) > 0;
story.notified = cursor.getInt(cursor.getColumnIndex(DatabaseConstants.STORY_NOTIFIED)) > 0;
return story; return story;
} }

View file

@ -31,6 +31,7 @@ import com.newsblur.util.AppConstants;
import com.newsblur.util.FeedSet; import com.newsblur.util.FeedSet;
import com.newsblur.util.FileCache; import com.newsblur.util.FileCache;
import com.newsblur.util.NetworkUtils; import com.newsblur.util.NetworkUtils;
import com.newsblur.util.NotificationUtils;
import com.newsblur.util.PrefsUtils; import com.newsblur.util.PrefsUtils;
import com.newsblur.util.ReadingAction; import com.newsblur.util.ReadingAction;
import com.newsblur.util.ReadFilter; import com.newsblur.util.ReadFilter;
@ -134,6 +135,7 @@ public class NBSyncService extends Service {
PowerManager.WakeLock wl = null; PowerManager.WakeLock wl = null;
APIManager apiManager; APIManager apiManager;
BlurDatabaseHelper dbHelper; BlurDatabaseHelper dbHelper;
FileCache iconCache;
private int lastStartIdCompleted = -1; private int lastStartIdCompleted = -1;
/** The time of the last hard API failure we encountered. Used to implement back-off so that the sync /** The time of the last hard API failure we encountered. Used to implement back-off so that the sync
@ -162,6 +164,7 @@ public class NBSyncService extends Service {
if (apiManager == null) { if (apiManager == null) {
apiManager = new APIManager(this); apiManager = new APIManager(this);
dbHelper = new BlurDatabaseHelper(this); dbHelper = new BlurDatabaseHelper(this);
iconCache = FileCache.asIconCache(this);
cleanupService = new CleanupService(this); cleanupService = new CleanupService(this);
originalTextService = new OriginalTextService(this); originalTextService = new OriginalTextService(this);
unreadsService = new UnreadsService(this); unreadsService = new UnreadsService(this);
@ -253,6 +256,8 @@ public class NBSyncService extends Service {
checkRecounts(); checkRecounts();
pushNotifications();
if (AppConstants.VERBOSE_LOG) Log.d(this.getClass().getName(), "finishing primary sync"); if (AppConstants.VERBOSE_LOG) Log.d(this.getClass().getName(), "finishing primary sync");
} catch (Exception e) { } catch (Exception e) {
@ -774,6 +779,19 @@ public class NBSyncService extends Service {
dbHelper.insertStories(apiResponse, false); dbHelper.insertStories(apiResponse, false);
} }
void pushNotifications() {
// don't notify stories until the queue is flushed so they don't churn
if (unreadsService.StoryHashQueue.size() > 0) return;
// don't slow down active story loading
if (PendingFeed != null) return;
Cursor cFocus = dbHelper.getNotifyFocusStoriesCursor();
Cursor cUnread = dbHelper.getNotifyUnreadStoriesCursor();
NotificationUtils.notifyStories(cFocus, cUnread, this, iconCache);
closeQuietly(cFocus);
closeQuietly(cUnread);
}
void incrementRunningChild() { void incrementRunningChild() {
synchronized (WAKELOCK_MUTEX) { synchronized (WAKELOCK_MUTEX) {
wl.acquire(); wl.acquire();

View file

@ -33,7 +33,6 @@ public abstract class SubService {
} }
public void start(final int startId) { public void start(final int startId) {
if (Boolean.TRUE != parent.isAuth) return;
if (parent.stopSync()) return; if (parent.stopSync()) return;
parent.incrementRunningChild(); parent.incrementRunningChild();
this.startId = startId; this.startId = startId;

View file

@ -4,12 +4,12 @@ import android.database.Cursor;
import android.util.Log; import android.util.Log;
import static com.newsblur.database.BlurDatabaseHelper.closeQuietly; import static com.newsblur.database.BlurDatabaseHelper.closeQuietly;
import com.newsblur.domain.Feed;
import com.newsblur.domain.Story; import com.newsblur.domain.Story;
import com.newsblur.network.domain.StoriesResponse; import com.newsblur.network.domain.StoriesResponse;
import com.newsblur.network.domain.UnreadStoryHashesResponse; import com.newsblur.network.domain.UnreadStoryHashesResponse;
import com.newsblur.util.AppConstants; import com.newsblur.util.AppConstants;
import com.newsblur.util.DefaultFeedView; import com.newsblur.util.DefaultFeedView;
import com.newsblur.util.NotificationUtils;
import com.newsblur.util.PrefsUtils; import com.newsblur.util.PrefsUtils;
import com.newsblur.util.StoryOrder; import com.newsblur.util.StoryOrder;
@ -17,6 +17,7 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Set; import java.util.Set;
@ -27,7 +28,7 @@ public class UnreadsService extends SubService {
private static volatile boolean doMetadata = false; private static volatile boolean doMetadata = false;
/** Unread story hashes the API listed that we do not appear to have locally yet. */ /** Unread story hashes the API listed that we do not appear to have locally yet. */
private static List<String> StoryHashQueue; static List<String> StoryHashQueue;
static { StoryHashQueue = new ArrayList<String>(); } static { StoryHashQueue = new ArrayList<String>(); }
public UnreadsService(NBSyncService parent) { public UnreadsService(NBSyncService parent) {
@ -44,11 +45,9 @@ public class UnreadsService extends SubService {
if (StoryHashQueue.size() > 0) { if (StoryHashQueue.size() > 0) {
getNewUnreadStories(); getNewUnreadStories();
parent.pushNotifications();
} }
if (StoryHashQueue.size() < 1) {
notifyStories();
}
} }
private void syncUnreadList() { private void syncUnreadList() {
@ -177,15 +176,6 @@ public class UnreadsService extends SubService {
return true; return true;
} }
private void notifyStories() {
Cursor c = parent.dbHelper.getNotifyStoriesCursor();
if (c.getCount() > 0 ) {
NotificationUtils.notifyStories(c, parent);
parent.dbHelper.markNotifications();
}
closeQuietly(c);
}
public static void clear() { public static void clear() {
StoryHashQueue.clear(); StoryHashQueue.clear();
} }

View file

@ -149,7 +149,7 @@ public class ImageLoader {
} }
} }
private Bitmap decodeBitmap(File f) { private static Bitmap decodeBitmap(File f) {
// is is perfectly normal for files not to exist on cache misses or low // is is perfectly normal for files not to exist on cache misses or low
// device memory. this class will handle nulls with a queued action or // device memory. this class will handle nulls with a queued action or
// placeholder image. // placeholder image.
@ -161,4 +161,17 @@ public class ImageLoader {
} }
} }
/**
* Directly access a previously cached image's bitmap. This method is *not* for use
* in foreground UI methods; it was designed for low-priority background use for
* creating notifications.
*/
public static Bitmap getCachedImageSynchro(FileCache fileCache, String url) {
if (url.startsWith("/")) {
url = APIConstants.buildUrl(url);
}
File f = fileCache.getCachedFile(url);
return decodeBitmap(f);
}
} }

View file

@ -12,9 +12,13 @@ import android.app.PendingIntent;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.database.Cursor; import android.database.Cursor;
import android.graphics.Bitmap;
import android.os.Build;
import com.newsblur.R; import com.newsblur.R;
import com.newsblur.activity.FeedReading;
import com.newsblur.activity.Main; import com.newsblur.activity.Main;
import com.newsblur.activity.Reading;
import com.newsblur.database.DatabaseConstants; import com.newsblur.database.DatabaseConstants;
import com.newsblur.domain.Feed; import com.newsblur.domain.Feed;
import com.newsblur.domain.Story; import com.newsblur.domain.Story;
@ -22,10 +26,86 @@ import com.newsblur.util.FileCache;
public class NotificationUtils { public class NotificationUtils {
private static final int NOTIFY_COLOUR = 0xFFDA8A35;
private static final int MAX_CONCUR_NOTIFY = 5;
private NotificationUtils() {} // util class - no instances private NotificationUtils() {} // util class - no instances
public static void notifyStories(Cursor stories, Context context) { public static synchronized void notifyStories(Cursor storiesFocus, Cursor storiesUnread, Context context, FileCache iconCache) {
; NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
int count = 0;
while (storiesFocus.moveToNext()) {
Story story = Story.fromCursor(storiesFocus);
if (story.read) {
nm.cancel(story.hashCode());
continue;
}
if (count < MAX_CONCUR_NOTIFY) {
Notification n = buildStoryNotification(story, storiesFocus, context, iconCache);
nm.notify(story.hashCode(), n);
} else {
nm.cancel(story.hashCode());
}
count++;
}
while (storiesUnread.moveToNext()) {
Story story = Story.fromCursor(storiesUnread);
if (story.read) {
nm.cancel(story.hashCode());
continue;
}
if (count < MAX_CONCUR_NOTIFY) {
Notification n = buildStoryNotification(story, storiesUnread, context, iconCache);
nm.notify(story.hashCode(), n);
} else {
nm.cancel(story.hashCode());
}
count++;
}
}
private static Notification buildStoryNotification(Story story, Cursor cursor, Context context, FileCache iconCache) {
Intent i = new Intent(context, FeedReading.class);
// the action is unused, but bugs in some platform versions ignore extras if it is unset
i.setAction(story.storyHash);
// these extras actually dictate activity behaviour
i.putExtra(Reading.EXTRA_FEEDSET, FeedSet.singleFeed(story.feedId));
i.putExtra(Reading.EXTRA_STORY_HASH, story.storyHash);
// force a new Reading activity, since if multiple notifications are tapped, any re-use or
// stacking of the activity would almost certainly out-race the sync loop and cause stale
// UI on some devices.
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
// set the requestCode to the story hashcode to prevent the PI re-using the wrong Intent
PendingIntent pendingIntent = PendingIntent.getActivity(context, story.hashCode(), i, 0);
String feedTitle = cursor.getString(cursor.getColumnIndex(DatabaseConstants.FEED_TITLE));
StringBuilder title = new StringBuilder();
title.append(feedTitle).append(": ").append(story.title);
String faviconUrl = cursor.getString(cursor.getColumnIndex(DatabaseConstants.FEED_FAVICON_URL));
Bitmap feedIcon = ImageLoader.getCachedImageSynchro(iconCache, faviconUrl);
Notification.Builder nb = new Notification.Builder(context)
.setContentTitle(title.toString())
.setContentText(story.shortContent)
.setSmallIcon(R.drawable.logo_monochrome)
.setContentIntent(pendingIntent)
.setAutoCancel(true)
.setWhen(story.timestamp);
if (feedIcon != null) {
nb.setLargeIcon(feedIcon);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
nb.setColor(NOTIFY_COLOUR);
}
return nb.build();
}
public static void clear(Context context) {
NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
nm.cancelAll();
} }
} }

View file

@ -116,6 +116,8 @@ public class PrefsUtils {
NBSyncService.softInterrupt(); NBSyncService.softInterrupt();
NBSyncService.clearState(); NBSyncService.clearState();
NotificationUtils.clear(context);
// wipe the prefs store // wipe the prefs store
context.getSharedPreferences(PrefConstants.PREFERENCES, 0).edit().clear().commit(); context.getSharedPreferences(PrefConstants.PREFERENCES, 0).edit().clear().commit();