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).下拉后通知栏显示内容: