Android创建前台运行的Service

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

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

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

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

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

  1. import java.lang.reflect.InvocationTargetException;  
  2. import java.lang.reflect.Method;  
  3.   
  4. import android.app.Notification;  
  5. import android.app.NotificationManager;  
  6. import android.app.PendingIntent;  
  7. import android.app.Service;  
  8. import android.content.Context;  
  9. import android.content.Intent;  
  10. import android.os.IBinder;  
  11. import android.os.Build.VERSION;  
  12. import android.util.Log;  
  13.   
  14. public class ForegroundService extends Service {  
  15.     private static final String TAG = "ForegroundService";  
  16.       
  17.     private boolean mReflectFlg = false;  
  18.       
  19.     private static final int NOTIFICATION_ID = 1// 如果id设置为0,会导致不能设置为前台service  
  20.     private static final Class<?>[] mSetForegroundSignature = new Class[] {  
  21.         boolean.class};  
  22.     private static final Class<?>[] mStartForegroundSignature = new Class[] {  
  23.         int.class, Notification.class};  
  24.     private static final Class<?>[] mStopForegroundSignature = new Class[] {  
  25.         boolean.class};  
  26.   
  27.     private NotificationManager mNM;    
  28.     private Method mSetForeground;  
  29.     private Method mStartForeground;    
  30.     private Method mStopForeground;  
  31.     private Object[] mSetForegroundArgs = new Object[1];  
  32.     private Object[] mStartForegroundArgs = new Object[2];    
  33.     private Object[] mStopForegroundArgs = new Object[1];    
  34.       
  35.     @Override    
  36.     public void onCreate() {    
  37.         super.onCreate();  
  38.         Log.d(TAG, "onCreate");  
  39.           
  40.         mNM = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);    
  41.         try {    
  42.             mStartForeground = ForegroundService.class.getMethod("startForeground", mStartForegroundSignature);    
  43.             mStopForeground = ForegroundService.class.getMethod("stopForeground", mStopForegroundSignature);    
  44.         } catch (NoSuchMethodException e) {    
  45.             mStartForeground = mStopForeground = null;    
  46.         }    
  47.           
  48.         try {  
  49.             mSetForeground = getClass().getMethod("setForeground",  
  50.                     mSetForegroundSignature);  
  51.         } catch (NoSuchMethodException e) {  
  52.             throw new IllegalStateException(  
  53.                     "OS doesn't have Service.startForeground OR Service.setForeground!");  
  54.         }  
  55.   
  56.         Notification.Builder builder = new Notification.Builder(this);  
  57.         PendingIntent contentIntent = PendingIntent.getActivity(this0,    
  58.                 new Intent(this, MainActivity.class), 0);    
  59.         builder.setContentIntent(contentIntent);  
  60.         builder.setSmallIcon(R.drawable.icon);  
  61.         builder.setTicker("Foreground Service Start");  
  62.         builder.setContentTitle("Foreground Service");  
  63.         builder.setContentText("Make this service run in the foreground.");  
  64.         Notification notification = builder.build();  
  65.           
  66.         startForegroundCompat(NOTIFICATION_ID, notification);    
  67.     }    
  68.       
  69.     @Override  
  70.     public int onStartCommand(Intent intent, int flags, int startId) {  
  71.         super.onStartCommand(intent, flags, startId);  
  72.         Log.d(TAG, "onStartCommand");  
  73.           
  74.         return START_STICKY;  
  75.     }   
  76.       
  77.     @Override    
  78.     public IBinder onBind(Intent intent) {    
  79.         return null;    
  80.     }    
  81.   
  82.     @Override    
  83.     public void onDestroy() {    
  84.         super.onDestroy();  
  85.         Log.d(TAG, "onDestroy");  
  86.           
  87.         stopForegroundCompat(NOTIFICATION_ID);    
  88.     }  
  89.       
  90.     void invokeMethod(Method method, Object[] args) {  
  91.         try {  
  92.             method.invoke(this, args);  
  93.         } catch (InvocationTargetException e) {  
  94.             // Should not happen.  
  95.             Log.w("ApiDemos""Unable to invoke method", e);  
  96.         } catch (IllegalAccessException e) {  
  97.             // Should not happen.  
  98.             Log.w("ApiDemos""Unable to invoke method", e);  
  99.         }  
  100.     }  
  101.       
  102.     /** 
  103.      * This is a wrapper around the new startForeground method, using the older 
  104.      * APIs if it is not available. 
  105.      */  
  106.     void startForegroundCompat(int id, Notification notification) {  
  107.         if (mReflectFlg) {  
  108.             // If we have the new startForeground API, then use it.  
  109.             if (mStartForeground != null) {  
  110.                 mStartForegroundArgs[0] = Integer.valueOf(id);  
  111.                 mStartForegroundArgs[1] = notification;  
  112.                 invokeMethod(mStartForeground, mStartForegroundArgs);  
  113.                 return;  
  114.             }  
  115.       
  116.             // Fall back on the old API.  
  117.             mSetForegroundArgs[0] = Boolean.TRUE;  
  118.             invokeMethod(mSetForeground, mSetForegroundArgs);  
  119.             mNM.notify(id, notification);  
  120.         } else {  
  121.             /* 还可以使用以下方法,当sdk大于等于5时,调用sdk现有的方法startForeground设置前台运行, 
  122.              * 否则调用反射取得的sdk level 5(对应Android 2.0)以下才有的旧方法setForeground设置前台运行 */  
  123.               
  124.             if(VERSION.SDK_INT >= 5) {  
  125.                 startForeground(id, notification);  
  126.             } else {  
  127.                 // Fall back on the old API.  
  128.                 mSetForegroundArgs[0] = Boolean.TRUE;  
  129.                 invokeMethod(mSetForeground, mSetForegroundArgs);  
  130.                 mNM.notify(id, notification);      
  131.             }  
  132.         }  
  133.     }  
  134.   
  135.     /** 
  136.      * This is a wrapper around the new stopForeground method, using the older 
  137.      * APIs if it is not available. 
  138.      */  
  139.     void stopForegroundCompat(int id) {  
  140.         if (mReflectFlg) {  
  141.             // If we have the new stopForeground API, then use it.  
  142.             if (mStopForeground != null) {  
  143.                 mStopForegroundArgs[0] = Boolean.TRUE;  
  144.                 invokeMethod(mStopForeground, mStopForegroundArgs);  
  145.                 return;  
  146.             }  
  147.       
  148.             // Fall back on the old API.  Note to cancel BEFORE changing the  
  149.             // foreground state, since we could be killed at that point.  
  150.             mNM.cancel(id);  
  151.             mSetForegroundArgs[0] = Boolean.FALSE;  
  152.             invokeMethod(mSetForeground, mSetForegroundArgs);  
  153.         } else {  
  154.             /* 还可以使用以下方法,当sdk大于等于5时,调用sdk现有的方法stopForeground停止前台运行, 
  155.              * 否则调用反射取得的sdk level 5(对应Android 2.0)以下才有的旧方法setForeground停止前台运行 */  
  156.               
  157.             if(VERSION.SDK_INT >= 5) {  
  158.                 stopForeground(true);  
  159.             } else {  
  160.                 // Fall back on the old API.  Note to cancel BEFORE changing the  
  161.                 // foreground state, since we could be killed at that point.  
  162.                 mNM.cancel(id);  
  163.                 mSetForegroundArgs[0] = Boolean.FALSE;  
  164.                 invokeMethod(mSetForeground, mSetForegroundArgs);  
  165.             }  
  166.         }  
  167.     }  
  168.   
  169. }  

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

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


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


转自:http://blog.csdn.net/ameyume/article/details/9150755


如何让Android service进程变成前台进程

Android的前台Service
        Service几乎都是在后台运行的,一直以来它都是默默地做着辛苦的工作。但是Service的系统优先级还是比较低的,当系统出现内存不足情况时,就有可能会回收掉正在后台运行的Service。如果你希望Service可以一直保持运行状态,而不会由于系统内存不足的原因导致被回收,就可以考虑使用前台Service
前台Service和普通Service最大的区别就在于,它会一直有一个正在运行的图标在系统的状态栏显示,下拉状态栏后可以看到更加详细的信息,非常类似于通知的效果。当然有时候你也可能不仅仅是为了防止Service被回收才使用前台Service,有些项目由于特殊的需求会要求必须使用前台Service,比如说墨迹天气,它的Service在后台更新天气数据的同时,还会在系统状态栏一直显示当前天气的信息,如下图所示:
 
 


那么我们就来看一下如何才能创建一个前台Service吧,其实并不复杂,如下所示:
 

 
这里只是修改了Service中onCreate()方法的代码。可以看到,我们首先创建了一个Notification对象,然后调用了它的setLatestEventInfo()方法来为通知初始化布局和数据,并在这里设置了点击通知后就打开MainActivity。然后调用startForeground()方法就可以让MyService变成一个前台Service,并会将通知的图片显示出来。
现在重新运行一下程序, Service就会以前台Service的模式启动了,并且在系统状态栏会弹出一个通栏图标,下拉状态栏后可以看到通知的详细内容,如下图所示:
 
 


Android:退出程序后保持Serivce开启不关闭 

Android中,service的开启,默认是绑定activity的,是activity级的。

如果要实现当退出程序后,保持Service的运行,那么需要把service设置成为system级的,设置方法:
在AndroidManifest.xml中注册service时,加上属性android:process,如:
   
   
<service
      android:name = "com.jansun.pushnotification.PushNotificationService"
      android:enabled = "true"
      android:process = "system"
      />
     
另外,还要在启动service时,加入FLAG_ACTIVITY_NEW_TASK标签,如:
   
   
public static void actionStart ( Context ctx ) {
//System.out.println("---- Notification service started!");
Intent i = new Intent(ctx,  PushNotificationService  .class);
i.setAction(ACTION_START);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
ctx.startService(i);
}

至此,当你退出程序后,service还在系统后台正常运行,目标达成。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值