diff options
author | Dianne Hackborn <hackbod@google.com> | 2009-08-17 23:33:56 -0700 |
---|---|---|
committer | Dianne Hackborn <hackbod@google.com> | 2009-08-18 13:59:27 -0700 |
commit | d8a43f61680bacf0d4b52a03ff3c7a07307377fc (patch) | |
tree | 298808433ea17b6842b87424629fa1869478ed94 /core | |
parent | 30c0b83490d856c1cd82441c8e2d800a88927237 (diff) | |
download | frameworks_base-d8a43f61680bacf0d4b52a03ff3c7a07307377fc.zip frameworks_base-d8a43f61680bacf0d4b52a03ff3c7a07307377fc.tar.gz frameworks_base-d8a43f61680bacf0d4b52a03ff3c7a07307377fc.tar.bz2 |
Fix issue #2047139: Remove Service.setForeground()
This API is becoming seriously abused, so now it is deprecated and has
become a no-op.
As an alternative, there is now a new API that allows you to make a service
be in the foreground but requires providing a persistent notification to
go along with this state, allowing the user to know about and control it.
Diffstat (limited to 'core')
-rw-r--r-- | core/java/android/app/ActivityManagerNative.java | 23 | ||||
-rw-r--r-- | core/java/android/app/IActivityManager.java | 2 | ||||
-rw-r--r-- | core/java/android/app/Notification.java | 7 | ||||
-rw-r--r-- | core/java/android/app/NotificationManager.java | 3 | ||||
-rw-r--r-- | core/java/android/app/Service.java | 45 |
5 files changed, 63 insertions, 17 deletions
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index 447512a..4dc23c0 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -39,9 +39,6 @@ import android.text.TextUtils; import android.util.Config; import android.util.Log; -import java.io.FileNotFoundException; -import java.io.FileDescriptor; -import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -551,8 +548,13 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM data.enforceInterface(IActivityManager.descriptor); ComponentName className = ComponentName.readFromParcel(data); IBinder token = data.readStrongBinder(); - boolean isForeground = data.readInt() != 0; - setServiceForeground(className, token, isForeground); + int id = data.readInt(); + Notification notification = null; + if (data.readInt() != 0) { + notification = Notification.CREATOR.createFromParcel(data); + } + boolean removeNotification = data.readInt() != 0; + setServiceForeground(className, token, id, notification, removeNotification); reply.writeNoException(); return true; } @@ -1664,13 +1666,20 @@ class ActivityManagerProxy implements IActivityManager return res; } public void setServiceForeground(ComponentName className, IBinder token, - boolean isForeground) throws RemoteException { + int id, Notification notification, boolean removeNotification) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); ComponentName.writeToParcel(className, data); data.writeStrongBinder(token); - data.writeInt(isForeground ? 1 : 0); + data.writeInt(id); + if (notification != null) { + data.writeInt(1); + notification.writeToParcel(data, 0); + } else { + data.writeInt(0); + } + data.writeInt(removeNotification ? 1 : 0); mRemote.transact(SET_SERVICE_FOREGROUND_TRANSACTION, data, reply, 0); reply.readException(); data.recycle(); diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index f6ef549..45c202d 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -139,7 +139,7 @@ public interface IActivityManager extends IInterface { public boolean stopServiceToken(ComponentName className, IBinder token, int startId) throws RemoteException; public void setServiceForeground(ComponentName className, IBinder token, - boolean isForeground) throws RemoteException; + int id, Notification notification, boolean keepNotification) throws RemoteException; public int bindService(IApplicationThread caller, IBinder token, Intent service, String resolvedType, IServiceConnection connection, int flags) throws RemoteException; diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index a67e60b..be5a7d3 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -257,6 +257,13 @@ public class Notification implements Parcelable */ public static final int FLAG_NO_CLEAR = 0x00000020; + /** + * Bit to be bitwise-ored into the {@link #flags} field that should be + * set if this notification represents a currently running service. This + * will normally be set for you by {@link Service#startForeground}. + */ + public static final int FLAG_FOREGROUND_SERVICE = 0x00000040; + public int flags; /** diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java index 39edab7..7b51fdf 100644 --- a/core/java/android/app/NotificationManager.java +++ b/core/java/android/app/NotificationManager.java @@ -61,7 +61,8 @@ public class NotificationManager private static INotificationManager sService; - static private INotificationManager getService() + /** @hide */ + static public INotificationManager getService() { if (sService != null) { return sService; diff --git a/core/java/android/app/Service.java b/core/java/android/app/Service.java index d2fb605..ce72e3f 100644 --- a/core/java/android/app/Service.java +++ b/core/java/android/app/Service.java @@ -24,6 +24,7 @@ import android.content.Context; import android.content.res.Configuration; import android.os.RemoteException; import android.os.IBinder; +import android.util.Log; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -304,24 +305,52 @@ public abstract class Service extends ContextWrapper implements ComponentCallbac } /** - * Control whether this service is considered to be a foreground service. + * @deprecated This is a now a no-op, use + * {@link #startForeground(int, Notification)} instead. + */ + @Deprecated + public final void setForeground(boolean isForeground) { + Log.w(TAG, "setForeground: ignoring old API call on " + getClass().getName()); + } + + /** + * Make this service run in the foreground, supplying the ongoing + * notification to be shown to the user while in this state. * By default services are background, meaning that if the system needs to * kill them to reclaim more memory (such as to display a large page in a * web browser), they can be killed without too much harm. You can set this - * flag if killing your service would be disruptive to the user: such as + * flag if killing your service would be disruptive to the user, such as * if your service is performing background music playback, so the user * would notice if their music stopped playing. * - * @param isForeground Determines whether this service is considered to - * be foreground (true) or background (false). + * @param id The identifier for this notification as per + * {@link NotificationManager#notify(int, Notification) + * NotificationManager.notify(int, Notification)}. + * @param notification The Notification to be displayed. + * + * @see #stopForeground(boolean) */ - public final void setForeground(boolean isForeground) { - if (mActivityManager == null) { - return; + public final void startForeground(int id, Notification notification) { + try { + mActivityManager.setServiceForeground( + new ComponentName(this, mClassName), mToken, id, + notification, true); + } catch (RemoteException ex) { } + } + + /** + * Remove this service from foreground state, allowing it to be killed if + * more memory is needed. + * @param keepNotification If true, the notification previously provided + * to {@link #startForeground} will remain displayed. + * @see #startForeground(int, Notification) + */ + public final void stopForeground(boolean removeNotification) { try { mActivityManager.setServiceForeground( - new ComponentName(this, mClassName), mToken, isForeground); + new ComponentName(this, mClassName), mToken, 0, null, + removeNotification); } catch (RemoteException ex) { } } |