Подтвердить что ты не робот

Регистрация BroadcastReceiver to Widget (Разница контекстного объекта)

A немного смутите разницу между Контекстом Виджета и Контекстом приложения: Что касается проблемы, связанной с неспособной зарегистрировать новый BroadcastReceiver через исходный код реализации Android Widget (Ref.1)


По соображениям удобочитаемости я копирую свой ответ, как показано ниже: ★ Проблема Генри (Ref.1):

Я создаю виджет, который нуждается в широковещательный приемник, такой как com.example.android.apis.appwidget.ExampleBroadcastReceiver. Однако в этом примере Intent.ACTION_TIMEZONE_CHANGED в манифест, но есть некоторые, которые делают не допускайте этого

Например, Intent.ACTION_TIME_TICK говорит: "Вы не можете получить это через компоненты, объявленные в манифесте, только путем неявной регистрации для него Context.registerReceiver()."

Итак, я удалил объявления манифеста и попытался заменить Функция AppWidgetProvider.onEnabled это было в примере с вызовом как показано ниже: context.registerReceiver(myReceiver, новый IntentFilter (Intent.ACTION_TIME_TICK));

(где "myReceiver" - это пример получателя я хочу.) Однако, когда я попробуйте запустить код, я получаю следующая ошибка:

Не удалось запустить приемник... android.content.ReceiverCallNotAllowedException: Компоненты IntentReceiver не являются разрешено регистрироваться для получения намерений

★ Наш анализ этой проблемы и решение этой проблемы (Ref.1)

Это результат после исследования этого проблема, я был успешным обработчиком вопрос. Поэтому я собираю как отчет для обмена с разработчиком Android. Надеюсь, что это поможет.

Вот результат:

❶ISSUE: * Относительно ограничений от Widget, когда пытаетесь зарегистрироваться BroadcastReceiver через явный источник код: (Нет эффекта при регистрации BroadcastReceiver через Manifest.xml)

❷EXAMPLE: * BroadcastReceiver: сообщение ACTION_TIME_TICK - одно Например: поскольку документы от Android были укажите: "Вы не можете получить это через компоненты, объявленные в проявляется, только экслитически регистрируя для него Context.registerReceiver()." (Ref.1)

❸PREVIOUS SOLUTION: * Code Snippet: context.registerReceiver(это, intentName); (1)

❹ERROR при использовании 3 ★ решения * Когда реализация следовать (1), он, хотя исключение: android.content.ReceiverCallNotAllowedException: Компоненты IntentReceiver не являются разрешено регистрироваться для получения намерений

★ Хорошая новость для всех, кто нуждается в зарегистрируйтесь BroadcastReceiver в виджет:) МОЖЕТ зарегистрироваться BroadcastReceiver

❺ НАШЕ РЕШЕНИЕ: * Но мы можем исправить это с помощью используемого контекста приложения вместо контекста виджетов (*) Код Snippet: context.getApplicationContext.registerReceiver(это, intentName);

❻REFERENCE: * http://developer.android.com/reference/android/content/Intent.html#AC... Что касается

❼TARGET ENVIRONEMNT: * SDK 2.3, как на эмуляторе, так и на NexusOne 2.3, If любой успех с этим решением обновите наш отчет

❽NOTES * Может быть разница между Контекстным объектом виджета и приложение, но я до сих пор не знаю именно причина этой проблемы.

Пожалуйста, дайте мне знать, если у вас есть лучшее решение или объяснить больше ясно

Также я решил эту проблему, но я до сих пор не известны точно причины эта проблема.

Пожалуйста, дайте мне знать, если у вас есть лучшее решение или объяснить больше ясно


★ CONCLUTION:

NG: при использовании контекста виджета для регистрации BroadcastReceiver

context.registerReceiver(this, intentName); 

- > он думал, что исключение:

Unable to start receiver...android.content.ReceiverCallNotAllowedException: IntentReceiver components are not allowed to register to receive intents

ОК: при использовании контекста приложения все работает нормально:

ontext.getApplicationContext.registerReceiver(this, intentName); 

★ ВОПРОС: Также наше решение может решить проблему: "невозможно зарегистрировать новое широковещательное сообщение через исходный код приложения Android-виджета".

Но я все еще отношусь к двум Qestion:

