I'm using FCM to get Messages and a receiver to broad cast messages to my receiver
receiver code:
public class MessageReceiver extends BroadcastReceiver {
private FCMInterface listener;
public MessageReceiver(FCMInterface listener){
this.listener = listener;
}
#Override
public void onReceive(Context context, Intent intent) {
}
}
I'm using an interface to connect my receiver to activity(activity implements the FCMInterface)
question is what happens if activity onDestroy calls and after that i call a function of my interface?
The method implemented in the class get called even after the onDestroy() method got called.
But you can no longer access the activity context or anything related to UI.
While setting up the broadcast receiver you should register and unregister on start() and stop() life cycle callbacks. failing to do so will give you memory leak exceptions.
In good android programming practices, you would normally try to avoid situations where you hold the references of objects which are related to the activity context after the onDestroy() has been called.
I think you should send intent to your activity (and set your activity singleTop or singleTask or SingleIntance if you need) instead of interface.
Related
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 want to call the activity method from broadcast receiver onReceive method which will be called once the alarm gets triggered.
Below is my Home Activity code snippet
public class HomeActivity extends Activity{
public static HomeActivity mHomeActivity = null;
protected void onCreate(Bundle savedInstanceState) {
}
public void startLocationReporting(){
...........//Logic to start the location reporting
}
public void stopLocationReporting(){
...........//Logic to stopthe location reporting
}
}
Below Broadcast receiver will be triggered based on the alarm we configured
public class AlarmReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
// Here context is application context not an HomeActivity instance
//Below code works fine when the app is in foreground
if (HomeActivity.mHomeActivity != null) {
HomeActivity.mHomeActivity.startLocationReporting();
}
//Static references are cleared once the app quits.
//How to start location reporting when the app is quitted
}
}
Please help me on this.
How to the call the methods of an Activity from broadcast receiver
once the app is quited?
Calling methods from class by creating object of class which extends Activity class will cause following major issues:
1. token android.os.BinderProxy#43756de8 is not valid; is your activity running? when trying to accessing any service using Activity context with is not running
2. NullPointerException when accessing views in calling methods.
or may other issues are also possible...
Try to implement logic using IntentService :
A. Create separate class with startLocationReporting and stopLocationReporting by passing all required parameters.
By doing this you will access both methods from Activity or from any other components
B. Create a IntentService for doing task and start it when onReceive method called. By this application will do long running task in background so call startLocationReporting and stopLocationReporting by passing all required parameters in IntentService
On receiving a certain event in my Android service, I want to terminate the app from within the service. I know I can call finish in an activity to end it.
Also I understand that service will call stopSelf() on itself to end itself. But I need to terminate the entire app including any particular activity of the app that was visible at that time.
Any ideas?
Try this:
Process.killProcess(Process.myPid());
You can create an BaseActivity with BroadcastReceiver to close all Activities by registering it in onCreate() of BaseActivity and extending all your Activities with BaseActivity.
public static final String EXIT_APP_ACTION = "EXIT_APP_ACTION";
BroadcastReceiver ExitAppBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
finish();
}
};
Register it in onCreate() for the BaseActivity in your Application using,
registerReceiver(ExitAppBroadcastReceiver, new IntentFilter(EXIT_APP_ACTION));
Then you can fire this BroadcastReceiver from your Service using the Context to close all Activites including Service by calling stofSelf(),
stopSelf()
context.sendBroadcast(new Intent(BaseActivity.EXIT_APP_ACTION));
I'm a newbie of Android. I would like to know from a more experienced programmer if I'm doing well. Inside an activity I declare a BroadcastReceiver in this way:
private BroadcastReceiver locationUpdateReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
//Do something
}
}
};
I register the receiver onResume() and unregister it onPause(). Could I run in memory leaks?
If no, would be the same if I declare a non-static inner class that extends BroadcastReceiver and I used it inside the activity, always registering and unregistering as before? (I suppose that in this way I control its life-cycle).
Thanks in advance.
Doing so will not cause any memory leak.
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