Bug 1465102 - Updated NotificationService for Oreo. r?sdaswani draft
authorVlad Baicu <vlad.baicu@softvision.ro>
Thu, 05 Jul 2018 19:35:16 +0300
changeset 817988 9a91c36b6e3c6278f13a0c942d0bdf1f238aeb4d
parent 817987 60f381e7555e5fe68e84c86da6c868a7a3b004ca
child 817989 4c5c44eb7dd068f4be4245d4fd09e919503c5faf
push id116231
push userplingurar@mozilla.com
push dateFri, 13 Jul 2018 19:23:06 +0000
reviewerssdaswani
bugs1465102
milestone63.0a1
Bug 1465102 - Updated NotificationService for Oreo. r?sdaswani Modified NotificationClient to use new start/stop intents for NotificationService for Android O. We are keeping a reference to the notification the service was first started with in order to comply with the mandatory startForeground call for Oreo. MozReview-Commit-ID: 4CzM4pvANJt
mobile/android/base/java/org/mozilla/gecko/notifications/NotificationClient.java
mobile/android/base/java/org/mozilla/gecko/notifications/NotificationService.java
--- a/mobile/android/base/java/org/mozilla/gecko/notifications/NotificationClient.java
+++ b/mobile/android/base/java/org/mozilla/gecko/notifications/NotificationClient.java
@@ -8,16 +8,17 @@ package org.mozilla.gecko.notifications;
 import android.annotation.SuppressLint;
 import android.app.Activity;
 import android.app.Notification;
 import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
 import android.graphics.Bitmap;
 import android.net.Uri;
+import android.support.annotation.NonNull;
 import android.support.v4.app.NotificationCompat;
 import android.support.v4.app.NotificationManagerCompat;
 
 import org.mozilla.gecko.AppConstants;
 import org.mozilla.gecko.GeckoActivityMonitor;
 import org.mozilla.gecko.GeckoAppShell;
 import org.mozilla.gecko.GeckoApplication;
 import org.mozilla.gecko.GeckoService;
@@ -303,23 +304,45 @@ public final class NotificationClient im
      */
     public boolean isOngoing(final Notification notification) {
         if (notification != null && (notification.flags & Notification.FLAG_ONGOING_EVENT) != 0) {
             return true;
         }
         return false;
     }
 
-    private void setForegroundNotificationLocked(final String name,
-                                                 final Notification notification) {
+    private void setForegroundNotificationLocked(@NonNull final String name,
+                                                 @NonNull final Notification notification) {
         mForegroundNotification = name;
 
         final Intent intent = new Intent(mContext, NotificationService.class);
         intent.putExtra(NotificationService.EXTRA_NOTIFICATION, notification);
-        mContext.startService(intent);
+        toggleForegroundService(intent);
+    }
+
+    private void removeForegroundNotificationLocked() {
+        mForegroundNotification = null;
+
+        final Intent intent = new Intent(mContext, NotificationService.class);
+        intent.putExtra(NotificationService.EXTRA_ACTION_STOP, true);
+        toggleForegroundService(intent);
+    }
+
+    /**
+     * Method used to toggle the NotificationService.
+     * When the intent is passed with {@link NotificationService#EXTRA_ACTION_STOP} we are queueing a stopSelf action.
+     * @param intent
+     */
+    @SuppressLint("NewApi")
+    private void toggleForegroundService(Intent intent) {
+        if (AppConstants.Versions.preO) {
+            mContext.startService(intent);
+        } else {
+            mContext.startForegroundService(intent);
+        }
     }
 
     private void updateForegroundNotificationLocked(final String oldName) {
         if (mForegroundNotification == null || !mForegroundNotification.equals(oldName)) {
             return;
         }
 
         // If we're removing the notification associated with the
@@ -332,11 +355,11 @@ public final class NotificationClient im
                 // uses a special ID, so we need to close its old instantiation and then
                 // re-add it with the new ID through the NotificationService.
                 onNotificationClose(name);
                 setForegroundNotificationLocked(name, notification);
                 return;
             }
         }
 
-        setForegroundNotificationLocked(null, null);
+        removeForegroundNotificationLocked();
     }
 }
--- a/mobile/android/base/java/org/mozilla/gecko/notifications/NotificationService.java
+++ b/mobile/android/base/java/org/mozilla/gecko/notifications/NotificationService.java
@@ -5,33 +5,57 @@
 
 package org.mozilla.gecko.notifications;
 
 import android.app.Notification;
 import android.app.Service;
 import android.content.Intent;
 import android.os.IBinder;
 
+import org.mozilla.gecko.AppConstants;
 import org.mozilla.gecko.R;
 
 public final class NotificationService extends Service {
+    /**
+     * Start Intent of the service must contain a notification extra.
+     */
     public static final String EXTRA_NOTIFICATION = "notification";
+    /**
+     * Stop Intent of the service must contain the stop action extra.
+     */
+    public static final String EXTRA_ACTION_STOP = "action_stop";
+
+    /**
+     * We are holding a reference to the notification this service was started with in order to use it
+     * again when we queue the stop action thus satisfying the Oreo limitations.
+     */
+    private Notification currentNotification;
 
     @Override // Service
     public int onStartCommand(final Intent intent, final int flags, final int startId) {
-        final Notification notification = intent.getParcelableExtra(EXTRA_NOTIFICATION);
-        if (notification != null) {
-            // Start foreground notification.
-            startForeground(R.id.foregroundNotification, notification);
-            return START_NOT_STICKY;
-        }
-
-        // Stop foreground notification
-        stopForeground(true);
-        stopSelfResult(startId);
+        handleIntent(intent, startId);
         return START_NOT_STICKY;
     }
 
     @Override // Service
     public IBinder onBind(final Intent intent) {
         return null;
     }
+
+    private void handleIntent(Intent intent, int startId) {
+        //Start Intent
+        if (intent.hasExtra(EXTRA_NOTIFICATION)) {
+            currentNotification = intent.getParcelableExtra(EXTRA_NOTIFICATION);
+            startForeground(R.id.foregroundNotification, currentNotification);
+        }
+
+        //Stop Intent
+        if (intent.hasExtra(NotificationService.EXTRA_ACTION_STOP)) {
+            //Call necessary for Oreo+ only
+            if (!AppConstants.Versions.preO) {
+                startForeground(R.id.foregroundNotification, currentNotification);
+            }
+
+            stopForeground(true);
+            stopSelfResult(startId);
+        }
+    }
 }