Android创建前台运行的Service

来源:互联网 发布:淘宝买家秀在哪里 编辑:程序博客网 时间:2024/06/04 18:46

Service如果要防止尽可能不被系统杀掉,需要设置为在前台运行。

由于设置前台运行service的方法在2.0之前和2.0之后有所变化。

所以需要根据不同的版本进行区分;或者完全使用反射机制来处理,这样只要有相应的方法就可以使用,否则使用其他版本的方法。

下面是一个设置servcie前台运行的例子,参考了API中对Service的说明。

http://developer.android.com/reference/android/app/Service.html#

import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import android.app.Notification;import android.app.NotificationManager;import android.app.PendingIntent;import android.app.Service;import android.content.Context;import android.content.Intent;import android.os.IBinder;import android.os.Build.VERSION;import android.util.Log;public class ForegroundService extends Service {    private static final String TAG = "ForegroundService";        private boolean mReflectFlg = false;        private static final int NOTIFICATION_ID = 1; // 如果id设置为0,会导致不能设置为前台service    private static final Class<?>[] mSetForegroundSignature = new Class[] {        boolean.class};    private static final Class<?>[] mStartForegroundSignature = new Class[] {        int.class, Notification.class};    private static final Class<?>[] mStopForegroundSignature = new Class[] {        boolean.class};    private NotificationManager mNM;      private Method mSetForeground;    private Method mStartForeground;      private Method mStopForeground;    private Object[] mSetForegroundArgs = new Object[1];    private Object[] mStartForegroundArgs = new Object[2];      private Object[] mStopForegroundArgs = new Object[1];          @Override      public void onCreate() {          super.onCreate();        Log.d(TAG, "onCreate");                mNM = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);          try {              mStartForeground = ForegroundService.class.getMethod("startForeground", mStartForegroundSignature);              mStopForeground = ForegroundService.class.getMethod("stopForeground", mStopForegroundSignature);          } catch (NoSuchMethodException e) {              mStartForeground = mStopForeground = null;          }                  try {            mSetForeground = getClass().getMethod("setForeground",                    mSetForegroundSignature);        } catch (NoSuchMethodException e) {            throw new IllegalStateException(                    "OS doesn't have Service.startForeground OR Service.setForeground!");        }        Notification.Builder builder = new Notification.Builder(this);        PendingIntent contentIntent = PendingIntent.getActivity(this, 0,                  new Intent(this, MainActivity.class), 0);          builder.setContentIntent(contentIntent);        builder.setSmallIcon(R.drawable.icon);        builder.setTicker("Foreground Service Start");        builder.setContentTitle("Foreground Service");        builder.setContentText("Make this service run in the foreground.");        Notification notification = builder.build();                startForegroundCompat(NOTIFICATION_ID, notification);      }          @Override    public int onStartCommand(Intent intent, int flags, int startId) {        super.onStartCommand(intent, flags, startId);        Log.d(TAG, "onStartCommand");                return START_STICKY;    }         @Override      public IBinder onBind(Intent intent) {          return null;      }      @Override      public void onDestroy() {          super.onDestroy();        Log.d(TAG, "onDestroy");                stopForegroundCompat(NOTIFICATION_ID);      }        void invokeMethod(Method method, Object[] args) {        try {            method.invoke(this, args);        } catch (InvocationTargetException e) {            // Should not happen.            Log.w("ApiDemos", "Unable to invoke method", e);        } catch (IllegalAccessException e) {            // Should not happen.            Log.w("ApiDemos", "Unable to invoke method", e);        }    }        /**     * This is a wrapper around the new startForeground method, using the older     * APIs if it is not available.     */    void startForegroundCompat(int id, Notification notification) {        if (mReflectFlg) {            // If we have the new startForeground API, then use it.            if (mStartForeground != null) {                mStartForegroundArgs[0] = Integer.valueOf(id);                mStartForegroundArgs[1] = notification;                invokeMethod(mStartForeground, mStartForegroundArgs);                return;            }                // Fall back on the old API.            mSetForegroundArgs[0] = Boolean.TRUE;            invokeMethod(mSetForeground, mSetForegroundArgs);            mNM.notify(id, notification);        } else {            /* 还可以使用以下方法,当sdk大于等于5时,调用sdk现有的方法startForeground设置前台运行,             * 否则调用反射取得的sdk level 5(对应Android 2.0)以下才有的旧方法setForeground设置前台运行 */                        if(VERSION.SDK_INT >= 5) {                startForeground(id, notification);            } else {                // Fall back on the old API.                mSetForegroundArgs[0] = Boolean.TRUE;                invokeMethod(mSetForeground, mSetForegroundArgs);                mNM.notify(id, notification);                }        }    }    /**     * This is a wrapper around the new stopForeground method, using the older     * APIs if it is not available.     */    void stopForegroundCompat(int id) {        if (mReflectFlg) {            // If we have the new stopForeground API, then use it.            if (mStopForeground != null) {                mStopForegroundArgs[0] = Boolean.TRUE;                invokeMethod(mStopForeground, mStopForegroundArgs);                return;            }                // Fall back on the old API.  Note to cancel BEFORE changing the            // foreground state, since we could be killed at that point.            mNM.cancel(id);            mSetForegroundArgs[0] = Boolean.FALSE;            invokeMethod(mSetForeground, mSetForegroundArgs);        } else {            /* 还可以使用以下方法,当sdk大于等于5时,调用sdk现有的方法stopForeground停止前台运行,             * 否则调用反射取得的sdk level 5(对应Android 2.0)以下才有的旧方法setForeground停止前台运行 */                        if(VERSION.SDK_INT >= 5) {                stopForeground(true);            } else {                // Fall back on the old API.  Note to cancel BEFORE changing the                // foreground state, since we could be killed at that point.                mNM.cancel(id);                mSetForegroundArgs[0] = Boolean.FALSE;                invokeMethod(mSetForeground, mSetForegroundArgs);            }        }    }}

前台Service运行后的效果如图:

(1).通知栏显示内容:


(2).下拉后通知栏显示内容:


原创粉丝点击