Is my Activity 'active'? [duplicate] - android

This question already has answers here:
Checking if an Android application is running in the background
(35 answers)
Closed 5 years ago.
My app consists of just one activity (launchMode=singleTask) with a viewpager in it. In the app, the user schedules alarms through the AlarmManager. When these alarms are triggered, a broadcast receiver creates notifications in the status bar (wether the app is open or not).
I'd like to update a RecyclerView in the activity whenever a notification is issued AND THE ACTIVITY IS IN THE FOREGROUND. If the activity is in the background or not 'active' at all (doesn't exist), there's no need to call it to the front or open it just to update the RecyclerView.
How can I check if my activity exists before calling, say, "MyActivity.updateMyRecyclerView()"? (I have an idea on how to check if it's in the foreground or not, I think that wouldn't be a problem.)

You can use broadcast receiver for your activity. You can send a broadcast and if your activity is 'alive' and is registered to receive the broadcast you can trigger the recyclerView update from there.
Send the broadcast when you are creating the notification like this
Intent intent = new Intent("key_to_identify_the_broadcast");
Bundle bundle = new Bundle();
bundle.putBoolean("updateRecyclerView",true);
intent.putExtra("bundle_key_for_intent", bundle);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
and in your Activity where you want to receive this intent, you can use a broadcast receiver
private final BroadcastReceiver mHandleMessageReceiver = new
BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Bundle bundle =
intent.getExtras().getBundle("bundle_key_for_intent");
if(bundle!=null){
boolean shouldRefresh = bundle.getBoolean("updateRecyclerView");
if(shouldRefresh){
//Refresh your recyclerView
}
}
}
};
You need to register and unregister the receiver to work
In your onResume method you can register this receiver to receive the broadcast
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
IntentFilter filter = new IntentFilter("key_to_identify_the_broadcast");
LocalBroadcastManager.getInstance(this)
.registerReceiver(mHandleMessageReceiver,filter);
}
You also need to unregister it before your activity gets paused
#Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
try {
LocalBroadcastManager.getInstance(this)
.unregisterReceiver(mHandleMessageReceiver);
} catch (Exception e) {
Log.e("UnRegister Error", "> " + e.getMessage());
}
}

Related

Closing running Application from BroadcastReceiver

In my App, there is a condition which check every day and if it gets true then I want my App get close in between the run like a crash and stack also gets clear .
I have try and tested many solutions but didn't find the one that works the way i wanted .
My BroadcastReceiver:
public void onReceive(Context context, Intent intent) {
PreferenceForApp prefs = new PreferenceForApp(context);
Bundle bundle = intent.getExtras();
if (bundle!=null){
if(bundle.containsKey("exception")) {
// String e = bundle.getString("exception")
if(bundle.get("exception").toString().equalsIgnoreCase("http request failed with error_msg No Match Found")) {
prefs.setIsDeviceValidated(false);
prefs.setIsLogIn(false);
Log.i("Time", "Exception Occur");
Intent CSPIntent=new Intent(context,CSPLoginActivity.class);
CSPIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TOP);
CSPIntent.putExtra("close_activity", true);
Log.i("Time", "IntentExit");
context.startActivity(CSPIntent);
}
}
}
}
}
And code to finish in an Activity I am calling from broadcastReceiver:
if (getIntent().getBooleanExtra("close_activity",false)) {
Log.i("Time", "ExitCSPLogin");
this.finish();
}
This code is not closing App in between the run.
You need to register BroadcastReceiver in your activity and send broadcast to BroadcastReceiver when you want to close application.
In your Activity try this:
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("com.package.ACTION_CLOSE");;
BroadcastReceiver Receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
finish();
}
};
registerReceiver(Receiver, intentFilter);
in onDestroy() method of you Activity unregister BroadcastReceiver:
#Override
protected void onDestroy() {
unregisterReceiver(Receiver);
super.onDestroy();
}
Now when you want close application send broadcast to BroadcastReceiver:
Intent broadcastIntent = new Intent();
broadcastIntent.setAction("com.package.ACTION_CLOSE");
sendBroadcast(broadcastIntent);
Hope this helps!
you have to check below condition in your app's mainActivity's onCreate method every time when user enter in your app. or in onResume if you want to to close your app immediately
if (!prefs.getIsDeviceValidated()) {
Log.i("Time", "ExitCSPLogin");
this.finish();
}
i assume you have more then one activity in your app, so insted of check above flag in every activity we 'll put it in main activity. allow user to use your app until he/she come at mainActivity
Note: create Broadcast Receiver for your App(add in manifest), not for specific activity

