Android: stopService() не вызывает onDestroy()!

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

Активность:

public void playTrack(View view){       
    Intent i=new Intent(this,playService.class);
    i.setAction("com.c0dehunterstudios.relaxer.PLAY");

    if(isPlaying){ 
          stopService(i);   
          isPlaying=false;
          Log.v("ACTIVITY", "Stopping..");
    }

    startService(i);
    isPlaying=true;
}

Услуги:

public void OnDestroy(){
    Log.v("SERVICE","Service killed");
    player.stop();
    super.onDestroy();  
}

Но, к сожалению, это не сработало - на самом деле он даже не дошел до "Службы, убитой" внутри OnDestroy().

Что я делаю неправильно?

Ответ 1

Во-первых, это onDestroy, а не OnDestroy. Во-вторых, вы должны использовать аннотацию @Override для проверки времени компиляции, поэтому ваш код службы должен выглядеть примерно так:

@Override
public void onDestroy(){
    Log.v("SERVICE","Service killed");
    player.stop();
    super.onDestroy();  
}

Ответ 2

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

Ответ заключается в том, что это ожидаемое поведение - я могу догадаться, но точно не знаю, почему. Таким образом, мое решение в этом случае состояло в том, чтобы создать публичный статический метод, чтобы остановить действия службы вручную, что происходит в момент ее вызова, а затем stopService() будет вызывать onDestroy в свое собственное свободное время...

В случае для этого примера (который, вероятно, давно ушел, я, вероятно, решил бы, чтобы служба работала до тех пор, пока она не ожидала от приложения, но предоставляет способы изменения аудиофайла, пока служба по-прежнему активна.

Ответ 3

Для начала нужно уточнить, сколько видов сервисов в Android. AFAIK, есть:

  • Передний план обслуживания.
  • Фоновый сервис.
  • Связанный сервис.
  • Намеренное обслуживание.

Эти службы останавливаются по-разному.

  • Передний план: останавливаться только тогда, когда вы намеренно останавливаете его, вызывая stopService() в действии или фрагменте, где вы запускаете эту службу, или вызываете stopSelf() в ее собственной службе. И обратите внимание, что только эти методы запускают службу onDestroy().
  • Фон: stopService() и stopSelf() делают так же, как передний план. Более того, вы должны знать, что этот сервис находится в одном потоке с вызывающим его действием или фрагментом, поэтому, если вы уничтожите действие или фрагмент, этот сервис также остановится, но без вызова onDestroy(). Это в основном разрушает подполье. Таким образом, если вы хотите отловить, когда эта служба останавливается, вам нужно добавить android:stopWithTask="false" при объявлении службы в файле манифеста следующим образом:

    <application>
        //....
        <service android:name=".services.catchingStopService" 
             android:stopWithTask="false" /> 
        //....
    </application>
    

    И теперь в своем классе обслуживания вы можете переопределить этот метод, который срабатывает всякий раз, когда эта служба останавливается:

    @Override 
    public void onTaskRemoved(Intent rootIntent) {
        super.onTaskRemoved(rootIntent); 
        // Your job when the service stops. 
    }
    
  • Ограничение: вам нужно справиться с самим собой с помощью bindService() и unbindService(), вы обнаружите, что оно полностью совпадает с starService() и stopService()

  • Намерение: этот тип службы останавливается сам по себе, когда завершает свою работу. И вы можете использовать ResultReceiver для связи между сервисом и действием или фрагментом. Это похоже на BroadcastReceiver. Вы можете легко найти, например, в Google.

Резюме: исходя из своей цели, выберите тип услуги, которая вас устраивает. И все они согласны с:

  • Не рассчитывайте на onDestroy(), чтобы знать, когда служба останавливается, потому что это иногда его называют подземным; точнее, звонки onDestroy когда stopService() или stopSelf() вызывает (BoundService работает в Точно так же, я думаю, но подобным способом, может быть unBind(), я не проверить еще).
  • Используйте атрибут android: stopWithTask = "false", чтобы узнать, когда сервис действительно останавливается.
  • Все типы сервисов останавливаются, когда устройство выключается или ОС убивает его, если утечки памяти устройства.
  • Вы также должны взглянуть на возвращение флага onStartCommand() иметь возможность иметь дело с тем, когда службы останавливаются, как перезапустить службу снова или что-то. Вот некоторые ключевые слова, которые вы можете искать:
    • START_STICKY
    • <action android:name="android.intent.action.BOOT_COMPLETED" />
    • <action android:name="android.intent.action.ACTION_SHUTDOWN" />
    • <actionandroid:name="android.intent.action.QUICKBOOT_POWEROFF" />

Ответ 4

В моем случае я печатал журнал внутри onDestroy, и он не печатал журнал, и я думал, что onDestroy не вызывает, когда я вызываю stopService. но в Android studio много раз не печатает журнал, поэтому вы можете один раз дважды проверить или проверить с помощью отладки или тоста.