Not sure if service onDestroy is called from BroadcastReceiver - android

I have a service which I start using
Intent serviceIntent = new Intent(getActivity().getApplicationContext(), LocationService.class);
getActivity().startService(serviceIntent);
When app is going into background, not closed, just not in foreground: i.e. press home button, I do:
Notification notification = mBuilder.build();
service.startForeground(NOTIFICATION, notification);
To bring the service to the foreground and show ongoing notification.
I have a BroadcastReceiver which is fired when the notification's shut down action is clicked (added action to notification).
The BroadcastReceiver stops the service:
#Override
public void onReceive(Context context, Intent intent) {
Intent serviceIntent = new Intent(context.getApplicationContext(), LocationService.class);
context.stopService(serviceIntent);
}
Now, there are two scenarios:
When app goes to background but not closed!, when pulling down the notification bar and clicking the shut down action -> the service's onDestroy is called just fine. I can see Toast and Log messages from onDestroy.
When app is closed (swiped away from apps list), meaning only service is running, when pulling down the notification bar and clicking the shut down action -> it doesn't look like the service's onDestroy is called! The code over there is not executed, and I cant see Toast and Log messages from onDestroy.
However, it seems that the service does stop, because I can see the app removed from settings -> running apps after clicking the shut down.
So, is the service getting destroyed? and if so, why isn't the code in onDestroy gets executed?
How can I make sure onDestroy is called?
Obviously it has something to do with the fact that in "good" scenario, the app is still in the background, and in the "bad" scenario, the app is closed.
EDIT:
Thanks to CommonsWare's and John Leehey's comments, I understood that it could be that the "process is being terminated" and "there is no guarantee" that onDestory() will be called.
My onDestory looks like this:
#Override
public void onDestroy() {
super.onDestroy();
stopLocationUpdates();
googleApiClient.disconnect();
Foreground.get(this).removeListener(this);
// set default zoom
sharedPrefrencesManager.putFloat(getString(R.string.zoom_last_location_key), 15);
Log.i("test", "onDestroy");
}
Should I do the stuff like stopLocationUpdates(); and googleApiClient.disconnect(); in another place? since there is no guarantee of onDestory being called?

Related

Android: How to stop service when I click on my notification

Is there any way that when I click on the notification and then this notification can stop the service? And my notification is in my service.
Every time when I click on my notification, the activity will run onResume() method. I cannot stop this in this onResume() since I have another notification.
My app process is: a notification helps to tell the user it is now counting down the time, and when time is up, I will begin another notification to tell the user your time is up. So, I cannot stopservice before the "timeup" notification. My thought is, When the user click on "timeup" notification, then I can stop the service.
Can I do that?
The lifecycle of an application puts OnResume at the start of every launch, so the best method would be to assign a new request code to each new notification and give the one you wish to recognize an action. If the action is received, you can stop the service. If it is not, then the app will be able to differentiate that it is a different notification and respond accordingly.
...
Intent intent = new Intent(this, TARGET.class);
intent.setAction("CUSTOM_ACTION");
PendingIntent pIntent = PendingIntent.getService(this,
(int) System.currentTimeMillis(), intent,
PendingIntent.FLAG_UPDATE_CURRENT);
...
#Override
public void onResume(){
super.onResume();
if (getIntent().getAction().equals("CUSTOM_ACTION")) {
// kill service
} else {
// other stuff
}
}

Getting an activity to start as soon as Android app is in the foreground

