Форум программистов, компьютерный форум CyberForum.ru

Программирование Android

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 23, средняя оценка - 4.61
obrazer
69 / 69 / 1
Регистрация: 04.09.2012
Сообщений: 170
#1

Использование Сервисов - Android

07.02.2013, 00:15. Просмотров 2846. Ответов 28
Метки нет (Все метки)

Итак задача:
1. Сервис работает с неким сервером в сети и постоянно запрашивает у того некоторые данные.
2. Данные есть критичные и некритичные
3. Если запущено приложение, то данные отображаются в нем (все сразу или частично, пока не существенно)
4. Если приложение свернуто или вообще убито системой или девайс спит и т.д. и тп., то если Сервис получил критичные данные, должен разбудить девайс, добавить Уведомление в состояние, поднять приложение, ну и приложение получает данные для отображения.

Собственно мысли:
1. Сервис у меня уже работает и данные с сервера тягает.
2. Сделал BroadcastReceiver, Сервис туда отправляет Intent с содержанием полученных данных
3. BroadcastReciever внутри себя определяет критичность данных и при необходимости выводит Уведомление и...

Вот тут вопрос. Как данные отобразить в приложении?

Т.е. по сути объект BroadcastReceiver является частью приложения.
1. Могу ли я быть уверен, что если приложение было в Паузе или вообще в Стопе, то после вызова BroadcastReciever оно уже снова запущено с последнего Активити?
2. BroadcastReceiver один, а Активити в приложении может быть много. Каким образом мне запоминать значения всех полученных данных, чтобы при перемещении между Активити можно было потом эти данные отобразить? Где их лучше сохранить?
3. Аналогично с Уведомлениями. Появилось Уведомление с данными, а приложение-то свернуто. Тыкаем в Уведомление, приложение разворачивается, а как передать данные в приложение как будто оно было развернуто?

Ну как-то так

Пробежала мысль не париться и сделать чтобы Сервис сохранял все что получает в БД и просто вызывает BroadcastReceiver. А приложение при активации просто читает из БД актуальные данные. Т.е. Оно читает данные при активации при получении BroadcastReceiver, при развертывании через Уведомление.

Однако такой способ меня как-то смущает, ибо связь с сервером будет с периодичностью 5-10 секунд, и получается постоянная работа с БД. Насколько это ресурсоемкая операция? Вообще нормальый ли будет такой подход.

PS: Возможно слегка сумбурно объяснил, если непонятно - спрашивайте, буду корректировать мысль.
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
flashok
86 / 88 / 1
Регистрация: 14.02.2009
Сообщений: 293
07.02.2013, 12:14     Использование Сервисов #2
возможно эта статья вас наталкнет на какие мысли
по работе с базой
http://www.enterra.ru/blog/android_issues_with_sqlite/

p.s. интересно что вы решите в итоге
obrazer
69 / 69 / 1
Регистрация: 04.09.2012
Сообщений: 170
07.02.2013, 13:59  [ТС]     Использование Сервисов #3
flashok, спасибо, довольно таки интересная статья. И, возможно, поможет в дальнейшем.
Однако сейчас меня больше интересует, какие в принципе решения могут быть.

Абстрагируясь от архитектуры андроида - имеется два куска кода, первый отвечает за получение данных, воторой за отображение данных. Прямой связи между ними нет. Так вот как средствами Андроид АПИ передавать данные между этими кусками кода. Особенно учитывая, что один из кусков кода может "спать" или вообще отсутствовать, но при "просыпании" или запуске должен отобразить актуальные данные.

Один из вариантов сохранять полученные данные в БД. Какие еще идеи?

Может как-то сохранять актуальное состояние данных в Сервисе, а Приложение либо получает Броадкаст, либо когда "просыпается" каким либо образом запрашивает информацию у Сервиса?
YuraAAA
1565 / 1307 / 269
Регистрация: 25.10.2009
Сообщений: 3,424
Записей в блоге: 2
07.02.2013, 15:17     Использование Сервисов #4
Передачу данных между активити и сервисом можно сделать с помощью паттерна Observer-Observable.

В сервис запихните внутренний класс, который будет extends Observable. Активити будет реализовывать интерфейс Observer.
dubok79
323 / 121 / 11
Регистрация: 01.11.2012
Сообщений: 586
07.02.2013, 18:21     Использование Сервисов #5
По сервисам надо прочитать уроки с 92 по 100 вот на этом ресурсе как раз там все это разбирается. Все очень понятно написано.
obrazer
69 / 69 / 1
Регистрация: 04.09.2012
Сообщений: 170
07.02.2013, 22:19  [ТС]     Использование Сервисов #6
Цитата Сообщение от dubok79 Посмотреть сообщение
Все очень понятно написано.
Спасибо. Этот ресурс я уже изучал. немного сразу не догнал некоторые моменты, сейчас вчитался подробнее

