Как получить контекст в службе (не applicationContext)

Можно ли ссылаться на контекст в службе, но не используя контекст приложения?

Я пытаюсь добиться возможности показывать закусочную из службы, когда что-то происходит. Это должно быть выполнено в НЕСКОЛЬКИХ действиях. Для этого мне нужен контекст, а затем ссылка на него, чтобы получить представление, используя эту строку:

View rootView = ((Activity)context).getWindow().getDecorView().findViewById(android.R.id.content)

Я делаю это в своем сервисе:

class MyService : Service() {

override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
//TODO do something useful

val view: View = (this.applicationContext as Activity).window.decorView.findViewById(android.R.id.content)
Timber.d("some jobe done")
return Service.START_NOT_STICKY
  }

override fun onBind(intent: Intent): IBinder? {
//TODO for communication return IBinder implementation
   return null
 }
}

Однако я получаю сообщение об ошибке при обращении к контексту приложения и приведению его к Activty:

Caused by: java.lang.ClassCastException: com.myapp.Application cannot be cast to android.app.Activity

Можно ли с этим справиться должным образом (в отношении моего варианта использования)?

1
0
172
1

Ответы 1

I am trying to achive ability to show snackbar from service when something occurs.

Это плохая идея. Например, он не касается сценария, в котором у вас нет текущих действий.

To do this i need context and then refer from it to get the view using this line:

Нет, вам понадобится объект Activity, как вы видите по вашему слепку.

Is it possible to handle this properly (refering my use case)?

Не так, как вы подходите к проблеме.

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

  • У вас есть видимое действие, которое затем может сообщить пользователю о событии с помощью некоторых подходящих средств (например, закусочной).

  • У вас нет активности, которая является видимой, и в этом случае служба может вызвать уведомление или, возможно, просто отбросить событие (если нет необходимости сообщать пользователю об этом, если пользователь не находится в пользовательском интерфейсе приложения )

Типичный подход к этой проблеме - использовать ту или иную форму шины событий (LocalBroadcastManager, EventBus greenrobot или любое количество реализаций шины событий на основе RxJava):

  • Сервис размещает мероприятие в автобусе.

  • Каждое действие подписывается на шину для событий, пока оно видно, и отменяет подписку, когда оно больше не отображается (например, через onStart() / onStop())

  • Если действие получает событие, оно показывает пользователю снэк-бар (или что-то еще).

  • Если служба определяет, что событие не зафиксировано, она использует некоторый запасной подход.

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

Это пример приложения демонстрирует этот подход с помощью EventBus greenrobot, и это пример приложения демонстрирует этот подход с LocalBroadcastManager.

Существуют и другие решения, которые не используют настоящую шину событий, например, служба обновления репозитория, которая обновляет компоненты пользовательского интерфейса с помощью реактивных средств (например, RxJava, ведущего к LiveData). Однако служба не должна пытаться напрямую манипулировать пользовательским интерфейсом действия, отчасти потому, что действия может не быть.

Да, но видение установки подписки на все мои действия довольно плохое для меня, у меня их много во всем моем приложении. Если бы у меня была эта возможность в моем Сервисе, я бы не заботился о реализации подписки во всех из них и просто показывал Snackbar, когда что-то происходит там, где есть активность (например, с Toast, он работает, поскольку для работы ему нужен только контекст)

K.Os 02.05.2018 01:25

@Konrad: «у меня их много во всем приложении» - используйте наследование, чтобы минимизировать дублирование кода.

CommonsWare 02.05.2018 01:29

Другие вопросы по теме