I'm using a running service to detect whether network is available or not. When it is not available, it calls an activity to start that displays a blank screen with "no network available" on it. When the network is back, it sends a broadcast to finish this activity.
The only problem is that this activity may start at any time (as a popup), even when using other apps. I want it to start (or be visible) only if the network is out and my app is in the foreground. Any help?
One option would be to have your foreground activity register for the broadcast, and then display the relevant notification from within the activity.
Alternatively you could start your service when your foreground activity starts/resumes (i.e, onResume), and stop it when your activity leaves the foreground.
You can use START_STICKY in your service to ensure it stays around until you stop it, like so:
#Override
public int onStartCommand(Intent intent, int flags, int startId){
//On start work here
return START_STICKY;
}
and then stop the service using stopService when your activity leaves the foreground (i.e onPause).
If you need the former behaviour across multiple activities you can register broadcast receivers programmatically:
BroadcastReceiver myBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if(MY_ACTION.equals(intent.getAction()))
{
//show appropriate dialog
}
}
};
IntentFilter myIntentFilter = new IntentFilter();
myIntentFilter.addAction(MY_ACTION);
registerReceiver(myBroadcastReceiver,myIntentFilter);
You can unregister like so:
unregisterReceiver(myBroadcastReceiver);
You could extend Activity and make your own custom subclass that reuses similar code to register and unregister whilst entering/leaving the foreground. Or you can extract this into utility methods/classes and call from the appropriate places.
I think you need Shared Preference to do this. store one Boolean value on finish you activity (you can use onpause() or onStop()) and for showing popup check the value and do what you want
for understnding to use sharePreference see this and developer.android.com
Try the following:
Intent intent = new Intent(this, YourActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getApplicationContext().startActivity(intent);
This worked in the context of my own app already running, I'm not sure if it will start your app if it is not already running in the background
EDIT: Not sure if I understand your question entirely. If you only want this activity to come to the foreground while your app is in the foreground, get rid of the addFlags line, also you can do some boolean stuff to check if your app is in the foreground like so, this way your code won't even run if the app isn't in the foreground.
EDIT: There are a few ways to check if your app is in the foreground, the link I posted above has one such solution, another one is to create a static boolean isForeground variable: in the onResume() methods of your app set isForeground = true and in onPuase() set isForeground = false. This isn't the best practice, using ActivityManager is better, but for purposes of testing this should be ok.
Then have something like the following:
if(isForeground){
//Start your activity
}
This should be quick to write, if this is the behavior you want, I would recommend replacing the isForeground static variable with the test for foreground provided by ActivityManager in the link I posted.

How to stop a Service from running after user stops viewing applications Activities. Android

I have the following code in each of the 5 activities of my app. I wanted to keep the service running that is bound to these five activities. It will play music in the background. However when the user navigates away from the any of these five activities the Service should be killed. Using the code below I am able to get it so that the music plays in the background when navigating between the activities. but the Service keeps running after leaving the application. What is the best way to solve this problem? How about some creative ideas.
I put this Toast message in the onDestroy method of the service so I can tell when the service is stopped.
Toast.makeText(this, "My Service Destroyed", Toast.LENGTH_LONG).show();
I never see any Toast message pop up when I leave the application. The other toast messages do show to indicate that the service has started.
#Override
public void onPause() {
super.onPause();
unbindService(serviceConnection);
}
#Override
public void onResume() {
//After a pause OR at startup
super.onResume();
//add this to the onResume of the activity
// startService(new Intent(this, AudioService.class));
bindService(new Intent(this, AudioService.class),
serviceConnection, Context.BIND_AUTO_CREATE);
}
According to the documentation here:
Multiple clients can bind to the service at once. When a client is done interacting with the service, it calls unbindService() to unbind. Once there are no clients bound to the service, the system destroys the service.
So maybe you're missing some unbind in one of your activities. You can check this by printing a log in the onBind and onUnbind methods of your service.

Service called several times ending itself

I am starting a service with a click on a button :
Intent intent = new Intent(getActivity(), UploadService.class);
getActivity().startService(intent);
My apps makes it possible to launch several services.
I know that the first time, onCreate() is called, then if the services is running, onStartCommand() is called.
onStartCommand returns START_STICKY.
But I'm facing a strange behavior :
On the first click, the Service is called, onCreate() then onStartCommand()... etc.
On the second click, while the Service is still running, onStartCommand()... etc.
But when the first is finished, onDestroy() is called, while the second is still in progress... ?
How to avoid that?
Thanks
If you start the Service that is already running then onDestroy() of Service won't be called and the instance of Service already running will be brought to front but if your Service is finished/stopped explicitly then only its onDestroy() will be called.

AppWidget Update Service does not stop on Widget being Deleted from host

What I am trying to do is once the AppWidget is removed from the homescreen of the user's Android phone, I want to stop the background service that Updates the AppWidget.
Here is the code that I am using...don't understand whats wrong?
#Override
public void onDeleted(Context context, int[] appWidgetIds){
Intent serviceIntent = new Intent(context, UpdateService.class);
context.stopService(serviceIntent);
super.onDeleted(context, appWidgetIds);
}
Any ideas? Thanks for the help.
After a lot of Research I finally fixed it. My goal here was to stop the background service if all AppWidget instances are removed from the screen.
This is what did it...
Used shared preferences to toggle 1 and 0. SharePref toggled to 1 when the very first instance of the widget is put on the screen by the user. It is toggled back to 0 when the last instance of the App widget is removed from the screen.
#Override OnReceive method in the Service. Listen for these broadcasts - AppWidget Enabled (broadcast when the very first instance of the widget is put on the screen) , AppWidget Disabled (broadcast by the OS when the very last instance of the widget is removed from the screen)
When AppWidget Disabled is broadcast call the overridden method OnDisabled method.
3.In #Override OnDisabled method call stopService. Works perfect.
Remember the difference between OnDeleted and OnDisabled. OnDeleted is called when an instance of the widget is removed, it doesn't mean that the widget being deleted is the last one. I wanted my service to still run even if there was a single widget instance on the screen.
*Also if you do not want to do all of the above and let Android take care of the Service etc...use IntentService. **
I think the stopservice is calling onDestroy in the Service itselfs.
It works for me with the following code in the Service
#Override
public void onDestroy() {
super.onDestroy();
timer.cancel();
//Toast.makeText(this, "Service Destroyed", Toast.LENGTH_LONG).show();
}
timer ist the timer which i am starting in the _startService void

Categories

Resources