53

我有一项服务定义为:

public class SleepAccelerometerService extends Service implements SensorEventListener

本质上,我正在制作一个应用程序,用于在用户睡觉时将他或她的手机/设备放在床上时出于各种原因监控加速度计活动。这是一项长期运行的服务,不得在夜间终止。根据夜间发生的后台应用程序和周期性进程的数量,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/

4

7 回答 7

72

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

文档说以下内容

启动的服务可以使用startForeground(int, Notification)API 将服务置于前台状态,系统认为它是用户主动意识到的,因此在内存不足时不适合杀死。(理论上,在当前前台应用程序的极端内存压力下,服务仍然可能被杀死,但实际上这不应该是一个问题。)

主要用于当终止服务会对用户造成干扰时,例如终止音乐播放器服务将停止音乐播放。

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

于 2010-10-04T16:01:02.450 回答
16

当您使用 BIND_AUTO_CREATE 将 Service 绑定到 Activity 时,您的服务将在您的 Activity 被销毁且未绑定之后被终止。它不取决于您如何实现 Services unBind 方法,它仍然会被杀死。

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

于 2011-01-27T18:57:59.953 回答
12

正如戴夫已经指出的那样,您可以Service使用前台优先级运行您的。但是这种做法应该只在绝对必要的情况下使用,即如果服务被Android杀死会导致糟糕的用户体验。这就是“前台”的真正含义:您的应用程序不知何故位于前台,如果它被杀死(例如,因为它播放歌曲或视频),用户会立即注意到它。

在大多数情况下,为您的服务请求前台优先级是适得其反的!

这是为什么?当 Android 决定杀死 aService时,它这样做是因为它缺乏资源(通常是 RAM)。根据不同的优先级,Android 决定终止哪些正在运行的进程(包括服务)以释放资源。这是您希望发生的健康过程,以便用户获得流畅的体验。如果你在没有充分理由的情况下请求前台优先级,只是为了不让你的服务被杀掉,那很可能会导致糟糕的用户体验。或者你能保证你的服务保持在最小的资源消耗范围内并且没有内存泄漏吗?1

Android 提供粘性服务来标记服务,如果它们被杀死,应该在一些宽限期后重新启动。这种重新启动通常会在几秒钟内发生。

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

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

于 2014-03-03T21:37:25.263 回答
5

我有一个类似的问题。一段时间后,在某些设备上,Android 会终止我的服务,甚至startForeground()也无济于事。我的客户不喜欢这个问题。我的解决方案是使用AlarmManager类来确保服务在必要时运行。我使用AlarmManager创建一种看门狗定时器。它不时检查服务是否应该运行并重新启动它。我还使用SharedPreferences来保留服务是否应该运行的标志。

创建/关闭我的看门狗定时器:

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 的代码只是为了简化它。

于 2015-09-22T08:33:18.130 回答
4

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、BI​​ND_AUTO_CREATE、BIND_IMPORTANT、BIND_NOT_FOREGROUND、BIND_WAIVE_PRIORITY。

请注意,BIND_AUTO_CREATE 的含义在 ICS 中已更改, 未指定的旧应用程序 BIND_AUTO_CREATE 将自动具有标志 BIND_WAIVE_PRIORITY BIND_ADJUST_WITH_ACTIVITY 为其设置。

于 2014-01-21T09:29:45.570 回答
2

保持您的服务占用空间小,这会降低 Android 关闭您的应用程序的可能性。您无法阻止它被杀死,因为如果可以,那么人们可以轻松创建持久性间谍软件

于 2010-10-04T15:42:17.790 回答
2

我正在开发一个应用程序,并面临通过应用程序终止来终止我的服务的问题。我在谷歌上进行了研究,发现我必须将其设为前台。以下是代码:

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);

    }
}

啤酒花可能会有所帮助!!!!

于 2016-06-24T12:40:06.063 回答