Android studio service binding

Полный список

— обмен данными в биндинге

Подключаться к сервису мы теперь умеем. В этом уроке попробуем обменяться с ним данными.

В сервисе метод onBind возвращает объект, наследующий интерфейс IBinder. Проще всего использовать для этого объект Binder и расширить его необходимыми нам методами. Т.е. создаем свой класс MyBinder с предком Binder и рисуем в нем свои методы.

При биндинге, в методе onServiceConnected мы получаем объект Binder. Мы можем привести его к типу MyBinder (из сервиса) и вызывать его методы, а реализация будет срабатывать в сервисе, где мы описывали этот класс.

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

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

Project name: P0981_ServiceBindingLocal
Build Target: Android 2.3.3
Application name: ServiceBindingLocal
Package name: ru.startandroid.develop.p0981servicebindinglocal
Create Activity: MainActivity

Добавим в strings.xml строки:

Кнопки для запуска сервиса, повышения интервала и понижения интервала.

Создаем сервис MyService.java:

Здесь мы используем таймер – Timer. Он позволяет повторять какое-либо действие через заданный промежуток времени. Кратко распишу принцип действия. TimerTask – это задача, которую Timer будет периодически выполнять. В методе run – кодим действия этой задачи. И далее для объекта Timer вызываем метод schedule, в который передаем задачу TimerTask, время через которое начнется выполнение, и период повтора. Чтобы отменить выполнение задачи, необходимо вызвать метод cancel для TimerTask. Отмененную задачу нельзя больше запланировать, и если снова надо ее включить – необходимо создать новый экземпляр TimerTask и скормить его таймеру.

Итак, в методе onCreate мы создаем таймер и выполняем метод schedule, в котором стартует задача.

Метод schedule проверяет, что задача уже создана и отменяет ее. Далее планирует новую, с отложенным на 1000 мс запуском и периодом = interval. Т.е. можно сказать, что этот метод перезапускает задачу с использованием текущего интервала повтора (interval), а если задача еще не создана, то создает ее. Сама задача просто выводит в лог текст run. Если interval = 0, то ничего не делаем.

Метод upInterval получает на вход значение, увеличивает interval на это значение и перезапускает задачу. Соответственно задача после этого будет повторяться реже.

Метод downInterval получает на вход значение, уменьшает interval на это значение (но так, чтоб не меньше 0) и перезапускает задачу. Соответственно задача после этого будет повторяться чаще.

onBind возвращает binder. Это объект класса MyBinder.

MyBinder расширяет стандартный Binder, мы добавляем в него один метод getService. Этот метод возвращает наш сервис MyService.

Т.е. в подключаемом Activity, в методе onServiceConnected мы получим объект, который идет на выход метода onBind. Далее преобразуем его к типу MyBinder, вызовем getService и вуаля — у нас в Activity будет ссылка на объект-сервис MyService.

В onCreate создаем Intent для доступа к сервису и ServiceConnection. В методе onServiceConnected мы берем binder, преобразуем его к MyService.MyBinder, вызываем метод getService и получаем наш сервис MyService. Теперь мы можем выполнять методы сервиса. Нас интересуют методы увеличения и понижения интервала.

Читайте также:  Неподдерживаемый метод шифрования андроид что делать

В методах onStart и onStop мы соответственно подключаемся к сервису и отключаемся.

В onClickStart запускаем сервис.

В onClickUp и onClickDown проверяем, что соединение с сервисом есть, и вызываем соответствующие методы сервиса для увеличения или понижения интервала. В качестве дельты изменения интервала передаем 500. В ответ эти методы передают нам новое значение интервала, и мы выводим его в TextView.

Все сохраним и запускаем.

Жмем Start – запускаем сервис. В логах:

MyService onCreate
MyService onBind
MainActivity onServiceConnected

Создается сервис, и мы к нему подключаемся. Биндинг был ранее вызван в onStart и, когда сервис стартанул, мы автоматически подключились. В прошлом уроке мы разбирали такую ситуацию, когда биндинг идет к незапущенному пока сервису.

Далее с интервалом в одну секунду в лог падает текст run.

Попробуем увеличить интервал. Жмем Up.

