onDestroy() callback of Service - android

In my Android project, I have a normal Service:
public class MyService extends Service{
#Override
public int onStartCommand(...){...}
...
#Override
public void onDestroy() {
super.onDestroy();
Log.d("MyApp","MyService onDestroy() is called!");
}
}
In my BroadcastReceiver class, I stop MyService & do another task :
public static class MyReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
context.stopService(new Intent(context, MyService.class));
doAnotherTask();
}
}
According to my log, onDestroy() of MyService is executed after doAnotherTask() is done.
How can I guarantee that onDestory() of MyService is executed before doAnotherTask() get called?
P.S.: I thought I could do something like:
boolean isStopped = context.stopService(new Intent(context, MyService.class));
if(isStopped){
doAnotherTask();
}
But it could be possible that there is no service has been started, which means stopService(...) does nothing. So, I can't rely on my above code.

call startActivityForResult() .... and after you got the onActivityResult,.... call your method doAnotherTask()
i think that will do the job

How about sending a special intent to your broadcast receiver from the onDestroy() function? When your receiver gets it, then call doAnotherTask(). (I am assuming that you can't simply call doAnotherTask() from onDestroy() directly.)

send a broadcast in the service's onDestroy function and in it's observer do your after things

The call to stopService() is asynchronous. You are basically telling Android that you want it to stop the Service. You have no control over when this actually occurs.
If you need to trigger something AFTER the Service is destroyed, then you send a broadcast Intent in MyService.onDestroy() and use that to trigger whatever you want to happen when the Service is destroyed.

Related

Destroy & re-create Service in my case

In my activity, I start my service in onStart() of my activity & bind to service in onResume() :
public class MyActivity extends Activity{
private boolean isBound;
ServiceConnection myConnection = new ServiceConnection(){...};
#Override
public void onStart(){
super.onStart();
startService(new Intent(this, MyService.class));
}
#Override
public void onResume(){
super.onResume();
Intent service = new Intent(this, MyService.class);
isBound = bindService(service, myConnection, Context.BIND_AUTO_CREATE);
}
}
I have a BroadcastReceiver class , in its onReceive() callback, I want to re-start my service. I mean destroy it completely & creat it by calling startService() again:
public class MyBroadcastReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
//I want to re-start MyService from scratch, i.e. destroy it & start it (create it) again
Intent service = new Intent(context, MyService.class);
stopService(service);
startService(service);
}
}
But as Android document says, my above code doesn't guarantee the previous started service will be destroyed since I have also bind to it.
My question is what is the most efficient way to unbind MyService in MyBroadcastReceiver to restart MyService from scratch? As you see, the bound myConnection instance is in MyActivity...
From the Service documentation:
Multiple clients can connect to the service at once. However, the
system calls your service's onBind() method to retrieve the IBinder
only when the first client binds. The system then delivers the same
IBinder to any additional clients that bind, without calling onBind()
again.
When the last client unbinds from the service, the system destroys the
service (unless the service was also started by startService()).
So, when using your service, don't start your service using startService(intent), but rather by called bindService(service, conn, flags). This way, if your Activity is the only activity bound to the service, when you call unbindService(ServiceConnection conn) the system will kill your service, then you can rebind afterwards.

Android - How can I check the sender class of the "stopService" Intent?

