Подтвердить что ты не робот

Когда запущенная и связанная служба уничтожена?

Я просматривал документацию по обслуживанию в андроиде, когда заметил две противоречивые точки:

В документе служб он указан в Управление жизненным циклом службы

Эти два пути не являются полностью отдельными. То есть вы можете привязываться к сервис, который уже был запущен с помощью startService(). Например, услугу фоновой музыки можно запустить, вызвав startService() с намерением, который определяет музыку для воспроизведения. Позже, возможно, когда пользователь хочет получить определенный контроль над игроком или получить информация о текущей песне, действие может связываться с службы, вызвав bindService(). В таких случаях stopService() или stopSelf() фактически не останавливает службу до тех пор, пока все клиенты отвязать.

Но в документе о связанных службах в Управление жизненным циклом связанной службы

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

Это может быть я, но я думаю, что заявления противоречивы. Может кто-нибудь прояснить...

4b9b3361

Ответ 1

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

Эти два пути не являются полностью отдельными. То есть вы можете привязать к службе, которая была запущена с помощью startService(). Например, услугу фоновой музыки можно запустить, вызвав startService() с намерением, который идентифицирует музыку для воспроизведения. Позже, возможно, когда пользователь захочет осуществлять некоторый контроль над игроком или получить информацию о текущей песне, действие может привязываться к службе, вызывая bindService(). В таких случаях stopService() или stopSelf() фактически не останавливает службу до тех пор, пока все клиенты не отвяжут.

Квинтэссенция: если вы запустите службу, затем привяжите к ней клиента, а затем попытайтесь ее остановить, служба не будет остановлена ​​(уничтожена), прежде чем все клиенты будут отключаться. Второй абзац не противоречит, он уточняет это утверждение.

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

Это означает: запущенная и связанная служба запускается, даже если клиенты не привязаны к ней, пока она не будет явно остановлена. Разумеется, формулировка, возможно, будет немного понятнее. Однако диаграмма жизненного цикла, приведенная в документации, показывает это (и я уверен, что я уже наблюдал это в "реальной жизни", хотя в настоящее время у меня нет прямого примера):

Lifecycle for started and bound services

Ответ 2

Согласитесь, что документация может быть более четкой. Они пытаются сказать:

  • Если вы вызываете startService(), служба будет продолжать работать до тех пор, пока вы не вызовеете stopSerivce() (или stopSelf() из службы)
  • Если вы вызываете bindService(), служба будет продолжать работать до тех пор, пока вы не вызовете unbindService()
  • Поэтому, если вы вызываете как startService(), так и bindService(), служба будет продолжать работать до тех пор, пока вы не вызовете stopService и unbindService(). Ни один из них не остановит службу.

Создал очень простой Activity and Service и выполнил следующие последовательности: start/stop/bind/unbind. Я заметил, что звонки дали следующие результаты.

связывают-отвязать

bindService() caused:
    onCreate()
    onBind()
unbindService() caused:
    onUnbind()
    onDestroy()

старт-связывания-отвязать-стоп

startService() caused:
    onCreate()
    onStartCommand()
bindService() caused:
    onBind()
unbindService() caused:
    onUnbind()
stopService() caused:
    onDestroy()

старт-стоп связывают-отвязать

startService() caused:
    onCreate()
    onStartCommand()
bindService() caused:
    onBind()
stopService() caused:
    -- nothing
unbindService() caused:
    onUnbind()
    onDestroy()

связывают-старт-стоп-отвязать

bindService() caused:
    onCreate()
    onBind()
startService() caused:
    onStartCommand()
stopService() caused:
    -- nothing -- still running
unbindService() caused:
    onUnbind()
    onDestroy()

связывают-старт-стоп UNBIND-

bindService() caused:
    onCreate()
    onBind()
startService() caused:
    onStartCommand()
unbindService() caused:
    onUnbind()
stopService() caused:
    onDestroy()

Как вы можете видеть, в каждом случае, когда вызывались оба вызова bind и start, служба продолжала работать до тех пор, пока не были вызваны оба unbind и stop. Последовательность unbind/stop не важна.

Вот пример кода, который был вызван из отдельных кнопок в моем простом тестовом приложении:

public void onBindBtnClick(View view) {
    Intent intent = new Intent(MainActivity.this, ExampleService.class);
    bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
}

public void onUnbindBtnClick(View view) {
    if (serviceIsBound) {
        unbindService(serviceConnection);
        serviceIsBound = false;
    }
}

public void onStartBtnClick(View view) {
    Intent intent = new Intent(MainActivity.this, ExampleService.class);
    startService(intent);
}

public void onStopBtnClick(View view) {
    Intent intent = new Intent(MainActivity.this, ExampleService.class);
    exampleService.stopService(intent);
}

Ответ 3

Да, это работает. Я хочу заполнить пример кода:

Мне нужно было создать приложение со службой, запущенной с помощью действия, действие должно вызвать некоторые методы в службе, служба должна работать в фоновом режиме, даже если действие было убито, а когда действие перезапускается, 't перезапустить службу, если она запущена. Надеюсь, это поможет вам, вы можете увидеть, как это работает с журналом. Итак, это код:

 public class MyActivity extends Activity{

    private MyService myService;
    private boolean mIsBound = false;

    private ServiceConnection mConnection = new ServiceConnection() {

        public void onServiceConnected(ComponentName className, IBinder binder) {
            MyService.MyBinder b = (MyService.MyBinder) binder;
            myService = b.getService();
            mIsBound = true
            //Do something
            // Here you can call : myService.aFonctionInMyService();

        }
        public void onServiceDisconnected(ComponentName className) {
            // Do something
            mIsBound = false;
        }
    }



    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);

        //Checked if my service is running
        if (!isMyServiceRunning()) {
            //if not, I start it.
            startService(new Intent(this,MyService.class));
        }
    }

    private boolean isMyServiceRunning() {
        ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
        for (RunningServiceInfo service : manager
                .getRunningServices(Integer.MAX_VALUE)) {
            if (MyService.class.getName().equals(
                    service.service.getClassName())) {
                return true;
            }
        }
        return false;
    }

    @Override
    protected void onResume() {
        // TODO Auto-generated method stub
        super.onResume();
        doBindService();
    }




    //Connection to the Service
    private void doBindService() {
        bindService(new Intent(this,MyService.class), mConnection,
                Context.BIND_AUTO_CREATE);
    }

    // Disconnection from the service
    private void doUnbindService() {
        if (mIsBound) {
            // Detach our existing connection.
            unbindService(mConnection);
        }
    }

    @Override
    protected void onPause() {
        // TODO Auto-generated method stub
        doUnbindService();
        super.onPause();
    }

}


public class MyService extends Service{


    public static String Tag = "MyService";
    private final IBinder mBinder = new MyBinder();

    @Override
    public void onCreate() {
        // TODO Auto-generated method stub      
        super.onCreate();
        Log.d(Tag, "onCreate()");

    }

    public class MyBinder extends Binder {
        public LocationService getService() {
            return LocationService.this;
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        Log.d(Tag, "onBind()");
        return mBinder;
    }

    @Override
    public boolean onUnbind(Intent intent) {
        // TODO Auto-generated method stub
        Log.d(Tag, "onUnBind()");
        return super.onUnbind(intent);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // TODO Auto-generated method stub
        Log.d(Tag,"onStartCommand()");

        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        // TODO Auto-generated method stub

        Log.d(Tag, "onDestroy");
        super.onDestroy();
    }

    public void aFonctionInMyService(){
        //Do Something
    }

}