На экране появилось текущее значение интервала. И по времени записей в логах видим, что именно с этим интервалом срабатывает задача (вывод текста run в лог) .

Далее можно нажимать Up и Down и наблюдать, как меняется интервал выполнения задачи. Таким образом, мы из Activity подключились к сервису и управляем его работой.

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

На следующем уроке:

— шлем уведомление из сервиса

Присоединяйтесь к нам в Telegram:

— в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.

— в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Kotlin, RxJava, Dagger, Тестирование

— ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня

— новый чат Performance для обсуждения проблем производительности и для ваших пожеланий по содержанию курса по этой теме

Источник

Полный список

— используем биндинг для подключения к сервису

В прошлых уроках мы общались с сервисом асинхронно. Т.е. мы отправляли запрос через startService, а ответ нам приходил когда-нибудь потом посредством PendingIntent или BroadcastReceiver.

Но есть и синхронный способ взаимодействия с сервисом. Он достигается с помощью биндинга (binding, я также буду использовать слово «подключение»). Мы подключаемся к сервису и можем взаимодействовать с ним путем обычного вызова методов с передачей данных и получением результатов. В этом уроке передавать данные не будем. Пока что разберемся, как подключаться и отключаться.

Как вы помните, для запуска и остановки сервиса мы использовали методы startService и stopService. Для биндинга используются методы bindService и unbindService.

Создадим два Application. В одном будет приложение, в другом сервис.

Создадим первый проект:

Project name: P0971_ServiceBindClient
Build Target: Android 2.3.3
Application name: ServiceBindClient
Package name: ru.startandroid.develop.p0971servicebindclient
Create Activity: MainActivity

Добавим в strings.xml строки:

4 кнопки: для запуска, остановки и биндинга сервиса

Читайте также:  Дроид шип для андроид

В onCreate мы создаем Intent, который позволит нам добраться до сервиса.

Объект ServiceConnection позволит нам определить, когда мы подключились к сервису и когда связь с сервисом потеряна (если сервис был убит системой при нехватке памяти). При подключении к сервису сработает метод onServiceConnected. На вход он получает имя компонента-сервиса и объект Binder для взаимодействия с сервисом. В этом уроке мы этим Binder пока не пользуемся. При потере связи сработает метод onServiceDisconnected.

Переменную bound мы используем для того, чтобы знать – подключены мы в данный момент к сервису или нет. Соответственно при подключении мы переводим ее в true, а при потере связи в false.

Далее идут обработчики кнопок. В onClickStart мы стартуем сервис, в onClickStop – останавливаем.

В onClickBind – соединяемся с сервисом, используя метод bindService. На вход передаем Intent, ServiceConnection и флаг BIND_AUTO_CREATE, означающий, что, если сервис, к которому мы пытаемся подключиться, не работает, то он будет запущен.

В onClickUnBind с помощью bound проверяем, что соединение уже установлено. Далее отсоединяемся методом unbindService, на вход передавая ему ServiceConnection. И в bound пишем false, т.к. мы сами разорвали соединение. Метод onServiceDisconnected не сработает при явном отключении.

Создадим второй проект, без Activity:

Project name: P0972_ServiceBindServer
Build Target: Android 2.3.3
Application name: ServiceBindServer
Package name: ru.startandroid.develop.p0972servicebindserver

Создаем сервис MyService.java:

Методы onCreate и onDestroy нам знакомы – они вызываются при создании и уничтожении сервиса. А onBind, onRebind и onUnbind используются при биндинге и мы далее будем смотреть как именно. Метод onStartCommand не используем.

В методе onBind возвращаем пока объект-заглушку Binder. В этом уроке он не будет использован.

Прописываем сервис в манифесте и настраиваем для него IntentFilter с Action = ru.startandroid.develop.p0972servicebindserver.MyService.

Все сохраняем, инсталлим сервис и запускаем приложение.

На самом экране ничего происходить не будет. Все внимание на логи.

Попробуем подключиться к неработающему сервису. Жмем Bind. В логах:

MyService onCreate
MyService onBind
MainActivity onServiceConnected

Сервис создался и сработал его метод onBind. Также сработал метод onServiceConnected в ServiceConnection, т.е. Activity теперь знает, что подключение к сервису установлено.