I stop a service from various places. How can I check when the sender of the command "stopService(Intent intent)" was my NetworkReceivar class (extends BroadcastReceiver)??
This is my code for do this more clear:
public class NetworkReceiver extends BroadcastReceiver{
public void onReceive(Context context, Intent intent) {
boolean isNetworkDown = intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
if (isNetworkDown) {
context.stopService(new Intent(context, MyService.class));
}
My service class:
public void onDestroy() {
Log.i(TAG, "OnDestroy");
// if came from NetworkReceiver do something.
this.updater.interrupt();
this.updater = null;
super.onDestroy();
}
How can I check when the sender of the command "stopService(Intent intent)" was my NetworkReceivar class (extends BroadcastReceiver)??
AFAIK, you can't.
However, instead of stopService(), you could call startService(), sending over a command that your service interprets as "time to shut down". Something on that Intent that is your command could be used to indicate the sender, so that you can distinguish one sender from another. And, the service can call stopSelf() to shut itself down.

stop IntentService from Activity

I need help with this situation:
I have activity, what starts IntentService.
Service do some job in while cycle and sleep for some time.
Main cycle of service is endless, so I need to stop it from activity again.
I must be able to end activity, start it again and stop IntentService from new "instance" of activity.
public class MyService extends IntentService {
public MyService()
{
super("MyService");
}
public MyService(String name) {
super(name);
}
#Override
protected void onHandleIntent(Intent intent) {
Log.d("SERVICE", "start");
while(true)
{
SystemClock.sleep(1000);
Log.d("SERVICE", "tick");
}
}
#Override
public void onDestroy() {
Log.d("SERVICE", "end");
super.onDestroy();
}
...
Intent intent = new Intent(getApplicationContext(), MyService.class);
startService(intent);
I tried calling stopService(), but it's not working. Is there any solution how to do this?
Thanks in advance.
Service do some job in while cycle and sleep for some time.
IMHO, this is an inappropriate use of IntentService. Please create a regular Service, with your own background thread that you manage yourself.
Is there any solution how to do this?
Create a regular Service, with your own background thread that you manage yourself. For example, you could use a ScheduledExecutorService instead of your sleep() loop, using shutdown() or shutdownNow() in the service's onDestroy().

Broadcast Receiver in IntentService (Service has leaked IntentReceiver)

I try to implement an IntentService with a BroadcastReceiver that reacts on the SCAN_RESULTS_AVAILABLE_ACTION.
The IntentService is supposed to compare Lists whenever onReceive is called. I always get the
"Service has leaked IntentReceiver"
error even though I unregister the BroadcastReceiver in onDestroy().
Here is the code:
public class MyClass extends IntentService {
private HashMap<String, List<String>>;
private WifiManager mWifiManager;
private WifiReceiver mWifiReceiver;
public MyClass() {
super("MyClass");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
mWifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
mWifiReceiver = new WifiReceiver();
registerReceiver(mWifiReceiver, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
mWifiManager.createWifiLock(WifiManager.WIFI_MODE_SCAN_ONLY,"ScanLock");
mWifiManager.setWifiEnabled(true);
return START_NOT_STICKY;
}
#Override
public void onDestroy(){
unregisterReceiver(mWifiReceiver);
mWifiManager.setWifiEnabled(false);
}
#Override
protected void onHandleIntent(Intent intent) {
// TODO Auto-generated method stub
}
class WifiReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
//Here I do my stuff with the scan results
//should be called every 5 seconds
}
}
Where is the problem in the code?
Why do I keep getting this error?
I still have to learn a lot about Android, but I think the IntentService is the right way to go since I do not expect any result from this class. It should just stop when I send a call stopService(). This IntentService is called by another IntentService! Is that a problem?
Thanks for helping.
I try to implement an IntentService with a BroadcastReceiver that reacts on the SCAN_RESULTS_AVAILABLE_ACTION.
This is largely pointless. Your receiver will be registered for a few seconds at most, hopefully.
I still have to learn a lot about Android, but I think the IntentService is the right way to go since I do not expect any result from this class.
That makes no sense whatsoever. You use an IntentService when you have a short bit of work that needs to be performed in a background thread. For example, if you use AlarmManager to check for new email messages every 15 minutes, or you have an activity kick off a large file download, you would use IntentService.
It should just stop when I send a call stopService().
You never call stopService() on an IntentService. The IntentService stops itself once onHandleIntent() returns. This is why your BroadcastReceiver will be removed within seconds -- your onHandleIntent() should only be running for seconds.
This IntentService is called by another IntentService!
This is unlikely to be a good design.
Try registering BroadcastReceiver in OnCreate() instead of OnStartCommand(),
That should fix your problem.

Where to register a BroadcastReceiver (Activity lifecycle fun)

Where's the right place to register/unregister an intent receiver in an Activity? Usually I would put stuff like this here:
class MyActivity
{
private BroadcastReceiver mMyReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Log.v(TAG, "Do something.");
}
};
#Override
public void onResume() {
super.onResume();
registerReceiver(mMyReceiver, new IntentFilter(...));
}
#Override
public void onPause() {
super.onPause();
unregisterReceiver(mMyReceiver);
}
}
The problem is that my activity can then no longer respond to the broadcast if it happens while it's in the pause state. Where's the right place to do something like this then?
Thanks
I think the following link might be useful to you
http://android-journey.blogspot.com/2010/01/android-braodcast-receivers.html
This should work in your case:
Unregister in onDestroy().
I think in your case, you can register the receiver in the onCreate() and unregister in the onDestroy(). This will keep it registered, even after it's been paused, until the activity is destroyed.
I had the reverse problem. I had originally registered my receivers in the onCreate() and when my activity was paused, I still got logs that it was receiving broadcasts. I moved it to the onResume, as you have, and that problem went away.

Categories

Resources