Урок 99. Service. Уведомления - notifications

Обсуждение уроков
sergpol
Сообщения: 10
Зарегистрирован: 11 фев 2014, 08:50

Re: Урок 99. Service. Уведомления - notifications

Сообщение sergpol » 11 фев 2014, 09:05

Всем привет. Огромное спасибо автору за уроки, практически по ним и учусь.
Вопрос по теме сервисов. Делаю сервис, Foreground, он выводит уведомление. Внешний вид уведомления задается своей разметкой, более того, выбор разметки зависит от выбора настроек в программе. Данные в уведомление должны попадать из БД. Так вот, вроде как все работает, запускается таймер с задачей, задача возвращает Notification notif, к которому я применяю nm.notify(1, notif); (где nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);) в процедурах onBind и onReBind, но изменение настроек сервис считать не может, он получает всегда значение настройки, которое получил при запуске (тип настройки - булево). И никак его не поменять, пробовал передавать значение настройки в Интенте при биндинге сервиса - нифига... :( Никак не поменять уведомление. Максимум 1 раз почему то, и как только срабатывает таймер задачи - оно опять приходит к первоначальному виду. Делал стоп-старт сервиса, но это как то... криво. Почему сервис не может считать значение настроек (объявляются они в модуле сервиса так: SharedPreferences sp_default = PreferenceManager.getDefaultSharedPreferences(this);)? И почему даже через Интент не передать изменившееся значение настройки?!! Делаю в MainActivity так (в процедуре onSharedPreferenceChanged):

Код: Выделить всё

Intent intent = new Intent(this, CurrencyForegroundNotify.class);
intent.putExtra("update_notification", true);				
intent.putExtra("daily_dynamic", prefs.getBoolean("daily_dynamic", false));				
bindService(intent, sConn, BIND_AUTO_CREATE);
unbindService(sConn);
И вот всегда сервис получает daily_dynamic, которая была при старте сервиса. Дальнейшие изменения его не интересуют...
Что я могу делать не так? Возможно где то принципиальная ошибка?

Т.е., в итоге, единственная у меня счас проблема - я банально не могу обновить уведомление! Задача-таймер работает (по логам), но считывает данные откуда то из кэша что ли. Уведомление выводится красивое :), но статичное...

Заранее спасибо!!!

Аватара пользователя
Mikhail_dev
Сообщения: 2386
Зарегистрирован: 09 янв 2012, 14:45
Откуда: Самара

Re: Урок 99. Service. Уведомления - notifications

Сообщение Mikhail_dev » 11 фев 2014, 16:46

А сервис в отдельном процессе или все же в основном?
А вы пробовали вообще проверить, может настройки после изменения вообще не поменялись? Может вы их заново то и не считали?
Почему сервис не может считать значение настроек (объявляются они в модуле сервиса так: SharedPreferences sp_default = PreferenceManager.getDefaultSharedPreferences(this);)?

В каком это еще модуле сервиса?

sergpol
Сообщения: 10
Зарегистрирован: 11 фев 2014, 08:50

Re: Урок 99. Service. Уведомления - notifications

Сообщение sergpol » 11 фев 2014, 16:55

m090050 писал(а):А сервис в отдельном процессе или все же в основном?
Да, уже начало доходить - в отдельном, поэтому простой биндинг и не работает.
m090050 писал(а):А вы пробовали вообще проверить, может настройки после изменения вообще не поменялись? Может вы их заново то и не считали?
Это все как то интересно работает. Я меняю настройку (true/false), первое изменение настройки почему то отрабатывается (почему?!!), внешний вид (разметка) меняется, нотификация обновляется, но далее, сколько бы я не менял - sp_default.getBoolean("daily_dynamic", false) всегда возвращает одно и тоже значение, получившееся после первого изменения настройки. Если передавать значение настройки в extras через intent - то же самое. Судя по логам - все прекрасно отрабатывает (onBind, onRebind, сам сервис прекрасно "живет", запуская по таймеру обновление нотификации). Но - ни значение настройки, ни передаваемый параметр через intent - не меняются! Т.е. я прямо в процедуре обновления нотификации считываю значение настройки - и оно не соответствует реальности! Например, значение = true, а возвращается false. Сумбурно, но как то так.
В каком это еще модуле сервиса?

Извиняюсь, профессиональное видимо :) В классе сервиса - наверное правильнее будет. Еще точнее - в onCreate().
Я вроде как примерно понимаю как надо - видимо через messanger. Буду копать дальше.
Спасибо за ответ!!!

Аватара пользователя
Mikhail_dev
Сообщения: 2386
Зарегистрирован: 09 янв 2012, 14:45
Откуда: Самара

Re: Урок 99. Service. Уведомления - notifications

Сообщение Mikhail_dev » 11 фев 2014, 17:30

Да, уже начало доходить - в отдельном, поэтому простой биндинг и не работает.
AIDL вам тут поможет
На счет почему не изменяются настройки в сервисе. Они не меняются по причине того, что отдельный процесс - это отдельная копия виртуальной машины, где крутится ваша программа (Dalvik), а это порождает то, что ваши синглтоны вдруг становятся двойными. Т.е. вот обновили вы настройки из Активности, они и обновились в активности, но не обновились в сервисе. Тут есть нюансы. Я писал заметку по этому поводу, в моей подписи, последняя.

