Android: сервис разрушается при повороте дисплея - PullRequest
5 голосов
/ 03 апреля 2011

У меня есть служба, которая работает в отдельном процессе. Я обнаружил, что после того, как поток пользовательского интерфейса основного процесса выходит из onDestroy (), мой сервис разрушается, хотя я предоставил контекст приложения с привязкой и указал BIND_AUTO_CREATE.

В потоке пользовательского интерфейса моего основного процесса onCreate () у меня есть этот код привязки:

Intent intent = new Intent(mAppContext, MyService.class);
mAppContext.bindService(intent, mMyServiceConnection, Context.BIND_AUTO_CREATE);

В потоке пользовательского интерфейса моего основного процесса onDestroy () у меня есть этот код привязки:

mAppContext.unbindService(mMyServiceConnection);

Обратите внимание, что я никогда не вызываю stopService ().

Документация Android для bindService () гласит:

Услуга будет считаться востребованной системой только до тех пор, пока существует вызывающий контекст.

Если я правильно читаю, потому что я предоставил контекст приложения, служба считается необходимой системе для жизни приложения.

Я думал, что, возможно, контекст приложения умирает с помощью onDestroy (). Это то, что говорится в документации Android для getApplicationContext ():

Возвращает контекст одного глобального объекта Application текущего процесса.

Если контекст приложения умирает с помощью onDestroy (), то я думаю, что в Android есть большая проблема. Проблема заключается в том, что при вращении дисплея вызывается onDestroy () (и сразу за ним следует onCreate ()). Таким образом, эффект заключается в том, что когда дисплей поворачивается - и это происходит довольно часто в моем случае! - Мой сервис всегда выходит.

Обратите внимание, что pid процесса моего приложения никогда не меняется, т.е. это тот же процесс. Это важно в свете документации для getApplicationContext () с указанием «текущий процесс».

Вот что показывают мои журналы отладки:

04-03 05: 15: 12.874: DEBUG / MyApp (841): main onDestroy
04-03 05: 15: 12.895: DEBUG / MyApp (847): служба onUnbind
04-03 05: 15: 12.895: DEBUG / MyApp (847): сервис onDestroy
04-03 05: 15: 12.934: DEBUG / MyApp (841): основное вкл. Создание
04-03 05: 15: 12.966: DEBUG / MyApp (847): обслуживание при создании
04-03 05: 15: 12.975: DEBUG / MyApp (847): служба onBind

Итак, мои вопросы:

1) Верно ли мое понимание привязки / отмены привязки?

2) Есть ли способ, чтобы мой сервис не был уничтожен при вызове onDestroy () потока пользовательского интерфейса?

Хак для вопроса №2 - никогда не отвязывать. Но мне это не нравится, потому что тогда я пропускаю привязку каждый раз, когда вызывается onDestroy (). Я мог бы «вспомнить», что у меня есть одна утечка привязки и утечка только этой, но потом у меня есть каскадные хаки, и это действительно ужасно.

Ответы [ 3 ]

4 голосов
/ 03 апреля 2011

1) Да, я думаю, что вы понимаете правильно (я говорю, я думаю, потому что я думаю, что я понимаю, что вы говорите ;-)). Используемый вами флаг означает «запускать эту службу автоматически, если кто-то пытается привязать ее и поддерживать в ней работу до тех пор, пока с ней кто-то связан, но как только с ней никто не связан, не стесняйтесь ее убивать».

2) Проверьте флаг START_STICKY, как описано здесь . Это должно позволить вам запустить службу и поддерживать ее работу независимо от того, что происходит с вызывающим Context

Как правило, onDestroy() означает, что ваша деятельность будет убита. При повороте дисплея Activity уничтожается и воссоздается. Вы несете ответственность за сохранение любого состояния в Bundle соответствующим способом и последующее восстановление его в onCreate().

0 голосов
/ 17 марта 2016

служба уничтожается, только если выполняются оба следующих условия:

  1. Все вызовы bindService () были сопоставлены с соответствующими вызовами unbindService ().
  2. Если кто-то вызвал startService (), кто-то также вызвал stopService () или службу stopSelf ().

Служба может быть запущена и иметь связанные с ней подключения. В таком случае система будет поддерживать работу службы до тех пор, пока она либо запущена, либо имеется одно или несколько подключений к ней с флагом Context.BIND_AUTO_CREATE. Если ни одна из этих ситуаций не выполняется, вызывается метод onDestroy () службы, и служба эффективно завершается.

это дает отличное решение, которое также довольно корректно и безопасно!

говорят, что есть 2 действия (в этом примере 'viewer' и 'chat'), которые нуждаются в обслуживании, если оба bindService И startService. Также используя связыватель, они обновляют 'viewer_connected' и 'chat_connected' во время onStart и onStop.

Затем служба запускает цикл в потоке, который делает это:

public isRunning = true;
while (isRunning) {

    if (viewer_connected) {
        // send update to viewer activity
    }

    if (chat_connected) {
        // send update to chat activity
    }

    try {
        Thread.sleep(5000);
    } catch (Exception e) { isRunning=false; }

    // 3 second timeout before destroying service
    if (!viewer_connected && !chat_connected) {
        try { Thread.sleep(3000); } catch (Exception e) { isRunning=false; }

        if (!viewer_connected && !chat_connected) isRunning=false;
    }

}
stopSelf();

Это работает, потому что для того, чтобы отключить службу, нужны как действия, так и служба, чтобы остановить себя (), то есть истекает время ожидания, прежде чем служба будет уничтожена.

0 голосов
/ 03 апреля 2011

Ваш сервис убит:

  1. если в стеке есть секунда Activity?
  2. если вы обрабатываете изменения конфигурации?

Зачем вам нужен сервис, чтобы остаться в живых после того, как ваша заявка была уничтожена?

Я думаю, что общее практическое правило заключается в том, что вы не можете быть уверены, когда ваши действия и услуги будут убиты. Если это блокирует то, чего вы пытаетесь достичь, возможно, есть разумный способ обойти это.

Редактировать - фактически вы можете справиться с изменением конфигурации ориентации, чтобы ваша деятельность не была перезапущена. Для получения дополнительной информации см. Вторую половину этот ответ .

О "втором" Activity: Изображение, с которого вы начинаете занятие A, а затем занятие B. Теперь вы поворачиваете экран, пока отображается B, вызывая перезапуск B. Будет ли A перезапущен в этот момент? Я не уверен, но у меня есть догадка, что A будет иметь тенденцию оставаться в живых и поддерживать ваше приложение во время изменения ориентации. Это может стать еще одной стратегией для поддержания вашего сервиса, если вы к этому стремитесь.

...