Android:保持后台服务(防止进程死亡)

我有一个服务被定义为:

public class SleepAccelerometerService extends Service implements SensorEventListener 

从本质上讲,我正在制作一个应用程序,用于监视加速度计活动的各种原因,而用户睡觉时,他/她的手机/设备在床上。 这是一个长期运行的服务,不能在夜间被杀害。 根据在夜间发生多less背景应用程序和周期性进程,android有时会杀死我的进程,从而结束我的服务。 例:

 10-04 03:27:41.673: INFO/ActivityManager(1269): Process com.androsz.electricsleep (pid 16223) has died. 10-04 03:27:41.681: INFO/WindowManager(1269): WIN DEATH: Window{45509f98 com.androsz.electricsleep/com.androsz.electricsleep.ui.SleepActivity paused=false} 

我不想强迫用户在我的应用程序中将“SleepActivity”或其他一些活动作为前景。 我不能让我的服务定期运行,因为它不断拦截onSensorChanged。

任何提示? 源代码在这里: http : //code.google.com/p/electricsleep/

对于Android 2.0或更高版本,您可以使用startForeground()方法在前台启动您的服务。

该文件说明如下 :

已启动的服务可以使用startForeground(int, Notification) API将服务置于前台状态,系统认为该服务是用户主动注意的内容,因此不适用于内存不足的情况下进行查杀。 (从理论上讲,服务在当前前台应用程序的极端内存压力下可能被杀死,但实际上这不应该成为问题。)

主要用于在杀死服务时对用户造成破坏,例如,杀死音乐播放器服务将阻止音乐播放。

您需要向“正在进行”部分的“通知栏”中显示的方法提供Notification

当您使用BIND_AUTO_CREATE将您的服务绑定到Activity时,您的服务在您的Activity被销毁和解除绑定之后立即被终止。 它不取决于你如何实现你的服务的解绑方法,它仍然会被杀死。

另一种方法是使用Activity的startService方法启动服务。 这样,即使你的Activity被销毁,你的服务也不会被破坏,甚至暂停,但是你必须在适当的时候用stopSelf / stopService自己暂停/销毁它。

正如戴夫已经指出的 ,你可以运行你的Service前景优先。 但是这种做法只能在绝对必要的时候使用,也就是说,如果服务被Android杀死,会导致不好的用户体验。 这就是“前景”的真正含义:你的应用程序在某种程度上处于前台,如果用户死亡(例如播放歌曲或video),用户会立即注意到它。

在大多数情况下,为您的服务请求前台优先权是徒劳的!

这是为什么? 当Android决定杀死一个Service ,它会这样做,因为它缺less资源(通常是RAM)。 基于不同的优先级类别,Android决定哪些正在运行的进程(包括服务)终止以释放资源。 这是你想要发生的一个健康的过程,以便用户有一个平稳的体验。 如果您请求前台优先级,没有一个很好的理由,只是为了防止您的服务被杀死,这很可能会导致不良的用户体验。 或者你能保证你的服务保持在一个最小的资源消耗和没有内存泄漏? 1

Android提供粘性服务来标记在某些宽限期之后应该重新启动的服务。 这个重启通常在几秒钟内发生。

您想要为Android编写XMPP客户端的图像。 您是否应该为包含您的XMPP连接的Service请求前台优先级? 绝对不是,绝对没有理由这样做。 但是,您希望使用START_STICKY作为服务的onStartCommand方法的返回标志。 这样当有资源压力时,你的服务就会停止,一旦情况恢复正常,你的服务就会重启。

1 :我很确定很多Android应用程序都有内存泄漏。 这是偶然的(桌面)程序员不关心的事情。

http://developer.android.com/reference/android/content/Context.html#BIND_ABOVE_CLIENT

public static final int BIND_ABOVE_CLIENT – 在API级别14中添加

标记为bindService(Intent, ServiceConnection, int) :表示绑定到此服务的客户端应用程序认为服务比应用程序本身更重要。 设置时,平台将尝试让内存不足杀手杀死应用程序,然后杀死绑定的服务,但这并不能保证。

其他相同组的标志是:BIND_ADJUST_WITH_ACTIVITY,BIND_AUTO_CREATE,BIND_IMPORTANT,BIND_NOT_FOREGROUND,BIND_WAIVE_PRIORITY。

请注意,ICD中BIND_AUTO_CREATE的含义已更改, 未指定 BIND_AUTO_CREATE 旧应用程序 将自动 BIND_ADJUST_WITH_ACTIVITY 设置 标志 BIND_WAIVE_PRIORITY BIND_ADJUST_WITH_ACTIVITY

我有一个类似的问题。 在一段时间后,在一些设备上杀死我的服务,甚至startForeground()没有帮助。 而我的客户不喜欢这个问题。 我的解决scheme是使用AlarmManager类来确保服务在必要时运行。 我使用AlarmManager创build一种看门狗定时器。 它会不时检查服务是否应该运行并重新启动。 此外,我使用SharedPreferences来保持标志服务是否应该运行。

创build/解散我的看门狗定时器:

 void setServiceWatchdogTimer(boolean set, int timeout) { Intent intent; PendingIntent alarmIntent; intent = new Intent(); // forms and creates appropriate Intent and pass it to AlarmManager intent.setAction(ACTION_WATCHDOG_OF_SERVICE); intent.setClass(this, WatchDogServiceReceiver.class); alarmIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); AlarmManager am=(AlarmManager)getSystemService(Context.ALARM_SERVICE); if(set) am.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + timeout, alarmIntent); else am.cancel(alarmIntent); } 

接收和处理来自看门狗定时器的意图:

 /** this class processes the intent and * checks whether the service should be running */ public static class WatchDogServiceReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if(intent.getAction().equals(ACTION_WATCHDOG_OF_SERVICE)) { // check your flag and // restart your service if it's necessary setServiceWatchdogTimer(true, 60000*5); // restart the watchdogtimer } } } 

事实上,我使用WakefulBroadcastReceiver而不是BroadcastReceiver 。 为了简化,我用BroadcastReceiver给了你代码。

保持您的服务足迹小,这减less了Androidclosures您的应用程序的可能性。 你不能阻止它被杀害,因为如果你能那么人们可以很容易地创build持久的间谍软件

我正在开发一个应用程序,并面临通过应用程序终止来终止我的服务的问题。 我研究了谷歌,发现我必须使它前景。 以下是代码:

 public class UpdateLocationAndPrayerTimes extends Service { Context context; @Override public void onCreate() { super.onCreate(); context = this; } @Override public int onStartCommand(Intent intent, int flags, int startId) { StartForground(); return START_STICKY; } @Override public void onDestroy() { super.onDestroy(); } @Nullable @Override public IBinder onBind(Intent intent) { return null; } private void StartForground() { LocationChangeDetector locationChangeDetector = new LocationChangeDetector(context); locationChangeDetector.getLatAndLong(); Notification notification = new NotificationCompat.Builder(this) .setOngoing(false) .setSmallIcon(android.R.color.transparent) //.setSmallIcon(R.drawable.picture) .build(); startForeground(101, notification); } } 

啤酒花,它可能会帮助!