START_STICKY, передний план службы Android исчезает без уведомления - PullRequest
7 голосов
/ 08 июля 2011

Я запустил службу в моем новом приложении. Услуга заранее, с уведомлением. Когда это выполняется в AVD 2.1 API Level 7, все работает нормально. Но когда он запускается на Samsung Galaxy Tab с Gingerbread, служба запускается (значок и имя приложения появляются в верхней части области уведомлений), но через несколько секунд служба исчезает. Последняя запись в журнале, которую я вижу, связана с моим приложением, является результатом моего Log.d («Слоганы», «Возврат с« + START_STICKY) », который непосредственно предшествует« return START_STICKY; » в переопределении onStartCommand моей службы, следующим образом:

@Override
public int onStartCommand(Intent intent, int flags, int startId) {

    int rc ;
    Log.d("Taglines","onStartCommand()");
    Toast.makeText(this, "Starting service TagsManager", Toast.LENGTH_SHORT).show();
    Log.d("Taglines","Calling super.onStartCommand()");
    rc = super.onStartCommand(intent,flags,startId);
    Log.d("Taglines","super.onStartCommand return code was " + rc);
    createNotification(INITIAL_NOTIFICATION_TEXT);
    Log.d("Taglines","Returning with " + START_STICKY);
    return START_STICKY ;
}

Уведомление настроено так:

void createNotification(String text) {

    Log.d("Taglines","createNotification called");
    if (mNotificationManager == null) {
        // Get a reference to the Notification Manager
        String ns = Context.NOTIFICATION_SERVICE;
        mNotificationManager = (NotificationManager) getSystemService(ns);
        Log.d("Taglines","Obtained reference to Notification Manager");
    }

    // Instantiate the Notification
    int icon = R.drawable.ic_notification;
    CharSequence tickerText = "Taglines";
    long when = System.currentTimeMillis();

    notification = new Notification(icon, tickerText, when);

    // Define Notification's expanded message and intent
    Log.d("Taglines","createNotificacion() .. getApplicationContext");
    context = getApplicationContext();
    contentText = text;
    // notificationIntent = new Intent(this, TagsOverview.class);
    notificationIntent = new Intent(this, TagsServiceMenu.class);
    contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);

    notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent);

    // Pass the Notification to the NotificationManager: 
    Log.d("Taglines","createNotificacion() ... passing notification");
    mNotificationManager.notify(NOTIFICATION_ID, notification);
    Log.d("Taglines","Starting foreground");
    startForeground(NOTIFICATION_ID, notification);
    Log.d("Taglines","Started");
}

Это результат "adb logcat" при запуске службы:

D/Taglines(21863): Starting service
D/Taglines(21863): TagsManager(nullary) completed
D/Taglines(21863): onStartCommand()
D/Taglines(21863): Calling super.onStartCommand()
D/Taglines(21863): super.onStartCommand eturn code was 2
D/Taglines(21863): createNotification called
D/Taglines(21863): Obtained reference to Notification Manager
D/Taglines(21863): createNotificacion() .. getApplicationContext
D/Taglines(21863): createNotificacion() ... passing notification
D/Taglines(21863): Starting foreground
D/Taglines(21863): Started
D/Taglines(21863): Returning with 1

После этого ничего особенного (вообще ничего из PID 21863). Просто куча:

D/KeyguardViewMediator(  302): setHidden false
D/KeyguardViewMediator(  302): setHidden false
D/KeyguardViewMediator(  302): setHidden false
D/KeyguardViewMediator(  302): setHidden false
D/KeyguardViewMediator(  302): setHidden false
W/InputManagerService(  302): Window already focused, ignoring focus gain of:         com.android.internal.view.IInputMethodClient$Stub$Proxy@40bc06e8
D/KeyguardViewMediator(  302): setHidden false
D/KeyguardViewMediator(  302): setHidden false
D/KeyguardViewMediator(  302): setHidden false
D/KeyguardViewMediator(  302): setHidden false
D/KeyguardViewMediator(  302): setHidden false
D/KeyguardViewMediator(  302): setHidden false
D/KeyguardViewMediator(  302): setHidden false
D/KeyguardViewMediator(  302): setHidden false
D/KeyguardViewMediator(  302): setHidden false

Я не думаю, что это необходимо в этом случае, но вот соответствующая часть AndroidManifest.xml:

    <service android:name=".TagsManager"
             android:exported="false">
    </service>

Где я мог ошибиться? Какую другую информацию я могу предоставить?

Ответы [ 2 ]

11 голосов
/ 29 июля 2011

Несколько вещей:

  1. Избавьтесь от mNotificationManager.notify(NOTIFICATION_ID, notification);.startForeground() отображает значок уведомления для вас.

  2. Передний план Service s все еще может быть убит, они просто менее вероятно.

  3. В 2.3 есть ошибка (не уверенная, была ли она исправлена), когда после уничтожения и перезапуска Service его onStartCommand() НЕ будет вызываться снова.Вместо этого вам придется выполнить любую настройку в onCreate().

1 голос
/ 12 ноября 2013

Оба кода имеют значение только тогда, когда в телефоне не хватает памяти и убивает Service до того, как он завершит работу.START_STICKY указывает ОС пересоздать службу после того, как у нее будет достаточно памяти, и снова вызвать onStartCommand() с нулевым намерением.START_NOT_STICKY говорит ОС, чтобы она больше не беспокоилась о воссоздании службы.Существует также третий код START_REDELIVER_INTENT, который сообщает ОС для воссоздания Service И повторной доставки того же намерения onStartCommand().

В этой статье Дайан Хакборн объясняется история вопросаэто намного лучше, чем официальная документация.

Ключевой частью здесь является новый код результата, возвращаемый функцией, сообщающий системе, что она должна делать со службой, если ее процесс убит во время работы:

START_STICKY в основном совпадает с предыдущим поведением, когда служба остается «запущенной» и позже будет перезапущена системой.Единственное отличие от предыдущих версий платформы состоит в том, что при перезапуске из-за прекращения процесса onStartCommand () будет вызываться для следующего экземпляра службы с нулевым намерением, а не вызываться вообще.Службы, которые используют этот режим, должны всегда проверять этот случай и обращаться с ним соответствующим образом.

START_NOT_STICKY говорит, что после возврата из onStartCreated (), если процесс завершается без оставшихся команд запуска для доставки, то службабудет остановлен вместо перезапуска.Это имеет больше смысла для сервисов, которые предназначены для запуска только при выполнении команд, отправленных им.Например, служба может запускаться каждые 15 минут после подачи сигнала тревоги для опроса какого-либо состояния сети.Если его убивают во время выполнения этой работы, лучше всего просто дать ему остановиться и начать работу при следующем срабатывании будильника.

START_REDELIVER_INTENT похож на START_NOT_STICKY, за исключением случаев, когда процесс службы прерывается перед вызовомstopSelf () для данного намерения, это намерение будет повторно доставлено ему до его завершения (если только после некоторого количества попыток оно все еще не может завершиться, в этот момент система сдается).Это полезно для служб, которые получают команды работы и хотят убедиться, что они в конечном итоге завершают работу для каждой отправленной команды.

...