Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Register BroadcastReceiver to Widget (Difference of Context object)

Tags:

A have a little confuse the difference between Widget Context and Application Context: Regarding problem relate with unable to register new BroadcastReceiver via implement source code of Android Widget (Ref.1)


For readability reason, i copy my answer as below: ★Problem by Henry (Ref.1):

I am making a widget that needs a broadcast receiver, like the one in com.example.android.apis.appwidget.ExampleBroadcastReceiver. However, the example defines Intent.ACTION_TIMEZONE_CHANGED in the manifest, but there are some that do not allow this

For example, Intent.ACTION_TIME_TICK says "You can not receive this through components declared in manifests, only by exlicitly registering for it with Context.registerReceiver(). "

So I removed the manifest declarations and tried replacing the AppWidgetProvider.onEnabled function that was in the example with a call like the following: context.registerReceiver(myReceiver, new IntentFilter(Intent.ACTION_TIME_TICK));

(where "myReceiver" is an instance of the receiver I want.) However, when I try to run the code, I get the following error:

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

★Our analysis this issue and solution for this problem (Ref.1)

This is result after investigate this problem, i was handler successful this issue. So i collect as report to share with android developer. Hope it help

Here is result:

❶ISSUE:* Regarding limited from Widget, when try to register BroadcastReceiver via explicit source code: (No effect when register BroadcastReceiver via Manifest.xml)

❷EXAMPLE: * BroadcastReceiver: ACTION_TIME_TICK message is one example: As docs from Android had point out: "You can not receive this through components declared in manifests, only by exlicitly registering for it with Context.registerReceiver()." (Ref.1)

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

❹ERROR when used 3★ solution* When implement follow (1), it though exception: android.content.ReceiverCallNotAllowedException: IntentReceiver components are not allowed to register to receive intents

★Good news for anyone who need to register BroadcastReceiver in Widget :) we CAN register successful BroadcastReceiver

❺OUR SOLUTION:* But, We can fixed this by used application context instead of Widget context(*) Code Snippet: context.getApplicationContext.registerReceiver(this, intentName);

❻REFERENCE:* http://developer.android.com/reference/android/content/Intent.html#AC... Regarding

❼TARGET ENVIRONEMNT:* SDK 2.3, both on Emulator and NexusOne 2.3, If anyone success with this solution please update our report

❽NOTES* May be difference between Context object of widget and application, but i still don't known exactly cause of this problem.

Please let me known if your have better solution or explain more clearly

Also i had solver this problem, but i still don't known exactly cause of this problem.

Please let me known if your have better solution or explain more clearly


★CONCLUTION:

NG: When use Widget context to register BroadcastReceiver

context.registerReceiver(this, intentName);  

-> it thought exception:

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

OK: When use Application context everything working fine:

ontext.getApplicationContext.registerReceiver(this, intentName);  

★QUESTION: Also our solution can solver problem: "unable to register new broadcast message via implement source code of Android widget".

But i still concern two Qestion:

Question❶: The difference between Widget Context and Application Context and other Context object (Activity Context)'

Question❷: Because context object was use usually so when to use Application context and when to use other Context.

For ❷ i had found explain relate with memory leak (Ref. 2), but i think it may not enough (Ref.2)

So if your have answer please let me known, any answer appreciated.

Thanks


★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

like image 645
NguyenDat Avatar asked Feb 25 '11 01:02

NguyenDat


People also ask

What file is used to register the BroadcastReceiver?

An application listens for specific broadcast intents by registering a broadcast receiver in AndroidManifest. xml file. Consider we are going to register MyReceiver for system generated event ACTION_BOOT_COMPLETED which is fired by the system once the Android system has completed the boot process.

What is the role of the onReceive () method in the BroadcastReceiver?

Retrieve the current result extra data, as set by the previous receiver. This can be called by an application in onReceive(Context, Intent) to allow it to keep the broadcast active after returning from that function.

How do I send data from BroadcastReceiver to activity?

Intent intent = getIntent(); String message = intent. getStringExtra("message"); And then you will use message as you need. If you simply want the ReceiveText activity to show the message as a dialog, declare <activity android:theme="@android:style/Theme.

Where do I register and unregister broadcast receiver?

You should register and unregister your broadcast in onResume() and onPause() methods. if you register in onStart() and unregister it in onStop().


2 Answers

This question is over a year old and is definitely long and complicated and the English language is difficult to understand. However, it still probably deserves some kind of answer.

If I understand, you are basically asking for the difference between the different Android Context objects. The main difference is scope or lifetime.

The application's Context (that you can get with Activity.getApplicationContext() or Context.getApplicationContext() has a lifetime of your entire application. The application Context is created when your application (or parts of it) are started. It lives (more or less) forever.

An activity's Context is created when that Activity is created and goes away when that activity is destroyed. If you are doing anything with the UI, you need to do that using the activity's Context so that when the activity is destroyed, those things that are related to that activity are also cleaned up.

There are other Contexts like the one you get in a BroadcastReceiver or an AppWidgetProvider in onReceive(). This Context has a very short lifetime (it is destroyed immediately after the onReceive() method returns). Therefore you can only do limited things with this Context.

You want to register a Receiver to listen for the broadcast Intents you are interested in. You cannot do this with the Context you get in onReceive() because that Context has a short lifetime and the listener has to be linked to something. In this case you can use the application's Context to link the listener to. This works, but you need to realize that you've created some objects that will never go away because they are always active. At least you should make sure that you clean this up when the user deletes your widget from his home screen by removing the listener using unregisterReceiver().

There are a lot of questions/answers on StackOverflow regarding usage of Context. For example, What's the difference between the various methods to get a Context?

like image 160
David Wasser Avatar answered Oct 14 '22 20:10

David Wasser


Even though David Wesser provided an excellent answer, I think there are still relevant information to be added. So here it goes:

In the end, Context is just a reference to different components of your own app (like resources, package information, etc) and to the operating system outside it. So all different contexts you mentioned are just a reference to the same thing, the only difference is for how long each reference is valid.

In the specific case of AppWidgetProvider, the context you get on its methods is the same context provided by BroadcastReceiver onReceive method. Actually AppWidgetProvider is just a fancy name for a regular BroadcastReceiver which calls specific methods when receiving widget related intents, like ACTION_APPWIDGET_UPDATE.

The problem with your code is that AppWidgetProvider has a very short lifecycle: every time a widget broadcast arrives, a new instance of AppWidgetProvider is created just to execute the correspondent method. So when you do this:

context.getApplicationContext.registerReceiver(this, intentName); 

you are registering a new BroadcastReceiver to your app context every time a widget intent is received. Besides that, when you try to unregister your AppWidgetProvider, you are actually referring to another instance of it, so you will probably get an exception and even if you catch it, there will be a memory leak on your app.

So if you need to programmatically add intent filters to a BroadcastReceiver here is my suggestion:

1)Create a different BroadcastReceiver on a long lived context class, like a class that extends Application. Lets call it mMainReceiver.

2)Apply the intent filter programatically on it, and register and unregister it according to your needs.

3)Create a private intent, like MY_ACTION_TIME_TICKER and fires it from your mMainReceiver onReceive method.

4)On your manifest, register a MY_ACTION_TIME_TICKER filter to your AppWidgetProvider receiver.

This way you can have a single BroadcastReceiver acting as a bridge to your AppWidgetProvider, and you can register and unregister it anytime.

like image 36
Rodrigo Dias Avatar answered Oct 14 '22 19:10

Rodrigo Dias