Аватара пользователя
klblk
Сообщения: 1097
Зарегистрирован: 18 окт 2012, 11:17
Откуда: г. Красноярск

Re: Урок 99. Service. Уведомления - notifications

Сообщение klblk » 11 фев 2014, 18:20

Messenger тоже может помочь
http://developer.android.com/guide/comp ... #Messenger
пример на хабре: http://habrahabr.ru/post/157063/


Аватара пользователя
klblk
Сообщения: 1097
Зарегистрирован: 18 окт 2012, 11:17
Откуда: г. Красноярск

Re: Урок 99. Service. Уведомления - notifications

Сообщение klblk » 11 фев 2014, 18:33

m090050 писал(а):А в чем его преимущество перед AIDL?
честно AIDL сам ни разу не использовал.
Но вот что пишут доки:
When you need to perform IPC, using a Messenger for your interface is simpler than implementing it with AIDL, because Messenger queues all calls to the service, whereas, a pure AIDL interface sends simultaneous requests to the service, which must then handle multi-threading.

For most applications, the service doesn't need to perform multi-threading, so using a Messenger allows the service to handle one call at a time. If it's important that your service be multi-threaded, then you should use AIDL to define your interface.
Если я правильно понял, то в случае Messenger сообщения обрабатываются поочередно, а в AIDL в разных потоках.

Аватара пользователя
Mikhail_dev
Сообщения: 2386
Зарегистрирован: 09 янв 2012, 14:45
Откуда: Самара

Re: Урок 99. Service. Уведомления - notifications

Сообщение Mikhail_dev » 11 фев 2014, 19:20

Я понял. Если у нас И сервис, И UI поток могут друг с другом общаться в обе стороны, то там лучше AIDL. Если всё же сервис в роли ответчика, а UI им заправляет, то там лучше Messendger.

sergpol
Сообщения: 10
Зарегистрирован: 11 фев 2014, 08:50

Re: Урок 99. Service. Уведомления - notifications

Сообщение sergpol » 11 фев 2014, 21:04

Спасибо вам за ответы, про разные процессы понятно. Но осталось непонятно, почему в extras не передать параметр? В активити то он - меняется. А при извлечении параметра в сервисе - нет! Получается, со стороны, бред: передаем true, вынимаем, получаем false. Как так?! :)

Аватара пользователя
Mikhail_dev
Сообщения: 2386
Зарегистрирован: 09 янв 2012, 14:45
Откуда: Самара

Re: Урок 99. Service. Уведомления - notifications

Сообщение Mikhail_dev » 11 фев 2014, 21:26

Я думаю что проблема именно в том, что это два процесса. Попробуйте проверьте, уберите сервис с отдельного процесса. Если проблема останется, значит однозначно что-то не так делаете.

sergpol
Сообщения: 10
Зарегистрирован: 11 фев 2014, 08:50

Re: Урок 99. Service. Уведомления - notifications

Сообщение sergpol » 11 фев 2014, 21:56

Да, теперь настройки считываются корректно! Но! То, что я передаю в Интенте, опять таки "дурит", не меняется... Завтра буду пристально смотреть, ибо должно все соответствовать, возможно я где то накосячил с передачей параметров. И попутно вопрос: а хорошо ли, что сервис не в отдельном процессе? Мне надо чтобы он "висел" сколько угодно долго и обновлялся по расписанию (раз в час) + принудительно после обновлений в программе, и убивался опять таки из программы, когда пользователь снимает галку в настройках.

Аватара пользователя
Mikhail_dev
Сообщения: 2386
Зарегистрирован: 09 янв 2012, 14:45
Откуда: Самара

Re: Урок 99. Service. Уведомления - notifications

Сообщение Mikhail_dev » 11 фев 2014, 22:53

А что собственно сервис должен делать?
Но! То, что я передаю в Интенте, опять таки "дурит", не меняется...
Ну не просто же так есть такая вещь как AIDL и Messenger, они нужны для работы при межпроцессорном взаимодействии. Я думаю это проблема именно межпроцессорного взаимодействия.
Как еще один вариант могу предложить использовать BroadcastReceiver.
А лучше вообще задуматься, а нужен ли второй процесс. Он нужен в КРАЙНЕ редких случаях.

sergpol
Сообщения: 10
Зарегистрирован: 11 фев 2014, 08:50

Re: Урок 99. Service. Уведомления - notifications

Сообщение sergpol » 12 фев 2014, 08:11

m090050 писал(а):Ну не просто же так есть такая вещь как AIDL и Messenger, они нужны для работы при межпроцессорном взаимодействии. Я думаю это проблема именно межпроцессорного взаимодействия.
Как еще один вариант могу предложить использовать BroadcastReceiver.
А лучше вообще задуматься, а нужен ли второй процесс. Он нужен в КРАЙНЕ редких случаях.
Понятно, огромное спасибо за ответы!!! Вчера вечером запустил сервис на эмуляторе и на телефоне у себя (который НЕ в отдельном процессе, просто) - до сих пор оба живые (каждые 10 сек сыпет в логи) :) Видимо так и сделаю. Еще в него видимо добавлю обнаружение WiFi - для автоматического обновления.