Вопрос остается открытым по поводу явного наличия Активити и Сервиса в одном процессе. Как в написано в этом же источнике - "Как вы понимаете, это сработает только, если сервис и приложение выполняются в одном процессе"

Т.е. учитывая жизненный цикл приложения могу предположить, что:
1. Приложение запускается, отображается некоторое Активити, которое запускает Сервис.
2. Сервис работает и может через БроадкастРесивер или через Биндинг отдавать данные или получать доступ к методом сервиса.
3. Устройство заснуло. Активити перешло в Паузу Или вообще в Стоп, а в последствии может даже было "убито" системой.
4. Сервис по-прежнему работает, и в случае получения Критичного сообщения создает уведомление и должен где-то сохранить данные, вероятно в каком-либо своем поле.
5. Пользователь получив уведомление будит девайс и тыкает в уведомление. Уведомление открывает соответствующее Активити и вроде как Активити должно опять иметь возможность либо через БроадкастРесивер или посредством Биндинга получить доступ к Сервису. Вот тут вопрос - это Активити будет создано в том же процессе, что и Сервис?

Если восстановленное Активити создается в том же процессе что и сервис, то самым рациональным вижу просто прибиндиться еще раз и получить критичное сообщение непосредственно с Сервиса.

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

По уведомлению просто открывается Активити, которое прибиндивается к Сервису и получает полный набор данных и критичных сообщений.

Подтвердите/опровергните/уточните мое понимание процесса.

Добавлено через 9 минут
Цитата Сообщение от YuraAAA Посмотреть сообщение
с помощью паттерна Observer-Observable.
Это предполагает оперативное информирование Активити об изменении в Сервисе. Но Активити может быть в Паузе, Стопе или вообще убито системой. И после восстановления Активити уже не узнает, что в Observable происходили какие либо изменения. Да и после восстановления придется снова добавляться в Observable, который является частью Сервиса, а для этого надо сперва подключиться к Сервису

Хотя отображать Критичные сообщения в случае когда Активити активно это может помочь.
dubok79
323 / 121 / 11
Регистрация: 01.11.2012
Сообщений: 586
08.02.2013, 06:04     Использование Сервисов #7
А нельзя ли в таком случае сохранять эти уведомления в каком либо файле, а активити при следующем запуске их прочитает, ну и, например, удалит. Я бы такой подход использовал.
obrazer
69 / 69 / 1
Регистрация: 04.09.2012
Сообщений: 170
08.02.2013, 08:43  [ТС]     Использование Сервисов #8
Ну в таком случае удобнее все же использовать БД. Все же структурированнее будут данные.

А что смущает в приведенном мною последнем варианте?
dubok79
323 / 121 / 11
Регистрация: 01.11.2012
Сообщений: 586
08.02.2013, 09:19     Использование Сервисов #9
Цитата Сообщение от obrazer Посмотреть сообщение
Ну в таком случае удобнее все же использовать БД. Все же структурированнее будут данные.
А что смущает в приведенном мною последнем варианте?
если вопрос был ко мне:
1. БД это такая хитроопая штука в андроиде, что надо иметь рядом с собой стакан иначе понять невозможно, так же как и русскую душу.
2. Ничего не смущает, просто написал свое видение. Стараюсь использовать то, что проще для меня...
obrazer
69 / 69 / 1
Регистрация: 04.09.2012
Сообщений: 170
11.02.2013, 14:49  [ТС]     Использование Сервисов #10
Цитата Сообщение от flashok Посмотреть сообщение
p.s. интересно что вы решите в итоге
Ну значится идея такова:
1. Делаем Сервис. Внутри сервиса крутится поток, который коннектится через интернет к серверу и получает различную информацию.
2. В самом же Сервисе имеется Объект Данных, хранящий все необходимые данные, в том числе и список критичных сообщений.
3. После получения данных и обновления Объекта Данных, Сервис вызывает BroadcastReсiever. Который является частью Activity.
4. Activity в ответ выполняет Bind-инг к Сервису и через него получает доступ к методам Сервиса. Сервис отдает необходимые данные, в том числе критичные сообщения и Activity их отображает (в том числе обновляет некритичные данные, если требуется). Заодно Сервис сбрасывает критичные сообщения, дабы более они не отображались
5. Одновременно, в случае наличия критичного сообщения, BroadcastReciever создает Notification, который отображается в строке состояния.
6. Если пользователь тыкает в Уведомление, то аналогично вызывается Activity, которое в свою очередь.. см.п.4
7. Если нужно передать что-то из Activity в Сервис, то делаем это через Bind-инг, либо вызывая startService с соответствующим Intent-ом. Пока не решил как правильнее и удобнее. Вероятно через Intent, потому как это и может стать самым первым запуском Сервиса и, по-сути, быть стандартным обращением и можно не заботится о наличии Сервиса при желании ему чего-то отправить.

