73 / 73 / 3
Регистрация: 04.09.2012
Сообщений: 170
1

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

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

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

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

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

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

Ну как-то так

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

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

PS: Возможно слегка сумбурно объяснил, если непонятно - спрашивайте, буду корректировать мысль.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
07.02.2013, 00:15
Ответы с готовыми решениями:

Гуру, Теория сервисов
Гуру, Помогите! Перечитал уроки, основы понял, но суть ускользает. ТАКИХ нюансов в уроках нет......

Обьясните работу сервисов в fcm
Задался вопросом, как работают собственно push-уведомления. В Android, чтобы система с меньшей...

Push уведомления без сторонних сервисов
Есть форма php, на которой располагается одна кнопка, при нажатии на эту кнопку на мобильный...

Как получить приблизительное местоположение пользователя без использования сервисов Google?
Добрый день, Никак не могу войти под старым ником, поэтому вновь зарегистрировался. Возник...

28
97 / 96 / 4
Регистрация: 14.02.2009
Сообщений: 311
07.02.2013, 12:14 2
возможно эта статья вас наталкнет на какие мысли
по работе с базой
http://www.enterra.ru/blog/and... th_sqlite/

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

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

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

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

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

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

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

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

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

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

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

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

Хотя отображать Критичные сообщения в случае когда Активити активно это может помочь.
0
325 / 123 / 10
Регистрация: 01.11.2012
Сообщений: 586
08.02.2013, 06:04 7
А нельзя ли в таком случае сохранять эти уведомления в каком либо файле, а активити при следующем запуске их прочитает, ну и, например, удалит. Я бы такой подход использовал.
0
73 / 73 / 3
Регистрация: 04.09.2012
Сообщений: 170
08.02.2013, 08:43  [ТС] 8
Ну в таком случае удобнее все же использовать БД. Все же структурированнее будут данные.

А что смущает в приведенном мною последнем варианте?
0
325 / 123 / 10
Регистрация: 01.11.2012
Сообщений: 586
08.02.2013, 09:19 9
Цитата Сообщение от obrazer Посмотреть сообщение
Ну в таком случае удобнее все же использовать БД. Все же структурированнее будут данные.
А что смущает в приведенном мною последнем варианте?
если вопрос был ко мне:
1. БД это такая хитроопая штука в андроиде, что надо иметь рядом с собой стакан иначе понять невозможно, так же как и русскую душу.
2. Ничего не смущает, просто написал свое видение. Стараюсь использовать то, что проще для меня...
0
73 / 73 / 3
Регистрация: 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).

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

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

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

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

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

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

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

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

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

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

Добавлено через 4 минуты
ну нагуглил я никаких упоминаний о том, что сервис не работает когда девайс засыпает.
0
73 / 73 / 3
Регистрация: 04.09.2012
Сообщений: 170
12.02.2013, 14:10  [ТС] 20
Будильник включается посредством АлармМенеджера. Это немного другой механизм нежели мне нужен
Цитата Сообщение от V0v1k Посмотреть сообщение
никаких упоминаний о том, что сервис не работает когда девайс засыпает.
Вот я тоже ненагуглил, но счетчик не работает, а значит сервис не работает. Походу придется запрещать девайсу спать.
0
12.02.2013, 14:10
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
12.02.2013, 14:10
Помогаю со студенческими работами здесь

Использование голосовых сервисов Google в своих целях
Всем привет. Два вопроса тут возникло по теме топика: 1) Как известно легко можно использовать...

API внешних сервисов
Подскажите, пожалуйста материалы какие-нибудь, книги, где можно изучить работу в Python с API...

Компонент платежных сервисов
Прива! Ребзя, нужна ваша помошь! Время терпит, но душа не имеет покоя... Проблема вот в чем....

Удаление Гугл - сервисов
Здравствуйте. Телефон - Yotaphone 2. Версия андроида - 4.4.3 Вопрос такой, как лучше...

Тестирование сервисов в Symfony
Как тестировать сервисы в Symfony? В приложении есть два варианта вызова сервисов - через контейнер...

Блокировка поисковых сервисов
Здравствуйте! Заранее извиняюсь если подобная тема обсуждалась (не нашел). Дело вот в чем: Есть...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru