package com.vaguehope.onosendai.notifications; import java.util.Collection; import java.util.List; import java.util.Random; import java.util.Set; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.support.v4.app.NotificationCompat; import android.support.v4.app.NotificationCompat.Builder; import android.support.v4.app.NotificationCompat.InboxStyle; import android.support.v4.app.NotificationCompat.Style; import android.text.Spannable; import android.text.SpannableString; import android.text.Spanned; import android.text.style.StyleSpan; import com.vaguehope.onosendai.R; import com.vaguehope.onosendai.config.Column; import com.vaguehope.onosendai.config.Config; import com.vaguehope.onosendai.config.InlineMediaStyle; import com.vaguehope.onosendai.config.NotificationStyle; import com.vaguehope.onosendai.model.Tweet; import com.vaguehope.onosendai.storage.DbInterface; import com.vaguehope.onosendai.storage.DbInterface.Selection; import com.vaguehope.onosendai.storage.SaveScrollNow; import com.vaguehope.onosendai.ui.MainActivity; import com.vaguehope.onosendai.util.StringHelper; public final class Notifications { private static final Random RAND = new Random(System.currentTimeMillis()); private Notifications () { throw new AssertionError(); } public static int notificationIcon () { switch (RAND.nextInt(2)) { case 0: return R.drawable.ic_ho_meji; case 1: default: return R.drawable.ic_saka_meji; } } public static void update (final Context context, final DbInterface db, final Config conf, final Collection<Column> columns) { SaveScrollNow.requestAndWaitForUiToSaveScroll(db); final NotificationManager nm = getManager(context); final Set<Integer> columnsHidingRetweets = conf.getColumnsHidingRetweets(); for (final Column col : columns) { if (col.getNotificationStyle() == null) continue; updateColumn(context, db, columnsHidingRetweets, col, nm); } } public static void clearColumn (final Context context, final Column col) { clearColumn(context, col.getId()); } public static void clearColumn (final Context context, final int colId) { getManager(context).cancel(idForColumn(colId)); } private static NotificationManager getManager (final Context context) { return (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); } private static void updateColumn (final Context context, final DbInterface db, final Set<Integer> columnsHidingRetweets, final Column col, final NotificationManager nm) { final int nId = idForColumn(col); final int count = db.getUnreadCount(col, columnsHidingRetweets); if (count > 0) { final Intent showMainActI = new Intent(context, MainActivity.class) .setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP) .putExtra(MainActivity.ARG_FOCUS_COLUMN_ID, col.getId()); final PendingIntent showMainActPi = PendingIntent.getActivity(context, col.getId(), showMainActI, PendingIntent.FLAG_CANCEL_CURRENT); final List<Tweet> tweets = db.getTweets(col.getId(), Math.min(count, 5), Selection.FILTERED, col.getExcludeColumnIds(), columnsHidingRetweets, col.getInlineMediaStyle() == InlineMediaStyle.SEAMLESS, col.getNotificationStyle().isExcludeRetweets(), !col.getNotificationStyle().isIncludeOwnTweets()); final String msg = makeMsg(col, tweets, count); final Style style = makePreview(tweets, count); final PendingIntent markAsReadPi = MarkAsReadReceiver.makePi(context, col, tweets); final Builder nb = new NotificationCompat.Builder(context) .setOnlyAlertOnce(true) .setSmallIcon(notificationIcon()) .setContentTitle(col.getTitle()) .setContentText(msg) .setTicker(msg) .setNumber(count) .setContentIntent(showMainActPi) .setAutoCancel(true) .setWhen(System.currentTimeMillis()) .setStyle(style); if (markAsReadPi != null) nb.addAction(android.R.drawable.ic_menu_close_clear_cancel, "Mark as read", markAsReadPi); //ES applyStyle(nb, col.getNotificationStyle()); nm.notify(nId, nb.build()); } else { nm.cancel(nId); } } private static int idForColumn (final Column col) { return idForColumn(col.getId()); } private static int idForColumn (final int colId) { return NotificationIds.BASE_NOTIFICATION_ID + colId; } private static void applyStyle (final Builder nb, final NotificationStyle ns) { int defaults = 0; if (ns.isLights()) defaults |= Notification.DEFAULT_LIGHTS; if (ns.isVibrate()) defaults |= Notification.DEFAULT_VIBRATE; if (ns.isSound()) defaults |= Notification.DEFAULT_SOUND; nb.setDefaults(defaults); } private static String makeMsg (final Column col, final List<Tweet> tweets, final int count) { if (count == 1 && tweets != null && tweets.size() == 1) { final Tweet t = tweets.get(0); return String.format("%s: %s", readName(t), t.getBody()); } return String.format("%s: %s new updates.", col.getTitle(), count); //ES } // https://stackoverflow.com/questions/14602072/styling-notification-inboxstyle private static Style makePreview (final List<Tweet> tweets, final int count) { if (tweets == null || tweets.size() < 1) return null; if (tweets.size() == 1) return new NotificationCompat.BigTextStyle() .bigText(tweetToSpanable(tweets.iterator().next())); final InboxStyle inboxStyle = new NotificationCompat.InboxStyle(); for (final Tweet tweet : tweets) { inboxStyle.addLine(tweetToSpanable(tweet)); } if (tweets.size() < count) { inboxStyle.setSummaryText(String.format("+%s more", count - tweets.size())); } return inboxStyle; } private static Spannable tweetToSpanable (final Tweet tweet) { final String name = readName(tweet); final Spannable s = new SpannableString(String.format("%s: %s", name, tweet.getBody())); s.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), 0, name.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); return s; } private static String readName (final Tweet tweet) { return !StringHelper.isEmpty(tweet.getUsername()) ? StringHelper.firstLine(tweet.getUsername()) : StringHelper.firstLine(tweet.getFullname()); } }