Т.о. решаются задачи:
Сервис крутится самостоятельно и не заботится об отображении. Он хранит данные и генерирует Intent-ы к BroadcastReciever-у. Причем Activity может и не существовать вовсе - данные будут получаться и сохраняться в Сервисе до момента их получения кем либо через Bind-инг.
А отображением занимается Activity, абсолютно не заботясь, откуда данные пришли, главное их забрать у Сервиса через Bind-инг (предполагаем, что сервис неубиваем).
Момент передачи данных - при старте/рестарте Activity (если не было запущено или было в стопе/паузе или система прибила Activity в случае нехватки ресурса или вызвалась по Уведомлению), при вызове BroadcastReciever-а (оперативное уведомление Activity).

Если мои умозаключения где-то расходятся с реальностью - комментируйте. Да и просто комментируйте
V0v1k
1158 / 982 / 1
Регистрация: 28.06.2012
Сообщений: 3,462
11.02.2013, 15:49     Использование Сервисов #11
Цитата Сообщение от obrazer Посмотреть сообщение
BroadcastReсiever. Который является частью Activity.
Цитата Сообщение от obrazer Посмотреть сообщение
Причем Activity может и не существовать вовсе
значит не будет и ресивера. или я что-то не так понял?
obrazer
69 / 69 / 1
Регистрация: 04.09.2012
Сообщений: 170
11.02.2013, 16:02  [ТС]     Использование Сервисов #12
Цитата Сообщение от V0v1k Посмотреть сообщение
значит не будет и ресивера. или я что-то не так понял?
Ресивер регистрируется в ОС. А значит должен вызываться и без наличия Активити. Хотя это опять же мои догадки, явного указание на это я нигде не нашел.
Создается ли Активити вместе с ресивером или, возможно, создается новый объект ресивера по данным из регистрации - я не знаю.

Однако в данном случае даже если ресивер не сработает, то и не критично, потому как ресивер нужен что бы указывать Активити, что необходимо обновить данные. Если нет Активити, то и обновлять нечего. В этой ситуации важно не потерять критичные сообщения (а они сохраняются непосредственно в свойствах Сервиса) и выдать Уведомление пользователю (что сервис может сделать и самостоятельно), при нажатии на которое запускается (возобновляется) Активити и оно в onRestart(onResume) в любом случае делает Bind-инг и получает данные с Сервиса.

Вроде бы все сходится. Или я чего-то опять упустил?
V0v1k
1158 / 982 / 1
Регистрация: 28.06.2012
Сообщений: 3,462
11.02.2013, 16:18     Использование Сервисов #13
Цитата Сообщение от obrazer Посмотреть сообщение
Который является частью Activity.
если под этим имеется ввиду что ресивер будет создан в активити, то перед закрытием активити вы должны отрегистрировать ресивер, если память не подводит. поэтому я и написал.

ну а если сам сервис нотификейшини делать будет, то все сходится, просто вы написали что ресивер их делает.
obrazer
69 / 69 / 1
Регистрация: 04.09.2012
Сообщений: 170
11.02.2013, 16:25  [ТС]     Использование Сервисов #14
Цитата Сообщение от V0v1k Посмотреть сообщение
ресивер будет создан в активити, то перед закрытием активити вы должны отрегистрировать ресивер
А что будет, если не отрегистрирую? Да и еще имеется регистрация в Манифесте - она для чего тогда? Не для вызова ли вне созданного Активити?
Цитата Сообщение от V0v1k Посмотреть сообщение
ну а если сам сервис нотификейшини делать будет, то все сходится, просто вы написали что ресивер их делает.
Действительно, так и написал - вот и нашелся косячек Да, Нотификейшн должен создавать Сервис, независимо от Активити. Активити или получать Ресивер или создаваться/перезапускаться по Нотификейшену.
V0v1k
1158 / 982 / 1
Регистрация: 28.06.2012
Сообщений: 3,462
11.02.2013, 16:31     Использование Сервисов #15
Цитата Сообщение от obrazer Посмотреть сообщение
А что будет, если не отрегистрирую? Да и еще имеется регистрация в Манифесте - она для чего тогда? Не для вызова ли вне созданного Активити?
давно ресиверы не писал, так-что могу ошибаться.
ресивер можно создать независимый и зарегистрировать в манифесте, а можно создать в самой активити и там же нужно регистрировать/отрегистрировать, если закрыть активити с неотрегистрированным ресивером, то будет екзепшен.

