I currently have a Service that runs fine when I start it but when I try to stop it using the stopService method its onDestroy method doesn't get called.
Here is the code I use to try to stop the Service
stop_Scan_Button = (Button)findViewById(R.id.stopScanButton);
stop_Scan_Button.setOnClickListener(new View.OnClickListener(){
public void onClick(View v){
Log.d("DEBUGSERVICE", "Stop Button pressed");
Intent service = new Intent(CiceroEngine. CICERO_SERVICE);
releaseBind();
Log.d("Stop_Scan_Button", "Service: " + service.toString());
stopService(service);
Log.d("Stop_Scan_Button", "Service should stop! ");
}
});
Am I right in thinking that when stopService is used it calls the onDestroy method of the Service? When I press my stop scan button the onDestroy() method in my Service is not called.
Is there anything else I am missing that I should put in to stop the service?
EDIT: to add onServiceConnected() gets called when stopService is run instead of onServiceDisconnected(), why would that be happening?
EDIT:To add more info regards Binding
I call bindService in the onCreate() method and I then have the releaseBind() method unbind the Service.
Here is the code for that method:
public void releaseBind(){
unbindService(this);
}
So I presume that the unbinding is not my problem?
I am going to guess that your having a method call for releaseBind() means that you previously called bindService() on this service and that releaseBind() is calling unbindService(). If my guess is incorrect, please ignore this answer.
A service will shut down after all bindService() calls have had their corresponding unbindService() calls. If there are no bound clients, then the service will also need stopService() if and only if somebody called startService() on the service.
So, there are a few possibilities here:
You still have bound clients (e.g., other activities), in which case you cannot stop the service until they unbind
Since both unbindService() and stopService() are asynchronous, something might be going haywire with the timing, in which case you may get better luck if you call stopService() from your ServiceConnection's onServiceDisconnected() method
Also, bear in mind that the exact timing of the service being destroyed is up to Android and may not be immediate. So, for example, if you are relying upon onDestroy() to cause your service to stop some work that is being done, consider using another trigger for that (e.g., activity calling a stopDoingStuff() method through the service binder interface).
Are all your bindings closed?
A service can be used in two
ways. The two modes are not
entirely
separate. You can bind to a service
that was started with startService().
For example, a background music
service could be started by calling
startService() with an Intent object
that identifies the music to play.
Only later, possibly when the user
wants to exercise some control over
the player or get information about
the current song, would an activity
establish a connection to the service
by calling bindService(). In cases
like this, stopService() will not
actually stop the service until the
last binding is closed
.
hai guys sorry for the late answer but as far as i know i have successfull stop the service in this code: you may check a link here.
public void onClick(View src) {
switch (src.getId()) {
case R.id.buttonStart:
Log.d(TAG, "onClick: starting srvice");
startService(new Intent(this, MyService.class));
break;
case R.id.buttonStop:
Log.d(TAG, "onClick: stopping srvice");
stopService(new Intent(this, MyService.class));
break;
}
}
and in services class:
public class MyService extends Service {
private static final String TAG = "MyService";
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
Toast.makeText(this, "My Service Created", Toast.LENGTH_LONG).show();
Log.d(TAG, "onCreate");
}
#Override
public void onDestroy() {
Toast.makeText(this, "My Service Stopped", Toast.LENGTH_LONG).show();
Log.d(TAG, "onDestroy");
}
#Override
public void onStart(Intent intent, int startid) {
Toast.makeText(this, "My Service Started", Toast.LENGTH_LONG).show();
Log.d(TAG, "onStart");
}
}
Related
I use services to play background music in all activities and it works. The problem is the music continues playing even if my app is in background (when user exit with home button or back button). How can I solve this?
Services class BackgroundSoundService
public class BackgroundSoundService extends Service {
private static final String TAG = null;
MediaPlayer player;
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
player = MediaPlayer.create(this, R.raw.slow_shock);
player.setLooping(true); // Set looping
player.setVolume(100,100);
}
public int onStartCommand(Intent intent, int flags, int startId) {
player.start();
return START_NOT_STICKY;
}
public void onStart(Intent intent, int startId) {
// TO DO
}
public IBinder onUnBind(Intent arg0) {
// TO DO Auto-generated method
return null;
}
public void onStop() {
}
public void onPause() {
}
#Override
public void onDestroy() {
player.stop();
player.release();
}
#Override
public void onLowMemory() {
}
}
Starting with
Intent svc = new Intent(this, BackgroundSoundService.class);
startService(svc);
Android Manifest:
<service android:enabled="true" android:name=".BackgroundSoundService" />
This is happened because the Service is still bounded in the activity. To terminate the service when multiple activity is bound to the service, you need to unbind the service from all of them as in the documentation says:
The service lifecycle—from when it's created to when it's
destroyed—can follow either of these two paths:
A started service
The service is created when another component calls startService().
The service then runs indefinitely and must stop itself by calling
stopSelf(). Another component can also stop the service by calling
stopService(). When the service is stopped, the system destroys it.
A bound service
The service is created when another component (a client) calls
bindService(). The client then communicates with the service through
an IBinder interface. The client can close the connection by calling
unbindService(). Multiple clients can bind to the same service and
when all of them unbind, the system destroys the service. The service
does not need to stop itself.
These two paths are not entirely separate. You can bind to a service
that is already started with startService(). For example, you can
start a background music service by calling startService() with an
Intent that identifies the music to play. Later, possibly when the
user wants to exercise some control over the player or get information
about the current song, an activity can bind to the service by calling
bindService(). In cases such as this, stopService() or stopSelf()
doesn't actually stop the service until all of the clients unbind.
Then call Context.stopService() to stop it:
context.stopService(new Intent(context, BackgroundSoundService.class));
I am starting and stopping a service from an activity calling startSertice()/stopService() (when user select/deselect a check box and service is not bounded). Every thing is working fine even though the activity that starts the service is closed. In "Running apps" I'm able to see 1 processes, 1 service running. But when I kill the application, using Task manager kind of application, the process is getting killed and service is not working though the running apps showing 0 processes, 1 service. How to make the service working in such situations? I observed the same in some other security applications like Avast with 0 processes, 1 service, while service working properly. Please help me out on this.
Following is the activity on click method
#Override
public void onClick(View arg0) {
boolean value = checkBox.isChecked();
if(value){
// start the service
startService(new Intent(this, MyService.class));
Toast.makeText(this, "Background service started", Toast.LENGTH_SHORT).show();
} else {
stopService(new Intent(this, MyService.class));
Toast.makeText(this, "Background service stopped", Toast.LENGTH_SHORT).show();
}
}
Following is the service class:
public class MyService extends Service{
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate(){
super.onCreate();
Log.d("######Service","Service created successfully");
}
#Override
public int onStartCommand(Intent intent, int flags, int stardId){
Log.d("######Service","Service started successfully");
IntentFilter powerButtonIntentFilter = new IntentFilter();
powerButtonIntentFilter.addAction("android.intent.action.SCREEN_ON");
this.registerReceiver(pbReceiver, powerButtonIntentFilter);
Log.d("#######","Power button register registered");
return START_STICKY;
}
#Override
public void onDestroy(){
Log.d("######Service","Service destroyed successfully");
this.unregisterReceiver(pbReceiver);
Log.d("#######","Power button register un-registered");
super.onDestroy();
}
}
Everything is working fine in ideal case. SCREEN ON action is being listened by the broadcast receiver properly even when the activity that starts the service is closed. I am able to see the app running in settings. But when I force kill the process using Task Manager kind of applications, processes is getting killed and in running apps I am able to see 0 process, 1 service running. Though the service is running after force killing the app from Task manager, broadcast receiver is not listening to the SCREEN ON action. Please help me out on this.
Thanks, JK
I was going through the services documentation in android when I noticed two contradicting points:
In the services document it is specified in Managing the Lifecycle of a Service
These two paths are not entirely separate. That is, you can bind to a
service that was already started with startService(). For example, a
background music service could be started by calling startService()
with an Intent that identifies the music to play. Later, possibly when
the user wants to exercise some control over the player or get
information about the current song, an activity can bind to the
service by calling bindService(). In cases like this, stopService() or
stopSelf() does not actually stop the service until all clients
unbind.
But in the document about bound services in Managing the Lifecycle of a Bound Service
However, if you choose to implement the onStartCommand() callback
method, then you must explicitly stop the service, because the service
is now considered to be started. In this case, the service runs until
the service stops itself with stopSelf() or another component calls
stopService(), regardless of whether it is bound to any clients.
It may be me but I think the statements are contradictory.Could anyone please clarify...
Agree that the documentation could be clearer. What they are trying to say is:
If you call startService(), then the service will keep running unless and until you call stopSerivce() (or stopSelf() from within the service)
If you call bindService(), then the service will keep running unless and until you call unbindService()
Therefore, if you call both startService() and bindService(), then the service will keep running until you call both stopService and unbindService(). Neither on its own will stop the service.
Created a very simple Activity and Service and ran the following sequences of start/stop/bind/unbind. I observed that the calls gave the following results.
bind-unbind
bindService() caused:
onCreate()
onBind()
unbindService() caused:
onUnbind()
onDestroy()
start-bind-unbind-stop
startService() caused:
onCreate()
onStartCommand()
bindService() caused:
onBind()
unbindService() caused:
onUnbind()
stopService() caused:
onDestroy()
start-bind-stop-unbind
startService() caused:
onCreate()
onStartCommand()
bindService() caused:
onBind()
stopService() caused:
-- nothing
unbindService() caused:
onUnbind()
onDestroy()
bind-start-stop-unbind
bindService() caused:
onCreate()
onBind()
startService() caused:
onStartCommand()
stopService() caused:
-- nothing -- still running
unbindService() caused:
onUnbind()
onDestroy()
bind-start-unbind-stop
bindService() caused:
onCreate()
onBind()
startService() caused:
onStartCommand()
unbindService() caused:
onUnbind()
stopService() caused:
onDestroy()
As you can see, in each case where both bind and start were called, the service kept running until both unbind and stop were called. The sequence of unbind/stop is not important.
Here is the example code that was called from separate buttons in my simple test app:
public void onBindBtnClick(View view) {
Intent intent = new Intent(MainActivity.this, ExampleService.class);
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
}
public void onUnbindBtnClick(View view) {
if (serviceIsBound) {
unbindService(serviceConnection);
serviceIsBound = false;
}
}
public void onStartBtnClick(View view) {
Intent intent = new Intent(MainActivity.this, ExampleService.class);
startService(intent);
}
public void onStopBtnClick(View view) {
Intent intent = new Intent(MainActivity.this, ExampleService.class);
exampleService.stopService(intent);
}
Actually, both paragraphs complement each other (although their wording might be misguiding), and both paragraphs are consistent with the image from the documentation. Let's have a look:
These two paths are not entirely separate. That is, you can bind to a service that was already started with startService(). For example, a background music service could be started by calling startService() with an Intent that identifies the music to play. Later, possibly when the user wants to exercise some control over the player or get information about the current song, an activity can bind to the service by calling bindService(). In cases like this, stopService() or stopSelf() does not actually stop the service until all clients unbind.
The quintessence is: If you start a service, then bind a client to it, then try to stop it, the service is not stopped (destroyed) before all clients unbind. The second paragraph does not contradict, it refines this statement.
However, if you choose to implement the onStartCommand() callback method, then you must explicitly stop the service, because the service is now considered to be started. In this case, the service runs until the service stops itself with stopSelf() or another component calls stopService(), regardless of whether it is bound to any clients.
This means: A started and bound service runs even if no clients are bound to it until it is explicitely stopped. Granted, the wording might probably be a bit clearer on this. The lifecycle diagram given in the documentation however shows this (and I am pretty sure I already observed this in "real-life", although I am currently have no direct example on top of my head):
Yep, it works.
I want to complete with a sample code :
I had to make an app with a service started by an activity, the activity have to call some methods in the service, the service have to run in background even if the activity were killed, and when the activity restarts, it haven't to restart the service if it is running. I hope it will help you, you can see how does it work with the Log.
So that is the code :
public class MyActivity extends Activity{
private MyService myService;
private boolean mIsBound = false;
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder binder) {
MyService.MyBinder b = (MyService.MyBinder) binder;
myService = b.getService();
mIsBound = true
//Do something
// Here you can call : myService.aFonctionInMyService();
}
public void onServiceDisconnected(ComponentName className) {
// Do something
mIsBound = false;
}
}
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
//Checked if my service is running
if (!isMyServiceRunning()) {
//if not, I start it.
startService(new Intent(this,MyService.class));
}
}
private boolean isMyServiceRunning() {
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (RunningServiceInfo service : manager
.getRunningServices(Integer.MAX_VALUE)) {
if (MyService.class.getName().equals(
service.service.getClassName())) {
return true;
}
}
return false;
}
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
doBindService();
}
//Connection to the Service
private void doBindService() {
bindService(new Intent(this,MyService.class), mConnection,
Context.BIND_AUTO_CREATE);
}
// Disconnection from the service
private void doUnbindService() {
if (mIsBound) {
// Detach our existing connection.
unbindService(mConnection);
}
}
#Override
protected void onPause() {
// TODO Auto-generated method stub
doUnbindService();
super.onPause();
}
}
public class MyService extends Service{
public static String Tag = "MyService";
private final IBinder mBinder = new MyBinder();
#Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
Log.d(Tag, "onCreate()");
}
public class MyBinder extends Binder {
public LocationService getService() {
return LocationService.this;
}
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
Log.d(Tag, "onBind()");
return mBinder;
}
#Override
public boolean onUnbind(Intent intent) {
// TODO Auto-generated method stub
Log.d(Tag, "onUnBind()");
return super.onUnbind(intent);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
Log.d(Tag,"onStartCommand()");
return START_STICKY;
}
#Override
public void onDestroy() {
// TODO Auto-generated method stub
Log.d(Tag, "onDestroy");
super.onDestroy();
}
public void aFonctionInMyService(){
//Do Something
}
}
I'm trying to revamp my multi-activity app to use just once instance of a LocationListener which I intend to implement in a service. Prior to doing this I've been experimenting with a stub activity and a stub service to see what happens under error conditions.
I want to see what happens if I attempt to unbind from a service which has already been unbound and avoid any errors if this should happen. The activity has two buttons to bind/unbind. If I deliberately hit the unbind twice in succession I do get a runtime error.
What condition can I test for at the point marked '<<<<<' in the code below to skip calling unbind again?
My activity code is
public void myClickHandler(View target) {
switch (target.getId()) {
case R.id.bind:
Log.d("STAG", "Activity One pressed BIND button");
mServiceConnected = bindService(new Intent(
"com.nbt.servicetest.LOCATIONSERVICE"), mServconn,
Context.BIND_AUTO_CREATE);
break;
case R.id.unbind:
Log.d("STAG", "Activity One pressed UNBIND button");
try{
if (mServconn != null) // <<<< What to put here if already unbound?
unbindService(mServconn);}
catch(Exception e){
Log.d("STAG", "Exception " + e.getMessage());
}
break;
}
}
ServiceConnection mServconn = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d("STAG", "Activity One service connected");
mIbinder = service;
}
#Override
public void onServiceDisconnected(ComponentName name) {
Log.d("STAG", "Activity One service disconnected");
}
};
The service is starting/stopping OK. I've put log lines in the service code with the same tag on all the pertinent lines. The output is :
STAG(2945): Activity One onCreate
STAG(2945): Activity One onStart
STAG(2945): Activity One onResume
STAG(2945): Activity One pressed BIND button
STAG(2945): Loc service ONCREATE
STAG(2945): Loc service ONBIND
STAG(2945): Activity One service connected
STAG(2945): Activity One pressed UNBIND button
STAG(2945): Loc service ONUNBIND
STAG(2945): Loc service ONDESTROY
STAG(2945): Activity One pressed UNBIND button
STAG(2945): Exception Service not registered: com.nbt.servicetest.ServiceTesterActivityOne$1#43b8b290
I note that the activity's onServiceDisconnected() never gets called, is this normal?
The simplest thing to do would be to introduce another variable, say, isServConnBound, and add checks on both bind and unbind actions. Of course, remember to update the variable after you call bindService and unbindService.
I agree with vhallac - just use boolean flags. What are your concerns with this approach? As for me there's nothing to be afraid of.
As to why "the activity's onServiceDisconnected() never gets called" - yes, this is normal. Look what API says on this callback:
Called when a connection to the Service has been lost. This typically happens when the process hosting the service has crashed or been killed.
Your process has neither crashed nor been killed, so this is an expected behavior. Even more, since you have your service in the same process, you'll never get this called. This is important when you bind to a service that runs in another process (inter process communication).
I want to create Service using bindService method.
But when I close one Activity my Service is destroyed, and I don't want that.
I try to put service in foreground using startForeground(NOTIFICATION_ID, notification); service onCreate , but service still destroy.
Now I try with call two methods for starting Service at same time :
Intent bindIntent= new Intent(this, ServiceC.class);
startService(bindIntent);
bindService(bindIntent, onService, BIND_AUTO_CREATE);
By calling these two methods Service not destroyed. My app work fine with this method.
Can someone explain to me whether this is a good way or if it is not can you please give me idea why startForeground(NOTIFICATION_ID, notification); does not work ?
What is the best way to use bindService but at the same time I don't want the service to self destroy.
I Used the same solution and it's a legitimate one. From Service ref:
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.
startForeground() is not working because it just tries to prevent the service from being killed by the system, but its lifecycle is another thing: if nothing is more bound to that service and it wasn't started, it just stops.
If you start service with startService() it is not destroyed. Tried starting a service, which extends IntentService and have a loop in onHandleIntent(). When loop is finished, then service destroyed and it is not related with Activity finish. User can close application, but service is not being killed.
public class MyService extends IntentService
{
private static final String serviceName = "MyService ";
public MyService () {
super(serviceName);
}
#Override
public void onDestroy()
{
Log.v(serviceName, "onDestroy");
Toast.makeText(this, serviceName+" stopped", Toast.LENGTH_LONG).show();
super.onDestroy();
}
#Override
protected void onHandleIntent(Intent arg0) {
long endTime = System.currentTimeMillis() + 30*1000;
while (System.currentTimeMillis() < endTime) {
synchronized (this) {
try {
Log.v(serviceName, "Service loop");
wait(1000);
} catch (Exception e) {
}
}
}
}
}