Привязать сервис к активности в Android


91

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

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

Ответы:


155

«Если вы запустите службу Android с startService(..)этой службой, она будет продолжать работать до тех пор, пока вы явно не вызовете ее stopService(..). Есть две причины, по которым служба может запускаться системой. Если кто-то позвонит, Context.startService()система получит службу (создав ее и вызовет onCreate()метод, если необходимо), а затем вызовите его onStartCommand(Intent, int, int)метод с аргументами, предоставленными клиентом. Служба на этом этапе продолжит работу до тех пор, пока не будет вызвана Context.stopService()или stopSelf(). Обратите внимание, что несколько вызовов, которые Context.startService()не следует вкладывать (хотя они приводят к нескольким соответствующим вызовам onStartCommand()), поэтому нет независимо от того, сколько раз он запускался, служба будет остановлена ​​один раз Context.stopService()или метод, гарантирующий, что служба не будет остановлена, пока запущенные намерения не будут обработаны. stopSelf() вызвана ; однако службы могут использовать своиstopSelf(int)

Клиенты также могут использовать Context.bindService()для получения постоянного подключения к службе. Это также создает службу, если она еще не запущена (вызывается onCreate()при этом), но не вызывает onStartCommand(). Клиент получит IBinderобъект, который служба возвращает из своего onBind(Intent)метода, позволяя клиенту затем делать обратные вызовы службе. Служба будет работать до тех пор, пока установлено соединение (независимо от того, сохраняет ли клиент ссылку на Службу IBinder). Обычно IBinderвозвращается сложный интерфейс, написанный на AIDL.

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


1
небольшая путаница: правда ли, что если активность будет уничтожена, служба также будет уничтожена? Или эта служба не уничтожается только в том случае, если я использую свой собственный AIDL? Я спрашиваю, потому что, когда я использую startService (особенно на IntentService), служба останавливается, когда ее работа завершена, а не когда действие прекращается. Так правда ли, что если действие умирает, то и связанная (исключительно) служба также умирает?
Katedral Pillon

1
если вы используете простой сервер, вызывая startService, тогда служба не остановится, пока вы не вызовете stopSelf () или stopService (). А затем, если вы используете bindService, тогда да, служба умрет, если все подключенные / привязанные компоненты уничтожены.
Asif

1
@UnKnown Если служба запускается с помощью startService (), то независимо от того, привязываете ли вы ее или отменяете привязку, она будет продолжать работать и может быть уничтожена только вызовом stopService () или stopSelf (). Таким образом, даже если действие, которое было связано со службой, будет уничтожено, служба не будет уничтожена.
CopsOnRoad 04

Не могли бы вы помочь мне с этим вопросом? Stackoverflow.com/questions/51508046/…
Rajesh K

25

Прежде всего, две вещи, которые нам нужно понять

Клиент

  • он делает запрос на конкретный сервер

    bindService(new 
        Intent("com.android.vending.billing.InAppBillingService.BIND"),
            mServiceConn, Context.BIND_AUTO_CREATE);`
    

вот mServiceConnэкземпляр ServiceConnectionкласса (встроенный), это на самом деле интерфейс, который нам нужно реализовать с помощью двух (1-й для подключения к сети и 2-го метода для подключения к сети) для мониторинга состояния сетевого подключения.

Сервер

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

Теперь на стороне клиента, как получить доступ ко всем методам сервера?

  • сервер отправляет ответ с помощью объекта IBind. поэтому объект IBind - это наш обработчик, который обращается ко всем методам обслуживания с помощью оператора (.).

    MyService myService;
    public ServiceConnection myConnection = new ServiceConnection() {
        public void onServiceConnected(ComponentName className, IBinder binder) {
            Log.d("ServiceConnection","connected");
            myService = binder;
        }
        //binder comes from server to communicate with method's of 
    
        public void onServiceDisconnected(ComponentName className) {
            Log.d("ServiceConnection","disconnected");
            myService = null;
        }
    }
    

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

myservice.serviceMethod();

вот myServiceобъект и serviceMethodeметод в обслуживании. Таким образом устанавливается связь между клиентом и сервером.



5

Существует метод unbindService , который примет ServiceConnection, который вы создадите при вызове bindService. Это позволит вам отключиться от службы, не отключая ее.

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

Удачи!


-1

Это предвзятый ответ, но я написал библиотеку, которая может упростить использование служб Android, если они работают локально в том же процессе, что и приложение: https://github.com/germnix/acacia

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

@Service(ServiceImpl.class)
public interface MyService {
    void doProcessing(Foo aComplexParam);
}

public class ServiceImpl implements MyService {
    // your implementation
}

MyService service = Acacia.createService(context, MyService.class);
service.doProcessing(foo);

<application
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme">
    ...
    <service android:name="com.gmr.acacia.AcaciaService"/>
    ...
</application>

Вы можете получить экземпляр связанной службы android.app.Service для скрытия / отображения постоянных уведомлений, использовать свой собственный android.app.Service и вручную обрабатывать потоки, если хотите.


-5

Если пользователь отступит, onDestroy()метод будет вызван. Этот метод заключается в остановке любой службы, используемой в приложении. Поэтому, если вы хотите продолжить службу, даже если пользователь откажется от приложения, просто удалите onDestroy(). Надеюсь на эту помощь.


Вам придется переопределить функцию и удалить вызов по умолчанию суперкласса onDestroy (), если ваша IDE автоматически создает его. но зачем вам это делать?
Riptyde4
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.