повторяю что могу ошибаться, давно ресиверы не делал.
obrazer
69 / 69 / 1
Регистрация: 04.09.2012
Сообщений: 170
12.02.2013, 10:07  [ТС]     Использование Сервисов #16
Опробовал. Появились новые вопросы.
1. Когда устройство засыпает - сервис останавливается. Т.е. у меня создан сервис, в котором создается отдельный поток, который просто считает секунды. В итоге он все считает пока не заснет. Минут через 20 будишь девайс, а он всего пару минут насчитал. Т.е. пока не спит - считает, как девайс заснул, так и сервис встал.
Видел пример с АлярмМенеджером, но тот в свою очередь работает в итоге самостоятельно. А надо чтобы сервис все отрабатывал. Как сделать чтоб Сервис постоянно работал (ну например приложение Майл.ру постоянно почту мониторит)?
2. Сервис прибивается системой. Я вообще предполагал, что сервис на то и сервис, что бы работать в фоне. А тут оставил на ночь - утром все запустилось с начала, причем специально делал эксперимент - оставил открытым именно мое приложение (там уже было насчитано несколько минут работы), устройство заснуло, утром разбудил, открылось мое же приложение, но "с нуля".

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

Как-то делал запуск отдельного потока непосредственно из активити. Так результат был аналогичный. Так же при неактивной активити поток работал самостоятельно, при засыпании устройства поток останавливался, система могла прибить активити вместе с потоком. А нафига тогда сервисы?

Как так? Что не так? Как быть? Чего я недопонял?

PS: Взаимодействие Сервиса, Активити, Нотификейшенов и прочее, выше мною описанное, работает нормально
V0v1k
1158 / 982 / 1
Регистрация: 28.06.2012
Сообщений: 3,462
12.02.2013, 13:02     Использование Сервисов #17
в активити есть методы для сохранения и восстановления состояния (onSaveInstanceState/onRestoreInstanceState).
время нужно рассчитывать вычитанием текущего времени от времени старта, а не считать каждую секунду.
obrazer
69 / 69 / 1
Регистрация: 04.09.2012
Сообщений: 170
12.02.2013, 13:14  [ТС]     Использование Сервисов #18
Цитата Сообщение от V0v1k Посмотреть сообщение
в активити есть методы для сохранения и восстановления состояния (onSaveInstanceState/onRestoreInstanceState).
А при чем тут сохранение состояния если (цитирую себя же) - "В итоге все для чего мне нужны были сервисы не работает. А именно - в фоне не работает, при неактивности прибивается системой..."

Цитата Сообщение от V0v1k Посмотреть сообщение
время нужно рассчитывать вычитанием текущего времени от времени старта, а не считать каждую секунду.
Время я считал просто для проверки активности сервиса. И полученное количество тиков говорит мне о том, что... см. предыдущий мой пост.
V0v1k
1158 / 982 / 1
Регистрация: 28.06.2012
Сообщений: 3,462
12.02.2013, 14:02     Использование Сервисов #19
ну, будильник как-то включается даже если девайс спит...

Добавлено через 4 минуты
ну нагуглил я никаких упоминаний о том, что сервис не работает когда девайс засыпает.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
12.02.2013, 14:10     Использование Сервисов
Еще ссылки по теме:

использование thread Android
Использование HttpURLConnection Android
Android Использование Loader
Android Использование RemoteViews в AppWidgetProvider
Push уведомления без сторонних сервисов Android

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
obrazer
69 / 69 / 1
Регистрация: 04.09.2012
Сообщений: 170
12.02.2013, 14:10  [ТС]     Использование Сервисов #20
Будильник включается посредством АлармМенеджера. Это немного другой механизм нежели мне нужен
Цитата Сообщение от V0v1k Посмотреть сообщение
никаких упоминаний о том, что сервис не работает когда девайс засыпает.
Вот я тоже ненагуглил, но счетчик не работает, а значит сервис не работает. Походу придется запрещать девайсу спать.
Yandex
Объявления
12.02.2013, 14:10     Использование Сервисов
Ответ Создать тему
Опции темы

Текущее время: 11:55. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru