Android创建前台运行的Service

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

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

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

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

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

[java] view
plain
copy

  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(this, 0,    
  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. }  

Demo:http://download.csdn.net/detail/u012808234/9367032

时间: 2024-12-02 22:21:10

Android创建前台运行的Service的相关文章

Android创建服务之started service详细介绍_Android

创建started service        应用组件(例如Activity)调用startService()来启动一个Service,将需要的参数通过Intent传给Service,Service将会在onStartCommand函数中获得Intent. 有两种方式可以创建started service,一种是扩展Service类,另外一种是扩展IntentService类 扩展Service       这是所有服务的基类.扩展这个类的时候,特别重要的一点是,需要创建一个新的线程来做服务

Android判断App前台运行还是后台运行(运行状态)_Android

本文通过图文并茂的方式给大家介绍android判断app状态的相关内容,具体详情如下所示: 要了解这块,首先需要明白一些概念,app,process,task 1.process就是进程,是linux的概念. 2.一般一个app拥有一个uid,运行在一个进程里,如果app中给service等定义不同的uid,那Service就运行在另外一个进程里,也就是说uid就相当于进程的id一样,一个uid就代表一个进程:也可以几个app定义一个uid,那他们就运行在一个进程里了. 3.task是andro

Android判断App是否在前台运行

// Android开发中,有时候需要判断App是否在前台运行. 代码实现如下: private boolean isRunningForeground(Context context) { ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); ComponentName cn = am.getRunningTasks(1).get(0).topActivity; St

在Android中 获取正在运行的Service 实例_Android

public class ServiceList extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); TextView tv = new TextView(this); ActivityManager activityManger = (ActivityManager) getSystemService(ACTIV

在Android中 获取正在运行的Service 实例

public class ServiceList extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); TextView tv = new TextView(this); ActivityManager activityManger = (ActivityManager) getSystemService(ACTIV

Android开发四大组件Activity/Service/Broadcast Receiver/Content Provider详解

Android开发的四大组件一.Activity详解二.Service详解三.Broadcast Receiver详解四.Content Provider详解外加一个重要组件 intent的详解. 一.Activity详解 Activty的生命周期的也就是它所在进程的生命周期. 一个Activity的启动顺序: onCreate()-->onStart()-->onResume() 当另一个Activity启动时:第一个Activity onPause()-->第二个Activity  

docker如何创建一个运行后台进程的容器并同时提供shell终端

只看标题还不是很明显,本文实现docker的这样一种比较常用的功能:通过docker run启动一个容器后,容器中已经运行了一个后台进程(这里以监听80端口的nginx为例),同时进入一个shell终端可供操作,而不受限于只能在前台运行nginx与运行shell终端之间的一种.这个例子实现了,那么其他类似的运行多任务docker就可以以此类推.另外本文还提供了一种在docker容器内部安装软件(vim)的方法,对于定制自己需要的镜像大有帮助. 你可能需要先阅读docker专题(2):docker

Android应用程序运行的性能设计综述

Android应用程序运行的移动设备受限于其运算能力,存储空间,及电池续航.由此,它必须是高效的.电池续航可能是一个促使你优化程序的原因,即使他看起来已经运行的足够快了.由于续航对用户的重要性,当电量耗损陡增时,意味这用户迟早会发现是由于你的程序. 虽然这份文档主要包含着细微的优化,但这些绝不能成为你软件成败的关键.选择合适的算法和数据结构永远是你最先应该考虑的事情,但这超出这份文档之外. 1. 介绍 写出高效的代码有两条基本的原则: ◆ 不作没有必要的工作 ◆ 尽量避免内存分配. 2. 明智的

Android应用程序运行的性能设计

Android应用程序运行的移动设备受限于其运算能力,存储空间,及电池续航.由此,它必须是高效的.电池续航可能是一个促使你优化程序的原因,即使他看起来已经运行的足够快了.由于续航对用户的重要性,当电量耗损陡增时,意味这用户迟早会发现是由于你的程序. 虽然这份文档主要包含着细微的优化,但这些绝不能成为你软件成败的关键.选择合适的算法和数据结构永远是你最先应该考虑的事情,但这超出这份文档之外. 1. 介绍 写出高效的代码有两条基本的原则: ◆ 不作没有必要的工作 ◆ 尽量避免内存分配. 2. 明智的