onReceive called many times

I have a service that get data from an other application.
When I get date I send message to broadCast in order to refresh the UI.
The onReceive method is called many times and data displayed multiple times.
this is my code:
DataService.java
if(sizeLat == 1) {
sendMessage("Alerte1;");
}
else {
sendMessage("Alerte2;");
}
private void sendMessage(String message) {
Log.w("","==> send message");
Intent intent = new Intent("my-event");
// add data
intent.putExtra("message", message);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
MainActivity.java
// handler for received Intents for the "my-event" event
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Log.e("","Onreceiver");
String message = intent.getStringExtra("message");
if(message.equals("Alerte1")){
parentItems.add(message);
adapter.notifyDataSetChanged();
}}};
#Override
protected void onResume() {
Log.d(TAG, "On Resume");
super.onResume();
// Register mMessageReceiver to receive messages.
LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver,
new IntentFilter("my-event"));}
How can I resolve the problem ?
Put broadcast register line in onCreate and unregister it in onDestroy() method. The line which you have to move from onResume() to onCreate is:-
LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver,
new IntentFilter("my-event"));}
Possibly, you have two instances of the activity living at the same time. Make a breakpoint on the message receiver and check the address of the instance of your activity class and see if they are different each time the onReceive is called.
There are a few reasons why you could have two instances living at the same time, but one of the most common is leaking context within the activity.
More on this topic.
I fixed same problem by unregister BroadcastReceiver in onPause method
LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver,new IntentFilter("my-event")));
Register it in OnResume Method
LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver,
new IntentFilter("my-event"));}

BroadcastReceiver lifecycle

1) I have an Activity. This Activity starts a service, which in turn creates and registers a BroadcastReceiver.
2) I have an Activity. This Activity creates and registers a BroadcastReceiver.
When does BroadcastReceiver's life end in each of the above cases? In other words - when it gets destroyed and won't listen to broadcasts anymore?
Declare broadcast receiver in manifest to achieve independent life cycle for it.
http://developer.android.com/reference/android/content/BroadcastReceiver.html
Only onReceive() method is called in BroadcastReciver's life cycle.
A BroadcastReciever life cycle ends (ie stop receiving broadcast) when you unregister it. usually you would do this in the onPause/onStop method. but it's up to you technically.
Example:
#Override
public void onResume() {
super.onResume();
// Register mMessageReceiver to receive messages.
LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver,
new IntentFilter("my-event"));
}
// handler for received Intents for the "my-event" event
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// Extract data included in the Intent
String message = intent.getStringExtra("message");
Log.d("receiver", "Got message: " + message);
}
};
#Override
protected void onPause() {
// Unregister since the activity is not visible
LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver);
super.onPause();
}

sending broadcasts to activity having google map register/unregister best places?