sergpol
Сообщения: 10
Зарегистрирован: 11 фев 2014, 08:50

Re: Урок 99. Service. Уведомления - notifications

Сообщение sergpol » 14 фев 2014, 10:51

В процессе работы все-таки возникли сложности, похоже не удается мне поместить в 1 сервис 2 задачи. Мешают они друг другу. В связи с этим вопрос: не будет ли перебором делать 2 сервиса (один отвечает за показ постоянного и обновляемого уведомления, второй - за определение, что подключился WiFi)? Это нормальная практика, или все таки надо постараться уложить обе задачи в 1 сервис? Задачи не обязательно должны работать одновременно - это по будет желанию пользователя, и периоды заданий разные (в одной 1 час, в другой (по WiFi) почаще).

Аватара пользователя
Mikhail_dev
Сообщения: 2386
Зарегистрирован: 09 янв 2012, 14:45
Откуда: Самара

Re: Урок 99. Service. Уведомления - notifications

Сообщение Mikhail_dev » 14 фев 2014, 12:01

Я даже не знаю как сейчас у вас архитектура. Сервис в отдельном процессе? AIDL или Messenger?
В любом случае, я не вижу причин делать два сервиса. У нас в удаленном сервисе крутится 100500 различных задач, все проблемы при этом решаемы.

sergpol
Сообщения: 10
Зарегистрирован: 11 фев 2014, 08:50

Re: Урок 99. Service. Уведомления - notifications

Сообщение sergpol » 14 фев 2014, 12:31

Сервис НЕ в отдельном процессе, иначе ему изменение настроек не увидеть.
Если бы сервис работал ВСЕГДА- нет проблем. Но это не надо. Есть 2 настройки. Каждая должна как включать сервис (если еще не была включена другая настройка), так и выключать (если другая настройка тоже выключена). Вот тут то и беда. Одна настройка должна запускать уведомление, другая нет... Сервис к тому же Foreground (для одной настройки обязательно уведомление, для этого собственно она и делается). Вот и не совместить мне...
Как мне правильно определить, что сервис уже запущен?

Аватара пользователя
Mikhail_dev
Сообщения: 2386
Зарегистрирован: 09 янв 2012, 14:45
Откуда: Самара

Re: Урок 99. Service. Уведомления - notifications

Сообщение Mikhail_dev » 14 фев 2014, 13:53

А зачем его вообще определять, запущен или нет? Можно ведь стартануть второй раз его, и собственно ничего не произойдет. Второй раз метод onCreate не вызовется.

sergpol
Сообщения: 10
Зарегистрирован: 11 фев 2014, 08:50

Re: Урок 99. Service. Уведомления - notifications

Сообщение sergpol » 14 фев 2014, 15:21

Все, вроде как зашуршало: я использовал биндинг, но что то он глючил, и через Intent параметры считывались опять некорректно почему то. Тупо везде, где надо, стал делать вызывать startService(intent); и все, параметры (команды "что делать" для сервиса) передаются корректно! В итоге все работает как надо, сколько бы галками не "играться", в любой последовательности, если обе выключить то и сервис грохается - красота..
Остался маленький вопрос-уточнение.
Если включена настройка отображения уведомления, то оно отображается, и, естественно не важно, работает ли задача по сканированию WiFi. Но. Если пользователь выключает уведомление, и хочет оставить сканирование WiFi - уведомление в данном случае надо бы убрать - я сделал вот так:

Код: Выделить всё

NotificationCompat.Builder mBuilder =  new NotificationCompat.Builder(this);
nm.notify(1, mBuilder.getNotification());
(где nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); в OnCreate()).
Так правильно делать?

Аватара пользователя
Mikhail_dev
Сообщения: 2386
Зарегистрирован: 09 янв 2012, 14:45
Откуда: Самара

Re: Урок 99. Service. Уведомления - notifications

Сообщение Mikhail_dev » 14 фев 2014, 18:15

Я делаю так
[syntax=java5]
public void removeNotificationById(int _id) {
try {
mNotificationManager.cancel(_id);
} catch (Exception e) {
if (DEBUG) Logger.log(Logger.WARN, TAG, e);
}
}
[/syntax]
где
private android.app.NotificationManager mNotificationManager;

sergpol
Сообщения: 10
Зарегистрирован: 11 фев 2014, 08:50

Re: Урок 99. Service. Уведомления - notifications

Сообщение sergpol » 15 фев 2014, 11:09

m090050 писал(а):Я делаю так
Я пробовал, но т.к. это уведомления сервиса Foreground, то оно не удаляется.

Последняя заморочка... При установке приложения (обновлении) сервис благополучно убивается и не восстанавливается. Есть какие то способы исправить такое поведение? А то после первого же обновления приложения, получается, сервис умирает.

Ответить