I have an android application which starts a service in the main activity with this command:
bindService(new Intent(ctx, MyService.class), _connection, Context.BIND_AUTO_CREATE);
The main activty does excatly nothing with this service (thats why I didnĀ“t provide the code for the Service connection). The idea is that the main activity handels the service lifetime!
It "stops" the service with this code after the user clicks the "close" button of my app:
if (_service != null) {
unbindService(_connection);
}
//Some cleanup here ...
System.exit(0);
I know at this point that no other activity is binded to the service cause every activity is called from the main activity and they unbind from the service at "onStop".
So the problem is that my Service wont call "onDestroy" when the user closes the app!
When I remove the "System.exit(0)" line it will close normally!
How can I make sure that the service is closed properly in this situation?
EDIT:
Ok I read this discussion: Is quitting an application frowned upon?.
Now I rebuild my activities. I have one activity that calls the service with startService, after that it binds the service. When the activity is destroyed it calls unbindService.
The service itself returns START_STICKY in onStartCommand to make it harder to kill it. It calls stopSelf when all work is done.
Now I have the problem that I get the ServiceConnectionLeaked message if the binding still exists! Whats about that? How could I prevent this?
Use finish() instead of System.exit(0)
Related
I built a class called MService extend Service in Android Studio , I started the service like this: - inside onClick associated with a button-
Intent serviceIntent = new Intent(getApplicationContext(), MService.class);
serviceIntent.putExtra("ID", "1");
startService(serviceIntent);
The Service onStartCommand method lunched and worked pretty good..
The problem is I don't know how to end the Service when a Button clicked, I tried to do this:
stopService(new Intent(getApplicationContext(), MService.class));
inside a onClick method , the onDestroy lunched, but the Service still running
How can I stop it?
inside a onClick method , the onDestroy lunched, but the Service still running
If onDestroy() of your service was called, then afterwards, the service is not running. Your code might still be running.
If you start things in a service, such as a background thread, it is your job to stop them and clean that up, typically in your onDestroy() method.
I am currently having a really weird issue, and I don't know what could be causing it. Every time I close the app by swiping it away, and then start it again, the app seems to be duplicating its output to logcat, or in other words, it appears to be running multiple times.
This doesn't happen when I am connected to Android Studio, but without a cable connection, it does it without fail.
In my main activity I start my service like this:
Intent intent = new Intent(this, BluetoothService.class);
startService(intent);
bindService(intent, bluetoothServiceConnection, Context.BIND_AUTO_CREATE);
Stopping the service:
unbindService(bluetoothServiceConnection);
Intent intent = new Intent(MainActivity.this, BluetoothService.class);
stopService(intent);
EDIT I have made some changes in the way I stop and start my service, which seems to have solved my problem on Android 5.1.1, but not on Android 4.4.4, sadly.
I was thinking that maybe my logging process could be the problem, but destroying that process in my activity's onDestroy()-method didn't solve the issue either.
Starting the logging process:
logger = Runtime.getRuntime().exec(new String[]{"logcat", "-v", "time", "-f", logcatFile.getAbsolutePath(), " *:E"});
Stopping it:
logger.destroy();
If you start a service, depends how you define your service in the AndroidManifest.xml, if you have android:process=":yourProcess", if the process name start with ":" it will create a new process, that probably your log output multiple times.
Your code doesn't contains any logging information, nor did you provide a stacktrace with it. Your splash screen doesn't seem to be the issue, but you should replace the new thread with a delayed post to a handler to the looper thread (main thread) you're running in:
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
Intent i = new Intent(getApplicationContext(), MainActivity.class);
startActivity(i);
finish();
}
}, 1500);
Instead of getApplicationContext() you could also use SplashActivity.this directly.
In your MainActivity you then need to make sure to unbind the service. Maybe also stop it, depending on what you need it for. Refer to Bound Services for more documentation and examples.
For making the Service terminate the documentation states
A service can be both started and have connections bound to it. In such a case, the system will keep the service running as long as either it is started or there are one or more connections to it with the Context.BIND_AUTO_CREATE flag. Once neither of these situations hold, the service's onDestroy() method is called and the service is effectively terminated.
That's why it works when the service isn't started at all. You try to stop the service in onDestroy() which is only called if the service is stopped. Your code looks like the service doesn't need to be started at all. But to do it correctly, just stop the service in the acivity's onDestroy() or utilize
onUnbind() or any other useful lifecycle event of the activity or service.
I don't know if this is possible, but I would like to do the next:
Imagine an app with 2 activities: MenuActivity and OtherPurposeActivity.
So, on the onCreate method of Menu I had run the Service. In the same Activity (Menu), I can easily "connect"(Edit: communicate) with this Service with no problems.
Then, I click the only button there is on MenuActivity, which starts OtherPurposeActivity. Here comes the question:
How can I connect to the Service I had run on MenuActivity? Is it possible? (I hadn't called stopService).
Thanks in advance.
Edit: Code:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_menu);
/* Execute service */
Log.d("SERVICE", "Launching service");
Intent msgIntent = new Intent(MenuActivity.this, ServerProcessingService.class);
msgIntent.setAction(ServerProcessingService.ACTION_STATUS);
startService(msgIntent);
/* Connection to the IntentService */
IntentFilter filter = new IntentFilter();
filter.addAction(ServerProcessingService.ACTION_STATUS);
//filter.addAction(ServerProcessingService.ACTION_CONTROL);
rcv = new ProgressReceiver();
registerReceiver(rcv, filter);
}
So I can handle the communication with the ProgressReceiver class. But, what if I open another activity, and this service still running? Can I access to it?
How can I connect to the Service I had run on MenuActivity?
Another activity that wants to communicate with the service can use exactly the same method as MenuActivity. startService() will only start the service if it is not already running, and then send the intent to onStartCommand() in all cases, so it is all right to call start service from multiple activities.
As a commenter pointed out, if your activity requires ongoing communication with a service, you should bind to it.
Is it possible? (I hadn't called stopService).
An IntentService will stop itself if it has no work to do, so it doesn't matter that you did not stop it explicitly. If the service needs to continue running, don't use an intent service.
To be on the same page I will describe briefly how I understood your dilemma.
You have an IntentService perfroming some operation which provides at the end some results. You are starting this process in one activity(asynchronously of course) and switch immediately to another one. Now, you are not sure whether service will finish the work before you switch to second Activity and result will be lost.
Basically, approach with BroadcastReceiver would be a good choice but if you won't register on time the data will be lost and service will end it's work. You could let the service to store the result before it ends, in DB, file or even in memory(depending on data type). When your second Activity start you can check if there is data waiting for you, if not you can wait for BroadcastReceiver to deliver it.
You could also use Otto library which is far more advanced solution than BroadcastReceiver. It allows to return to registered observer(Activity) the last result and what is more important it will allow your service to check if any observer received the message. If not you could only then store last result.
My question is as follows:
I started my intentService from my main Activity. This intentService does some audio processing with audioRecord.
However, when I need to start another activity in my application (recording video in this case), i need to stop the intentService in the background (because it is hogging the audio resource).
Is there a way to stop the intentService from the main activity?
You can use stopService() from your main activity like this:
stopService(new Intent(yourMainActivity.this,yourIntentService.class));
use the same pre-declared intent which you used to start the IntentService and call
stopService(intent);
if you create a new intent and use it to stop the service, the service will not respond to it until its finishes processing the previous intent.
but it should be noted that this will not immediately stop the service. So a workaround to this is to have a Global boolean variable. When its set to true the processing within the service will carry out, and when you want to end it set the boolean variable to false from your activity. and then you can stop the service from within itself by calling
stopSelf();
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.