My Application has a main screen containing a map ,it also contains several other screens And around 3 services sending broadcast updates to the map(polylines , markers ...).
the map updated by broadcasts from the services
for register/unregister of the broadcasts i have two options :
1-register/unregister broadcast on onPause/onResume
PROS :only when the map is visible it can receives updates
CONS:when the map goes to the background and there are several updates i will need to do them all onResume which can cause some slowness in the application
2-register/unregister broadcast on onCreate/onDestroy
PROS:the map is always up to date regardless of which screen you are in
CONS:i am not sure if this will cause memory problems or any other unforeseen issues
As for the fact that the onDestroy might not be called for sometime i already took that in to consideration , and designed the application in a way that if "the application" not in foreground anymore it will shutdown all the services after 30 sec.
what is the best way to handle this ?
The LocalBroadcastManager class is used to register for and send broadcasts of Intents to local objects within your process. This is faster and more secure as your events don't leave your application.
The following example shows an activity which registers for a customer event called my-event.
#Override
public void onResume() {
super.onResume();
// Register mMessageReceiver to receive messages.
LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver,
new IntentFilter("my-event"));
}
// handler for received Intents for the "my-event" event
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// Extract data included in the Intent
String message = intent.getStringExtra("message");
Log.d("receiver", "Got message: " + message);
}
};
#Override
protected void onPause() {
// Unregister since the activity is not visible
LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver);
super.onPause();
}
// This method is assigned to button in the layout
// via the onClick property
public void onClick(View view) {
sendMessage();
}
// Send an Intent with an action named "my-event".
private void sendMessage() {
Intent intent = new Intent("my-event");
// add data
intent.putExtra("message", "data");
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}

refreshing and reloading an Activity from a Service without exiting the Activity, Android appwidget

Good day, I have an activity which i navigate to from an icon on an appwidget using pending Intents. Everything is being done in a service class. Now, the activity has a refresh button which when pressed, it sends an intent that calls the onStart() method on the service to update itself and perform some web operations. How do i go about reflecting the changes that could have occurred from the service in the activity without temporarily existing the activity.
Service to Activity:
if(intent.getExtras()!= null){
appWidgetId = intent.getExtras().getInt(AppWidgetManager.EXTRA_APPWIDGET_ID);
//if i get this action from my detailedinfo class add a boolean to it
if(intent.getAction() == refresh_action){
// boolean variable to hold condition
my_action = true;
}
Intent forecast = new Intent(this,detailedInfo.class );
forecast.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
forecast.putExtra("cityname", city);
PendingIntent forecastIntent = PendingIntent.getActivity(this, 0, forecast, 0);
/*onclick to go to detailedInfo class*/
remoteView.setOnClickPendingIntent(R.id.city_image_id, forecastIntent);
if(my_action == true){
//Log.d(TAG, "my_action is true, performing pending intent");
try {
forecastIntent.send(this, 0, forecast);
} catch (CanceledException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
And in the Activity class:
Intent service = new Intent(this, cityService.class);
service.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
service.setAction(refresh_action);
Uri data = Uri.withAppendedPath(Uri.parse(CityWidgetProvider.URI_SCHEME + "://widget/id/"), String.valueOf(appWidgetId));
service.setData(data);
startService(service);
I tried adding a setAction() method to the intent that calls the service and then use the same pendingIntent(even though i think is a long shot) but they seems to be ignored. Please how do i go about this and what could i have been doing wrong.? As usual any help is highly appreciated. Thank you.
I'm not 100% clear on what you're trying to do, but the easiest thing to do would be to register a BroadcastReceiver in your Activity onResume (remove it in onPause). When the service is done with whatever it needs to do, broadcast that info.
In the Activity
public static final String ACTION_STRING = "THE_BIG_ACTION";
private BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// Do whatever you want here
Toast.makeText(getApplicationContext(), "received", Toast.LENGTH_SHORT);
}
};
#Override
protected void onResume() {
super.onResume();
registerReceiver(receiver, new IntentFilter(ACTION_STRING));
}
#Override
protected void onPause() {
super.onPause();
unregisterReceiver(receiver);
}
In the service, when you're done, just call...
sendBroadcast(new Intent(YourActivityClass.ACTION_STRING));
If you want to include some data, just put it in the intent like you would when starting an Activity.
If your Activity is off screen when the service completes, and the user goes back to it, you'll have missed the notification. That's a different issue to resolve.

Categories

Resources