How to start a service on its own??
I dont want to start the service from another activity.but i want to bind to the service to the activity..
my problem is exactly as described in this link.
onServiceConnected never called after bindService method
i.e my onserviceconnected is never called.
Messenger mService = null;
public void onServiceConnected(ComponentName className, IBinder service) {
mService = new Messenger(service);
Log.d("IMSLogging", "inside onServiceConnected");
}
from oncreate of my activity i am calling bindService.but i am getting a nullpointerexception when i am doing mService.send(msg); from oncreate.(after the bindService is called, of course.) though bindService is returning true.,
You can't call mService.send() until after you get the onServiceConnected() callback. That means you can't do both bindService() and mService.send() in onCreate(). You need to move the mService.send() call into either onResume() or into onServiceConnected() or somewhere else.
Related
I have a remote Service that I start with startService() then bind to with bindService(). I do this because I want the Service to run in the background until the app explicitly stops it, even if the user closes the Activity with a swipe. Here are the relevant parts of the Service:
public class TrackService extends Service {
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("onStartCommand","got to onStartCommand");
return START_NOT_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
Log.i("onBind", "got to onBind");
return trackServiceBinder;
}
}
Here is the activity:
public class GPSLoggerActivity extends Activity implements ServiceConnection {
#Override
protected void onStart() {
super.onStart();
Intent intent = new Intent(TrackService.class.getName());
intent.setClass(getApplicationContext(), TrackService.class);
startService(intent);
Log.i("onStart", "started TrackService");
if (!getApplicationContext().bindService(intent, this, 0)) {
// close the Activity
}
Log.i("onStart", "bound to TrackService");
}
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.i("onServiceConnected", "got here");
// get and use the interface from the Binder
}
}
Here is the manifest for the Service:
<service
android:name=".TrackService"
android:process=":track_service_process"
android:stopWithTask="false"
android:label="#string/track_service_label"
android:exported="false"
android:enabled="true">
<intent-filter>
<action android:name="com.mydomain.gpslogger.TrackService" />
</intent-filter>
</service>
When I run this in the debugger step-wise through startService() and bindService() everything is fine. Within the Service, onStartCommand() is invoked followed by onBind(), and in the Activity onServiceConnected() is invoked with the Binder. However, when I'm not debugging, for some reason the Service gets its onBind() method invoked before its onStartCommand() method. Here's the output from the log:
11-28 23:17:01.805: I/onStart(1103): started TrackService
11-28 23:17:01.815: I/onStart(1103): bound to TrackService
11-28 23:17:01.985: I/onBind(1165): got to onBind
11-28 23:17:01.995: I/onStartCommand(1165): got to onStartCommand
The Activity's onServiceConnected() method is never invoked. I've tried using BIND_AUTO_CREATE in the bindService() call, to no effect. It's pretty clear I have some sort of race condition going on here, but I've run this probably 20 times and it always comes out in the same order. The only way I can think of to enforce the correct order of calls in the Service is to put a BroadcastReceiver in the Activity and send an Intent from the onStartCommand() method of the Service to let the Activity know that it's time to call bindService(). That seems pretty kludgy...is there a better way to do this? Or is there something that I'm missing that is causing the out-of-order calls?
You could call startService() and then wait some period of time before calling bindService(). How long to wait is certainly a question, but I would think if your Service doesn't do massive amounts of work when started, 500 or 1000 milliseconds delay should do it.
I would question why this is important. The Service has an onCreate() method, which is called when the Service is instantiated, regardless of whether onStartCommand() or onBind() is called first. You should be able to setup your architecture so that you do all important setup in onCreate() and then it shouldn't matter in what order onStartCommand() or onBind() is called. NOTE: You must use flag BIND_AUTO_CREATE in the call to bindService()
I also do not understand why the onServiceConnected() method is not called. Unless the call to bindService() returns false (which basically means that Android can't find the Service to bind to), you should get the onServiceConnected() callback. This sounds strange. One possibility is that the Service crashes in onCreate(), or it takes too long to execute the onCreate() method, in which case Android will declare the Service broken.
I've got a service that's bound to from a couple of activities, each using a ServiceConnection.
Each activity needs to check before calling the service whether the service is already in use. So in the service I have a function (let's say getCurrentId() ) which returns details of what the service is currently doing.
Then in the client activity, the service connection is set up:
private MyService mService = null;
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder binder) {
MyService.MyBinder myBinder = (MyService.MyBinder) binder;
mService = myBinder.getService();
activeId = mService.getCurrentId();
log.i(TAG, "Service bound" );
}
public void onServiceDisconnected(ComponentName className) {
log.i(TAG, "Service has been killed");
mService = null;
}
};
A button toggles binding to the service:
activity.bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
and unbinding:
activity.unbindService(mConnection);
I'm not calling startService() at all.
Before I bind to the service, I check if it's already active and what it's doing:
if (mService == null)
activeId = -1;
else
activeId = mService.getCurrentId();
The problem is, if an activity binds to and then unbinds from the service, the service onDestroy() method is called (I've logging in it to confirm this), which is fine.
BUT this doesn't trigger onServiceDisconnected().
So mService is never set to null, and when I get to that if statement, it happily carries on and calls getCurrentId(), which returns whatever the previous details were.
I gather that onServiceDisconnected() is only supposed to be called when the thread the service is running in is unexpectedly killed, so it's correct that it's not called when the service is destroyed due to the last activity using it unbinding.
As far as I can tell, the service isn't being reinstantiated, I've got logging throughout it.
Which gives me two questions:
Is there an alternative callback function or some way where a ServiceConnection is notified that its service has been destroyed by unbinding?
If the service has been destroyed, then how can I still call its functions? Or is something else going on - is the ServiceConnection or the Binder somehow returning the value without actually calling the service?
onServiceDisconnected() is only called
when a connection to the Service has been lost. This typically happens
when the process hosting the service has crashed or been killed.
Quoted from the Android docs. This seems to be a very rare case, and will not be called when simply unbinding normally from a service.
To keep my connections with a service sane, I would suggest you bind to the service in the Activities onResume method and unbind from it in the onPause method.
I am using an android service as explained here. I am calling doBindService() in onCreate() and trying to call one of mBoundservice's methods in onResume(). This is where I run into an issue. At this point, mBoundService is still null, presumably because mConnection.onServiceConnected() hasn't yet been called.
Is there some way to be able to call methods of mBoundService in onResume(), or is there no way around it's being null at that point?
It hasn't been clear stated in the official dev guide that bindService() is actually an asynchronous call:
A client can bind to the service by calling bindService(). When it does, it must provide an implementation of ServiceConnection, which monitors the connection with the service. The bindService() method returns immediately without a value, but when the Android system creates the connection between the client and service, it calls onServiceConnected() on the ServiceConnection, to deliver the IBinder that the client can use to communicate with the service.
There is a lag (although instantaneous but still a lag) after calling bindService() and before system prepare/instantiate a usable service instance (not NULL) and hand it back in ServiceConnection.onServiceConnected() callback. the time interval between onCreate() and onResume() is too short to overcome the lag (in case if activity is opened first time).
Suppose you want to call mBoundservice.foo() in onResume(), a common workaround is call it in onServiceConnected() callback when activity is first created, and set a boolean state, and in onResume() method, only call it iff the state is set, to conditional control the code execution i.e. calling mBoundservice.foo() based on different Activity lifecycle:
LocalService mBoundservice = null;
boolean mBound = false;
... ...
private ServiceConnection mConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName className, IBinder service) {
LocalBinder binder = (LocalBinder) service;
mBoundservice = binder.getService();
mBound = true;
// when activity is first created:
mBoundservice.foo();
}
... ...
};
... ...
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// call bindService here:
doBindService();
}
#Override
protected void onResume() {
super.onResume();
// when activity is resumed:
// mBound will not be ready if Activity is first created, in this case use onServiceConnected() callback perform service call.
if (mBound) // <- or simply check if (mBoundservice != null)
mBoundservice.foo();
}
... ...
Hope this helps.
I just want to know could I bind a service from another service. For example, currently I have an activity A starting a service B and now I just want service B to bind and start another service C. So does anybody know how to do that? That means could I use the same method for activity A to start a service on a service to start another service?
You can call bindService from a Service exactly the same way you can call it from an Activity. You'll notice from the javadoc that the only place you can't call bindService is in a BroadcastReceiver. You can use a ServiceConnection as well to receive the Binder.
This works for me. If I call bindService from onCreate then onServiceConnected is in a race with the first call to onHandleIntent, so re-submit the intent if it arrives too soon. My code is roughly like this.
class MyService extends IntentService implements ServiceConnection {
IMyOtherService iService;
#Override
void onCreate() {
bindService(intent);
}
#Override
void onServiceConnected(ComponentName name, IBinder service) {
iService = IMyService.Stub.asInterface(service);
}
#Override
void onHandleIntent(Intent intent) {
if (iService == null) {
/* onHandleIntent has lost the race with onServiceConnected
* so wait 250 ms and resend the Intent.
*/
try { System.getCurrentThread().sleep(250); } catch (InterruptedException e) { }
startService(intent);
}
iService->method1();
}
I'm not good in English, but I would try to explain my problem in good way.
So, the problem is:
1) I have a local service
2) I start it and then bound to it.
3) Problem appears when I am about to close that service. onServiceDisconnected method from my implementation of class ServiceConnection is never called. If I close it manually (from settings), or by unbindService, or by stopService, or by combination of unbindService and stopService - onServiceDisconnected still doesn't to be called.
What am I doing wrong?
Short code is below:
protected ServiceConnection mServerConn = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder binder) {
Log.d(LOG_TAG, "onServiceConnected");
}
#Override
public void onServiceDisconnected(ComponentName name) {
Log.d(LOG_TAG, "onServiceDisconnected");
}
}
public void start() {
// mContext is defined upper in code, I think it is not necessary to explain what is it
mContext.bindService(i, mServerConn, Context.BIND_AUTO_CREATE);
mContext.startService(i);
}
public void stop() {
mContext.stopService(new Intent(mContext, ServiceRemote.class));
mContext.unbindService(mServerConn);
}
I'm testing this code under emulator of Android 2.2
onServiceDisconnected is only called in extreme situations (crashed / killed).
which is very unlikely to happen for a local service since all your application components normally run in the same process... meaning, unless you intentionnaly unbind or destroy the service, it should remain connected, or die with the component using it.
Android developer documentation says...
public abstract void onServiceDisconnected (ComponentName name)
Called when a connection to the Service has been lost. This typically happens when the process hosting the service has crashed or been killed. This does not remove the ServiceConnection itself -- this binding to the service will remain active, and you will receive a call to onServiceConnected(ComponentName, IBinder) when the Service is next running.
For more: https://developer.android.com/reference/android/content/ServiceConnection#onServiceDisconnected(android.content.ComponentName)
I used Context.BIND_AUTO_CREATE in bindService. I have fetch same issue after apply its working perfect for me.
bindService(new Intent(this,XMPPService.class),mConnection, Context.BIND_AUTO_CREATE);