package org.mozilla.mozstumbler.client.util; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.os.Build; import android.support.v4.app.NotificationCompat; import org.mozilla.mozstumbler.R; import org.mozilla.mozstumbler.client.DateTimeUtils; import org.mozilla.mozstumbler.client.MainApp; import org.mozilla.mozstumbler.client.navdrawer.MainDrawerActivity; import org.mozilla.mozstumbler.svclocator.ServiceLocator; import org.mozilla.mozstumbler.svclocator.services.ISystemClock; import org.mozilla.mozstumbler.svclocator.services.log.ILogger; import org.mozilla.mozstumbler.svclocator.services.log.LoggerUtil; public class NotificationUtil { private static final ILogger Log = (ILogger) ServiceLocator .getInstance() .getService(ILogger.class); private static final String LOG_TAG = LoggerUtil.makeLogTag(NotificationUtil.class); public static final int NOTIFICATION_ID = 1; private static final long UPDATE_FREQUENCY = 60 * 1000; private static String sStopTitle; private static int sObservations, sCells, sWifis; private static long sUploadTime, sDisplayTime, sLastUpdateTime; private static boolean sIsPaused; private final Context mContext; private ISystemClock clock = (ISystemClock) ServiceLocator.getInstance().getService(ISystemClock.class); public NotificationUtil(Context context) { mContext = context; } private Notification build() { PendingIntent notificationStopIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(MainApp.NOTIFICATION_STOP), 0); Intent notificationIntent = new Intent(mContext, MainDrawerActivity.class); notificationIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_FROM_BACKGROUND); PendingIntent contentIntent = PendingIntent.getActivity(mContext, NOTIFICATION_ID, notificationIntent, PendingIntent.FLAG_CANCEL_CURRENT); String appname = mContext.getString(R.string.app_name); int titleId = sIsPaused ? R.string.notification_paused : R.string.notification_scanning; String title = String.format(mContext.getString(titleId), appname); String metrics = mContext.getString(R.string.metrics_notification_text); metrics = String.format(metrics, sObservations, sCells, sWifis); String uploadtime = mContext.getString(R.string.metrics_observations_last_upload_time_never); if (sUploadTime > 0) { uploadtime = DateTimeUtils.formatTimeForLocale(sUploadTime); } String uploadLine = mContext.getString(R.string.metrics_notification_extraline); uploadLine = String.format(uploadLine, uploadtime); ISystemClock clock = (ISystemClock) ServiceLocator.getInstance() .getService(ISystemClock.class); sLastUpdateTime = clock.currentTimeMillis(); return new NotificationCompat.Builder(mContext) .setSmallIcon(R.drawable.ic_status_scanning) .setContentTitle(title) .setContentText(metrics) .setWhen(sDisplayTime) .setContentIntent(contentIntent) .setOngoing(true) .setPriority(NotificationCompat.PRIORITY_LOW) .setVisibility(NotificationCompat.VISIBILITY_PUBLIC) .setStyle(new NotificationCompat.BigTextStyle() .bigText(metrics + "\n" + uploadLine)) .addAction(R.drawable.ic_action_cancel, sStopTitle, notificationStopIntent) .build(); } void update() { Notification notification = build(); NotificationManager nm = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE); if (nm == null) { // This really *shouldn't* happen, but we get this on some devices. See : // https://github.com/mozilla/MozStumbler/issues/1564 Log.d(LOG_TAG, "Couldn't acquire notification service"); return; } nm.notify(NOTIFICATION_ID, notification); } public Notification buildNotification(String stopTitle) { sStopTitle = stopTitle; sIsPaused = false; sDisplayTime = clock.currentTimeMillis(); return build(); } public void setPaused(boolean isPaused) { sIsPaused = isPaused; sDisplayTime = System.currentTimeMillis(); update(); } public void updateMetrics(int observations, int cells, int wifis, long uploadtime, boolean isActive) { sObservations = observations; sCells = cells; sWifis = wifis; sUploadTime = uploadtime; long diffLastUpdate = System.currentTimeMillis() - sLastUpdateTime; boolean isUpdateAnimated = Build.VERSION.SDK_INT < 21; if (isActive && (!isUpdateAnimated || diffLastUpdate > UPDATE_FREQUENCY)) { update(); } } // Will update the last uploaded label without rate-limiting the update. Therefore ensure // this is being called only when the upload label actually needs updating. public void updateLastUploadedLabel(long value) { sUploadTime = value; update(); } }