Вопрос ❶: Разница между Контекстом Виджета и Контекстом приложения и другим объектом Контекста (Контекст активности) '

Вопрос. Поскольку контекстный объект обычно использовался, когда использовать контекст приложения и когда использовать другой контекст.

Для ❷ я нашел объяснение, связанное с утечкой памяти (ссылка 2), но я думаю, что этого может быть недостаточно (Ref.2)

Итак, если у вас есть ответ, пожалуйста, сообщите мне, любой ответ оценили.

Спасибо


★ Referecens:

(1) http://groups.google.com/group/android-developers/browse_thread/thread/790da1a655f4a227/0b8d6aad1dc2d371?hl=en&lnk=gst&q=Broadcast+Receiver+From+Widget#0b8d6aad1dc2d371

(2) http://developer.android.com/resources/articles/avoiding-memory-leaks.html

4b9b3361

Ответ 1

Этот вопрос старше года и определенно долгий и сложный, и английский язык трудно понять. Тем не менее, он, вероятно, заслуживает какого-то ответа.

Если я понимаю, вы в основном просите разницу между различными объектами Android Context. Основное отличие - область или продолжительность жизни.

Контекст приложения (который можно получить с помощью Activity.getApplicationContext() или Context.getApplicationContext()) имеет срок службы всего вашего приложения. Контекст приложения создается, когда запущено ваше приложение (или его части). Оно живет (более или менее) ) навсегда.

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

Существуют другие Контексты, подобные тем, которые вы получаете в BroadcastReceiver или AppWidgetProvider в onReceive(). Этот Контекст имеет очень короткое время жизни (он уничтожается сразу же после возвращения метода onReceive()). Поэтому вы можете делать ограниченные вещи только с помощью этого Контекста.

Вы хотите зарегистрировать приемник для прослушивания интересующих вас вещательных намерений. Вы не можете сделать это с помощью контекста, который вы получаете в onReceive(), потому что этот контекст имеет короткое время жизни, и слушатель должен быть связан с чем-то. В этом случае вы можете использовать контекст приложения, чтобы связать слушателя с. Это работает, но вам нужно понять, что вы создали некоторые объекты, которые никогда не исчезнут, потому что они всегда активны. По крайней мере, вы должны убедиться, что вы очистите это, когда пользователь удалит ваш виджет со своего домашнего экрана, удалив прослушиватель, используя unregisterReceiver().

В StackOverflow есть много вопросов/ответов относительно использования Context. Например, В чем разница между различными методами получения контекста?

Ответ 2

Несмотря на то, что Дэвид Уэссер дал отличный ответ, я думаю, что по-прежнему имеется соответствующая информация. Итак, вот оно:

В конце концов Контекст - это просто ссылка на разные компоненты вашего собственного приложения (например, ресурсы, информацию о пакете и т.д.) и на внешнюю операционную систему. Таким образом, все различные контексты, которые вы упомянули, являются лишь ссылкой на одно и то же, единственное различие заключается в том, как долго каждая ссылка действительна.

В конкретном случае AppWidgetProvider контекст, который вы получаете по его методам, - это тот же контекст, который предоставляется методом BroadcastReceiver onReceive. Фактически AppWidgetProvider - просто причудливое имя для обычного BroadcastReceiver, который вызывает определенные методы при получении связанных с виджетами намерений, например ACTION_APPWIDGET_UPDATE.

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

context.getApplicationContext.registerReceiver(this, intentName);

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

Итак, если вам нужно программно добавить фильтры намерений в BroadcastReceiver, вот мое предложение:

1) Создайте другой BroadcastReceiver в долговечном контексте класса, например класс, расширяющий приложение. Давайте назовем его mMainReceiver.

2) Применить фильтр намерения на нем, а также зарегистрировать и отменить регистрацию в соответствии с вашими потребностями.

3) Создайте личное намерение, например MY_ACTION_TIME_TICKER, и запускает его из вашего метода mMainReceiver onReceive.

4) В вашем манифесте зарегистрируйте фильтр MY_ACTION_TIME_TICKER для вашего приемника AppWidgetProvider.

Таким образом, вы можете использовать один BroadcastReceiver, действующий как мост к вашему AppWidgetProvider, и вы можете в любое время зарегистрироваться и отменить регистрацию.