Android How to Wait Until a Service Is Actually Connected

Android how do I wait until a service is actually connected?

How can I wait for
ServiceConnection.onServiceConnected
being called reliably?

You don't. You exit out of onCreate() (or wherever you are binding) and you put you "needs the connection established" code in onServiceConnected().

Are all the event handlers:
Activity.onCreate, any
View.onClickListener.onClick,
ServiceConnection.onServiceConnected,
etc. actually called in the same
thread

Yes.

When exactly is
ServiceConnection.onServiceConnected
actually going to be called? Upon
completion of Activity.onCreate or
sometime when A.oC is still running?

Your bind request probably is not even going to start until after you leave onCreate(). Hence, onServiceConnected() will called sometime after you leave onCreate().

How do wait for a service to start on Android without using bindService

You can try to use both methods, first start the service with startForeground() and then use bindService() to wait for the service connection.

The service starts in the foreground and you can use the service methods.

Starting Service:

listenServiceIntent = new Intent(getApplicationContext(), ListenService.class);

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {

//Start in Foreground
ContextCompat.startForegroundService(this, listenServiceIntent);

if (connection != null) {
//Then bind service
bindService(listenServiceIntent, connection, Context.BIND_AUTO_CREATE);
}
}
else {
startService(listenServiceIntent);
if (connection != null) {
bindService(listenServiceIntent, connection, Context.BIND_AUTO_CREATE);
}
}

Waiting Connection:

private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.i(TAG, "onServiceConnected");

ListenService.LocalBinder binder = (ListenService.LocalBinder) service;
listenService = binder.getService();

//HERE you can use service methods

}

@Override
public void onServiceDisconnected(ComponentName name) {
Log.i(TAG, "onServiceDisconnected");
}
};

Create notificationChannel:

public static void createNotificationChannel(Context context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel serviceChannel = new NotificationChannel(
NOTIFICATION_CHANNEL,
NOTIFICATION_NAME,
NotificationManager.IMPORTANCE_HIGH
);

NotificationManager manager = context.getSystemService(NotificationManager.class);
if (manager != null) {
manager.createNotificationChannel(serviceChannel);
}
}
}

Push notification:

public static Notification pushNotification(Context context, String notificationText, Class classNotification) {

Intent notificationIntent = new Intent(context, classNotification);

PendingIntent pendingIntent = PendingIntent.getActivity(context,
0, notificationIntent, 0);

return new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL)
.setContentTitle(context.getString(R.string.notification_title))
.setContentText(notificationText)
.setContentIntent(pendingIntent)
.setSmallIcon(R.drawable.logosinfondo_mini)
.setColor(Color.MAGENTA)
.setAutoCancel(true)
.build();
}

In onCreate() inside your Service:

@Override
public void onCreate() {
super.onCreate();
Lib.createNotificationChannel(this);
startForeground(1, Lib.pushNotification(this, "Started", ListenActivity.class));
}

How to wait for service on activity start

I used a singleton approach from this tip.

Don't do that. Use bindService() and the local binding pattern instead, and you will be notified when the service is ready. You also get access to an API published by the service and can start using it once you are bound.

Android java - how to make Activity wait until Service is binded?

I think you want that: http://developer.android.com/guide/components/bound-services.html.

On this page you can find:

/** Defines callbacks for service binding, passed to bindService() */
private ServiceConnection mConnection = new ServiceConnection() {

@Override
public void onServiceConnected(ComponentName className,
IBinder service) {
// We've bound to LocalService, cast the IBinder and get LocalService instance
LocalBinder binder = (LocalBinder) service;
mService = binder.getService();
mBound = true;
}

@Override
public void onServiceDisconnected(ComponentName arg0) {
mBound = false;
}
};

The onServiceConnected method is called when the service is ready and you can do your stuff inside (or use the mBound attribute).

To bind to your service, use that:

    // Bind to LocalService
Intent intent = new Intent(this, LocalService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);

How to wait until services stops in Android

Instead of a normal Service, Use an Intent service, as it automatically stops itself after completing its task.

Now when this service stops, you may send a Local Broadcast, and receive this Broadcast in your Splash Activity.

Keep a track of running services, and one which have stopped, you may use flags for this.

So for example if service A stops itself and sends a broadcast set its flag to true.

Now on each Broadcast receive check if all flags are true, if Yes, stop the Splash screen and move to next step or else wait for other services to stop.

Example

We have three services A, B, C running and corresponding to them we have three flag stopA, stopB, stopC in our Splash Activity.

Now when A finishes, it sends a local broadcast, which is then received in Splash Activity, now we set the flag of A i.e stopA = true; and check if flags for services B & C are true or not (i.e. if other services have stopped or running)

If true finish this activity, else wait for other broadcasts.

start service from activity and wait until its ready

Your question is a little confusing, because Services already live independently of Activities. Note, however, that Services run in the main thread by default. If you want to run the Service in a different thread (and in this case it looks like you do), you will have to set up a Messenger object and send messages between your worker thread and your UI thread. You can also look into using AIDL (on top of which Messenger is really built anyway). Your communication, if you don't use a Messenger, could use intents. If this is the case, you should look into IntentService. However, this only works when you are sending messages to the Service, not back and forth. If you want back and forth communication, you will have to use some sort of Messenger or similar pattern.

By the way, using an IntentService for things like 'stop' and 'start' is pretty common. Typically there is also a background thread, which communicates with the Service using a Messenger or something similar, and then sends / receives messages to instruct the worker thread as to what should be done.

You might also look into AsyncTask, as it makes this kind of thing much simpler.

Android: how to properly wait on service process completion

If user performs the search during the
update I want to wait until the update
is over while displaying "Please wait"
progress alert. I don't want to query
and display search results until
refresh is fully done.

That's your call, but bear in mind you are creating your own problem. Personally, I'd dump this requirement. The user should not be inconvenienced just because an alarm went off.

For example, you could disable the alarm and re-enable it when the activity goes away.

Or, have the update be performed in such a way that it is atomic (e.g., do the update on a copy of the table, then sync the tables in a transaction), so that the activity can still safely access the database while the update is occurring.

What would be a "right" way to
properly wait (may be even with status
update) in this case?

Have the service tell the activity when the update is done, via some sort of callback, or perhaps a broadcast Intent. Keep the progress indicator alive until this occurs. This still introduces some timing challenges, which is why I'd just dump the requirement.

Starting an activity from a service and wait for the result

There is no equivalent to startActivityForResult in Service, so you have to roll your own.

First option:

You can use several standard Java tools for this, like Object.wait / Object.notify, that require a shared object reference.

For example, declare somewhere:

public static final Object sharedLock = new Object();

and in your service do:

startActivity(new Intent(this, GoogleAuthHelperActivity.class), FLAG_ACTIVITY_NEW_TASK);
synchronized (sharedLock) {
sharedLock.wait();
}

and in the activity:

// do something upon request and when finished:
synchronized (sharedLock) {
sharedLock.notify();
}

There are other more sophisticated classes for this in the java.util.concurrent package that you can use for this. Be careful though, that Services run on the same thread as the Activity, so if you are not starting a new Thread from the Service, then this will not work.

Another possible problem is if you cannot share an object reference between them two (because they run in different processes). Then you have to signal the finishing in some other way.

Second option:

You could split your Service code in two parts (before and after the activity). Run the activity and send a new intent to the Service when you are done. Upon receipt of this second Service, you continue with the second part.



Related Topics



Leave a reply



Submit