I know this is a broad question, but this might be any average android developer's question. In a BroadcastReceiver, what is the context parameter passed through onReceive() method?
public class MyReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
}
}
I just know we have 3 main types of context: Activity, Service, Application.
Initially Context represents environment data and it is used to create application specific resource.
for example, if you create a new object for a class with "this" keyword as its context, that object was resource for that specific class and not for others.
context was also used to share system resources like layoutInflater, NotificationManager and so on.
In Broadcast receiver, context refers to the activity or class in which the broadcast receiver is running. if your "MainActivity" sends a broadcast then the context would have something like the following "com.example.MainActivity"
Related
Pass additional parameters to a dynamically registered BroadcastReceiver.
The problem is basic: I want to pass parameters to a BroadcastReceiver. Can this be done? Even when the receiver is created dynamically?
Additionally, say I create an anonymous BroadcastReceiver i.e. as a variable implementation. Can I reference the encapsulating class variables? Check the code below for how I stop / start the file observer.
// Create the external media broadcast receiver.
mExternalMediaBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(final Context context, final Intent intent) {
// if action = media removed, stop the file observer.
EncapsulatingFragment.this.mFileObserver.stopWatching()
}
};
Is this valid?
Is this valid?
So long as the receiver has the same lifetime as EncapsulatingFragment.this, probably.
I want to pass parameters to a BroadcastReceiver. Can this be done? Even when the receiver is created dynamically?
Create an actual class and pass in the values to the constructor:
class WhateverReceiver extends BroadcastReceiver {
FileObserver mFileObserver;
WhateverReceiver(FileObserver observer) {
mFileObserver = observer;
}
#Override
public void onReceive(final Context context, final Intent intent) {
// if action = media removed, stop the file observer.
mFileObserver.stopWatching();
}
}
Then, in your fragment:
mExternalMediaBroadcastReceiver = new WhateverReceiver(mFileObserver);
All that being said... you might want to consider whether this logic should be implemented in your fragment. I/O-related stuff ideally lies outside of a fragment, such as in a repository object.
I had to implement a feature to this app which consists of an Activity and a Service working on the background (it implements Service, not IntentService).
I went through a few tutorials on the Internet that are supposed to work, and they all use LocalBroadcastManager, which by the way is the recommended by Android:
If you don't need to send broadcasts across applications, consider
using this class with LocalBroadcastManager instead of the more
general facilities described below.
I literally lost a day to find out the problem why it wouldn't work for me: it only works if I use Context.sendBroadcast(). and Context.registerReceiver() instead of the LocalBroadcastManager methods.
Now my app is working, but I feel I am going against the best practices, and I don't know why.
Any ideas why it could be happening?
EDIT:
After I wrote this question I went further on the problem. LocalBroadcastManager works through a Singleton, as we should call LocalBroadcastManager.getInstance(this).method(). I logged both instances (in the Activity and in the Service) and they have different memory addresses.
Now I came to another question, shouldn't a Service have the same Context as the Activity that called it? From this article a Service runs on the Main Thread, hence I'd think the Context would be
the same.
Any thoughts on that? (sorry for the long post)
Code samples:
MyService
public class MyService extends Service {
...
// When an event is triggered, sends a broadcast
Intent myIntent = new Intent(MainActivity.MY_INTENT);
myIntent.putExtra("myMsg","msg");
sendBroadcast(myIntent);
// Previously I was trying:
// LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(myIntent);
}
MyActivity
public class MainActivity {
...
private BroadcastReceiver messageReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Log.d("onReceive", "received!");
// TODO something
}
};
#Override
protected void onResume() {
super.onResume();
registerReceiver(messageReceiver, new IntentFilter(MY_INTENT));
// Previously I was trying:
// LocalBroadcastManager.getInstance(getApplicationContext()).registerReceiver(messageReceiver, new IntentFilter(MY_INTENT));
}
}
I've never used LocalBroadcastManager, but it sounds like you have to register your receiver on there (i.e. lbm.registerReceiver(...), not mycontext.registerReceiver(...)). Are you doing that?
Now I came to another question, shouldn't a Service have the same Context as the Activity that called it? From this article a Service runs on the Main Thread, hence I'd think the Context would be the same.
The Context class is not related to threads. In fact, both Service and Activity are (indirect) subclasses of Context -- so they're their own Contexts! That's why you can use "this" as a Context.
But regardless of which context you send into LocalBroadcastManager.getInstance(), you should be getting the exact same LBM instance out. I can't think of any reason that you wouldn't -- except if you're running the Activity and Service in different processes?
Declaration:
private BroadcastReceiver receiver;
Initialization:
receiver = new BroadcastReceiver()
{
#Override
public void onReceive(Context context, Intent intent)
{
//todo
}
};
Registration:
LocalBroadcastManager.getInstance(context).registerReceiver(receiver, new IntentFilter("RECEIVER_FILTER"));
context can be any type of Context, you can use the application context.
Unregister:
LocalBroadcastManager.getInstance(context).unregisterReceiver(receiver);
Broadcast:
Intent intent = new Intent("RECEIVER_FILTER");
intent.putExtra("EXTRA", someExtra);
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
check out if your Service and Activity are run in different process, LocalBroadcastManager can't apply in different process.(you should see it in AndroidManifest.xml file)
I have a Broadcastreceiver in my ReceiverApp, which I call from my SenderApp and this works fine.
I would like to call a method of the Activity in my ReceiverApp.
How can I do that with the following prerequisites ? :
The ReceiverApp was not started and dynamically registering the receiver is not possible.
I can't call the Receivers Mainactivity from my Sender, because I would like to prevent showing any ActivityScreen of the Receiver. The Sender should just call an ReceiverActivity method and proceed further, so the Senderscreen should be always on top.
I cant do the ReceiverActivity Method "static", because then I loose the context of the Activity. I need for example to fetch the Packagename of the Receiver with : this.getPackageName()
public class MyBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
// Extract data included in the Intent
CharSequence intentData = intent.getCharSequenceExtra("message");
Toast.makeText(context, "Say : "+intentData, Toast.LENGTH_LONG).show();
MainActivity.myMethod(); <<<<<--------
}
}
Any hint or help ?
By definition, what you want is impossible. If the activity does not exist, you cannot call methods on it.
Move your code to some common location that is accessible from both the receiver and the activity, such as a static method.
I cant do the ReceiverActivity Method "static", because then I loose the context of the Activity.
Pass a Context as a parameter to the method.
I need for example to fetch the Packagename of the Receiver with : this.getPackageName()
Call getPackageName() on the Context that is passed into onReceive().
I've a simple Main Activity which has to stop till an SMS is received... How can I launch a method from the MainActivity within the BroadcastReceiver's onReceive() Method?
Is there away with Signal and Wait? Can I pass something with a pending Intent, or how can I implement this communication?
Communication from BroadcastReceiver to Activity is touchy; what if the activity is already gone?
If I were you I'd set up a new BroadcastReceiver inside the Activity, which would receive a CLOSE message:
private BroadcastReceiver closeReceiver;
// ...
closeReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
//EDIT: receiving parameters
String value = getIntent().getStringExtra("name");
//... do something with value
finish();
}
};
registerReceiver(closeReceiver, new IntentFilter(CLOSE_ACTION));
Then from the SMS BroadcastReceiver you can send out this action:
Intent i = new Intent(CLOSE_ACTION);
i.putExtra("name", "value"); //EDIT: this passes a parameter to the receiver
context.sendBroadcast(i);
I hope this helps?
I had the exact same problem, I tried using intent but i was unsuccessful
The easiest way to use it would be using static methods and static variables
MainActivity.java
public static void stopsms()
{
/*
some code to stop the activity
*/
}
SMSReceiver.java
at the end call this function
MainActivity.stopsms();
It works amazing if your code does not affect when you use static methods and variables. Let me know if you need any help.
The problem with registering a second receiver within the activity, however, is that it will not be persistent like registering in the manifest... thus, although, this solution may work, will only work if the activity is running in background.
it's easy, use interface like that:
1) in your broadcast receiver create an interface.
public interface ChangeListener{
public void functionWhoSendData(String type);
public void etc();
}
and instantiate that interface in your broadcast receiver, use it:
public void onReceive(....
String data=functionWhereYouReceiveYouData();
ChangeListener.functionWhoSendData(data);
}
And in your activity, make it implements your interface
I basically want to make an intent and pass it to a service from my BroadcastReceiver's onReceive().
So far I always used View.getContext(), but here, I'm stuck.
How exactly can I get the context so I can use public Intent (Context packageContext, Class<?> cls)?
public abstract void onReceive(Context context, Intent intent)
onReceive gives you the context. What more do you want?
Well the Answer mentioned above is not of any use. You can use the context as long as you are in onReceive. once you code has returned from onReceive, the context is no longer existing.
So your problem statement say you wanted to start the service using this context in your intent creation and then calling startService with this context object. That cannot be done.
Read this what can and cannot be done in BroadcastReceiver context.
http://developer.android.com/reference/android/content/BroadcastReceiver.html
In the BroadcastReceiver the
onReceive(Context context, Intent intent)
method provides context
so
to start activity use
context.startActivity(intent);
and to start service use
context.startService(intent);