Попробуем отключиться. Жмем Unbind.

MyService onUnbind
MyService onDestroy

Сработал метод Unbind в сервисе и сервис закрылся. Т.е. если мы биндингом запустили сервис, он будет жить, пока живет соединение. Как только мы отключаемся, сервис останавливается. onServiceDisconnected не сработал, т.к. мы сами отключились.

Теперь попробуем соединиться с сервисом и убить его. Посмотрим, что станет с соединением. Жмем Bind.

MyService onCreate
MyService onBind
MainActivity onServiceConnected

Теперь в процессах убиваем процесс сервиса

Сработал метод onServiceDisconnected объекта ServiceConnection. Тем самым Activity уведомлено, что соединение разорвано.

Теперь немного подождем (у меня это заняло 5 секунд) и в логах появляются строки:

MyService onCreate
MyService onBind
MainActivity onServiceConnected

Сервис запустился и соединение восстановилось. Очень удобно.

Жмем Unbind и отключаемся.

Попробуем снова подключиться к незапущенному сервису, но уже без флага BIND_AUTO_CREATE. Перепишем onClickBind в MainActivity.java:

Вместо флага BIND_AUTO_CREATE мы написали 0.

Сохраняем, запускаем. Жмем Bind. В логах ничего. Мы убрали флаг, сервис сам не создается при подключении.

Читайте также:  Убрать рекламу с андроида без root

Давайте запустим его методом startService. Жмем Start. В логах:

MyService onCreate
MyService onBind
MainActivity onServiceConnected

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

Отключились от сервиса. Но сервис продолжает жить, потому что он был запущен не биндингом, а методом startService. А там уже свои правила закрытия сервиса. Это мы проходили в прошлых уроках.

Сервис завершил работу.

Попробуем запустить сервис методом startService и, пока он работает, несколько раз подключимся и отключимся. Жмем Start.

Подключаемся и отключаемся, т.е. жмем Bind

MyService onBind
MainActivity onServiceConnected

Сработали методы onBind и onUnbind в сервисе, и onServiceConnected в ServiceConnection.

Еще раз подключаемся и отключаемся — жмем Bind, а затем Unbind

При повторном подключении к сервису методы onBind и onUnbind не сработали. Только onServiceConnected.

И далее, сколько бы мы не подключались, так и будет.

Остановим сервис – нажмем Stop.

Это поведение можно скорректировать. Для этого необходимо возвращать true в методе onUnbind. Сейчас мы там вызываем метод супер-класса, а он возвращает false.

Перепишем метод Unbind в MyService.java:

Сохраним и инсталлим сервис. Жмем Start, а затем жмем поочередно Bind и Unbind, т.е. подключаемся и отключаемся. Смотрим логи:

MyService onCreate
MyService onBind
MainActivity onServiceConnected
MyService onUnbind

Сервис создан, подключились и отключились. Продолжаем подключаться и отключаться.

MyService onRebind
MainActivity onServiceConnected
MyService onUnbind
MyService onRebind
MainActivity onServiceConnected
MyService onUnbind

Последующие подключения и отключения сопровождаются вызовами методов onRebind и onUnbind. Таким образом, у нас есть возможность обработать в сервисе каждое повторное подключение/отключение.

Вот примерно такой Lifecycle имеет биндинг сервиса. Разумеется, я рассмотрел не все возможные комбинации запуска методов startService, stopService, bindService и unbindService. Оставляю это вам, если есть интерес. Я рассмотрел только типичные случаи.

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

Насколько я понял по хелпу, не рекомендуется оставлять незавершенные подключения к сервисам по окончании работы приложения. В хелповских примерах подключение к сервису производится в методе onStart, а отключение — в onStop. Но, разумеется, если вам надо, чтобы подключение оставалось при временном уходе Activity в background, то используйте onCreate и onDestroy. Также есть четкая рекомендация от гугла — не использовать для этих целей onResume и onPause.

На следующем уроке:

— обмен данными в биндинге

Присоединяйтесь к нам в Telegram:

— в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.

— в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Kotlin, RxJava, Dagger, Тестирование

— ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня

— новый чат Performance для обсуждения проблем производительности и для ваших пожеланий по содержанию курса по этой теме

Источник

Оцените статью