Discussion:
What's the best way to handle an task w/progress dialog on orientation change?
Robert Green
2009-05-27 18:01:35 UTC
Permalink
I have an app that communicates with a server. While it is
communicating, it shows a progress dialog. The way this actually
works is that I have a class that I call my NetworkGateway. Each
method takes a Handler as a callback so that the gateway can send back
the response as a bundle when it has finished.

Right now when someone changes orientation while a network operation
is occuring, the activity doesn't know that a thread is running the
network code and then the callback might be invalid.

What's the right way to do this? I want to make it so that after the
orientation switch, the activity can check something to see if a
network operation is running and if so, display the progress dialog
again and wait for the callback, or set itself as the callback handler
now, invalidating the old one.

My first guess is that this is exactly the kind of thing services were
designed for, but I'd like specifics if anyone can supply them.

Thanks!
Streets Of Boston
2009-05-27 19:22:25 UTC
Permalink
Take a look at the method onRetainNonConfigurationInstance() of the
Activity class. :-)

http://developer.android.com/reference/android/app/Activity.html#onRetainNonConfigurationInstance()

On May 27, 2:01 pm, Robert Green <***@gmail.com> wrote:
> I have an app that communicates with a server.  While it is
> communicating, it shows a progress dialog.  The way this actually
> works is that I have a class that I call my NetworkGateway.  Each
> method takes a Handler as a callback so that the gateway can send back
> the response as a bundle when it has finished.
>
> Right now when someone changes orientation while a network operation
> is occuring, the activity doesn't know that a thread is running the
> network code and then the callback might be invalid.
>
> What's the right way to do this?  I want to make it so that after the
> orientation switch, the activity can check something to see if a
> network operation is running and if so, display the progress dialog
> again and wait for the callback, or set itself as the callback handler
> now, invalidating the old one.
>
> My first guess is that this is exactly the kind of thing services were
> designed for, but I'd like specifics if anyone can supply them.
>
> Thanks!
Robert Green
2009-05-27 20:07:24 UTC
Permalink
I just looked at it.

1) They state that it is only an optimization and that you are not to
rely on the method being called.

2) My design is a little too complex to use that elegantly. I do
network calls from multiple activities and some dialogs on those
activities, which need to chain to other actions upon completion.

I'm learning about Services right now and I think that if I could have
a network service that I can register a specific callback with, like a
"User Updated" callback, it would work really well. When the service
finishes updating a user, it simply notifies the user updated
callback. It won't care if it was the original activity/dialog or a
new one.

Does that sound feasible?

On May 27, 2:22 pm, Streets Of Boston <***@gmail.com> wrote:
> Take a look at the method onRetainNonConfigurationInstance() of the
> Activity class. :-)
>
> http://developer.android.com/reference/android/app/Activity.html#onRe...()
>
> On May 27, 2:01 pm, Robert Green <***@gmail.com> wrote:
>
> > I have an app that communicates with a server.  While it is
> > communicating, it shows a progress dialog.  The way this actually
> > works is that I have a class that I call my NetworkGateway.  Each
> > method takes a Handler as a callback so that the gateway can send back
> > the response as a bundle when it has finished.
>
> > Right now when someone changes orientation while a network operation
> > is occuring, the activity doesn't know that a thread is running the
> > network code and then the callback might be invalid.
>
> > What's the right way to do this?  I want to make it so that after the
> > orientation switch, the activity can check something to see if a
> > network operation is running and if so, display the progress dialog
> > again and wait for the callback, or set itself as the callback handler
> > now, invalidating the old one.
>
> > My first guess is that this is exactly the kind of thing services were
> > designed for, but I'd like specifics if anyone can supply them.
>
> > Thanks!
>
>
Streets Of Boston
2009-05-27 20:22:03 UTC
Permalink
I agree you should use a service.
But for optimization, i would use this method.

You should have a call to the service to query if the service is still
busy. If so, show a progress dialog and start listening to the service
to know when it no longer is busy (callback from the service into your
app)

On May 27, 4:07 pm, Robert Green <***@gmail.com> wrote:
> I just looked at it.
>
> 1)  They state that it is only an optimization and that you are not to
> rely on the method being called.
>
> 2)  My design is a little too complex to use that elegantly.  I do
> network calls from multiple activities and some dialogs on those
> activities, which need to chain to other actions upon completion.
>
> I'm learning about Services right now and I think that if I could have
> a network service that I can register a specific callback with, like a
> "User Updated" callback, it would work really well.  When the service
> finishes updating a user, it simply notifies the user updated
> callback.  It won't care if it was the original activity/dialog or a
> new one.
>
> Does that sound feasible?
>
> On May 27, 2:22 pm, Streets Of Boston <***@gmail.com> wrote:
>
>
>
> > Take a look at the method onRetainNonConfigurationInstance() of the
> > Activity class. :-)
>
> >http://developer.android.com/reference/android/app/Activity.html#onRe...()
>
> > On May 27, 2:01 pm, Robert Green <***@gmail.com> wrote:
>
> > > I have an app that communicates with a server.  While it is
> > > communicating, it shows a progress dialog.  The way this actually
> > > works is that I have a class that I call my NetworkGateway.  Each
> > > method takes a Handler as a callback so that the gateway can send back
> > > the response as a bundle when it has finished.
>
> > > Right now when someone changes orientation while a network operation
> > > is occuring, the activity doesn't know that a thread is running the
> > > network code and then the callback might be invalid.
>
> > > What's the right way to do this?  I want to make it so that after the
> > > orientation switch, the activity can check something to see if a
> > > network operation is running and if so, display the progress dialog
> > > again and wait for the callback, or set itself as the callback handler
> > > now, invalidating the old one.
>
> > > My first guess is that this is exactly the kind of thing services were
> > > designed for, but I'd like specifics if anyone can supply them.
>
> > > Thanks!- Hide quoted text -
>
> - Show quoted text -
Robert Green
2009-05-27 20:33:53 UTC
Permalink
I'm searching all of the documentation I can find but I'm not seeing
any mechanism to register for callbacks from a service or to callback
to whatever handler is registered as the service.

I see the AIDL binding stuff, and so far I think maybe this sort of
thing might work?

Activity
-- Starts Service (this is to make the service keep going after this
context is destroyed)
-- Binds to Service, calls remote interface to check if the service is
busy, it's not, so nothing happens.
- User clicks on form submission
-- Starts Service (this is to make the service keep going after this
context is destroyed, it won't hurt to start again because it's
already running)
-- Binds to Service, calls remote interface to set self as callback
handler
-- Orientation change, destroyed
New Activity
-- Starts Service (this is to make the service keep going after this
context is destroyed)
-- Binds to Service, calls remote interface to check if the service is
busy, if so, sets self as callback handler
-- Service finishes working, calls back and ends itself.

Does this sound correct? So far as I understand from the APIs, this
may be the only way to do it. Please let me know of an easier way if
one exists!

Thanks!

On May 27, 3:22 pm, Streets Of Boston <***@gmail.com> wrote:
> I agree you should use aservice.
> But for optimization, i would use this method.
>
> You should have a call to theserviceto query if theserviceis still
> busy. If so, show a progress dialog and start listening to theservice
> to know when it no longer is busy (callbackfrom theserviceinto your
> app)
>
> On May 27, 4:07 pm, Robert Green <***@gmail.com> wrote:
>
> > I just looked at it.
>
> > 1)  They state that it is only an optimization and that you are not to
> > rely on the method being called.
>
> > 2)  My design is a little too complex to use that elegantly.  I do
> > network calls from multiple activities and some dialogs on those
> > activities, which need to chain to other actions upon completion.
>
> > I'm learning about Services right now and I think that if I could have
> > a networkservicethat I can register a specificcallbackwith, like a
> > "User Updated"callback, it would work really well.  When theservice
> > finishes updating a user, it simply notifies the user updated
> >callback.  It won't care if it was the original activity/dialog or a
> > new one.
>
> > Does that sound feasible?
>
> > On May 27, 2:22 pm, Streets Of Boston <***@gmail.com> wrote:
>
> > > Take a look at the method onRetainNonConfigurationInstance() of the
> > > Activity class. :-)
>
> > >http://developer.android.com/reference/android/app/Activity.html#onRe...()
>
> > > On May 27, 2:01 pm, Robert Green <***@gmail.com> wrote:
>
> > > > I have an app that communicates with a server.  While it is
> > > > communicating, it shows a progress dialog.  The way this actually
> > > > works is that I have a class that I call my NetworkGateway.  Each
> > > > method takes a Handler as acallbackso that the gateway can send back
> > > > the response as a bundle when it has finished.
>
> > > > Right now when someone changes orientation while a network operation
> > > > is occuring, the activity doesn't know that a thread is running the
> > > > network code and then thecallbackmight be invalid.
>
> > > > What's the right way to do this?  I want to make it so that after the
> > > > orientation switch, the activity can check something to see if a
> > > > network operation is running and if so, display the progress dialog
> > > > again and wait for thecallback, or set itself as thecallbackhandler
> > > > now, invalidating the old one.
>
> > > > My first guess is that this is exactly the kind of thing services were
> > > > designed for, but I'd like specifics if anyone can supply them.
>
> > > > Thanks!- Hide quoted text -
>
> > - Show quoted text -
>
>
Streets Of Boston
2009-05-27 21:08:34 UTC
Permalink
Your steps below are basically correct, but take a look at the API
Demoes source code.
There is one for demoeing how to write a Service, using AIDL.
It also shows how to write a callback method (service calling back
into activities bound to that service).

I use it for monitoring image-upload progress. The activity binds to
the service and registers itself as interested in upload progress.
When the service is uploading images, it calls back to any registered
activity. The activity then updates, on these callbacks, various
progress indicators.

On May 27, 4:33 pm, Robert Green <***@gmail.com> wrote:
> I'm searching all of the documentation I can find but I'm not seeing
> any mechanism to register for callbacks from a service or to callback
> to whatever handler is registered as the service.
>
> I see the AIDL binding stuff, and so far I think maybe this sort of
> thing might work?
>
> Activity
> -- Starts Service (this is to make the service keep going after this
> context is destroyed)
> -- Binds to Service, calls remote interface to check if the service is
> busy, it's not, so nothing happens.
> - User clicks on form submission
> -- Starts Service (this is to make the service keep going after this
> context is destroyed, it won't hurt to start again because it's
> already running)
> -- Binds to Service, calls remote interface to set self as callback
> handler
> -- Orientation change, destroyed
> New Activity
> -- Starts Service (this is to make the service keep going after this
> context is destroyed)
> -- Binds to Service, calls remote interface to check if the service is
> busy, if so, sets self as callback handler
> -- Service finishes working, calls back and ends itself.
>
> Does this sound correct?  So far as I understand from the APIs, this
> may be the only way to do it.  Please let me know of an easier way if
> one exists!
>
> Thanks!
>
> On May 27, 3:22 pm, Streets Of Boston <***@gmail.com> wrote:
>
>
>
> > I agree you should use aservice.
> > But for optimization, i would use this method.
>
> > You should have a call to theserviceto query if theserviceis still
> > busy. If so, show a progress dialog and start listening to theservice
> > to know when it no longer is busy (callbackfrom theserviceinto your
> > app)
>
> > On May 27, 4:07 pm, Robert Green <***@gmail.com> wrote:
>
> > > I just looked at it.
>
> > > 1)  They state that it is only an optimization and that you are not to
> > > rely on the method being called.
>
> > > 2)  My design is a little too complex to use that elegantly.  I do
> > > network calls from multiple activities and some dialogs on those
> > > activities, which need to chain to other actions upon completion.
>
> > > I'm learning about Services right now and I think that if I could have
> > > a networkservicethat I can register a specificcallbackwith, like a
> > > "User Updated"callback, it would work really well.  When theservice
> > > finishes updating a user, it simply notifies the user updated
> > >callback.  It won't care if it was the original activity/dialog or a
> > > new one.
>
> > > Does that sound feasible?
>
> > > On May 27, 2:22 pm, Streets Of Boston <***@gmail.com> wrote:
>
> > > > Take a look at the method onRetainNonConfigurationInstance() of the
> > > > Activity class. :-)
>
> > > >http://developer.android.com/reference/android/app/Activity.html#onRe...()
>
> > > > On May 27, 2:01 pm, Robert Green <***@gmail.com> wrote:
>
> > > > > I have an app that communicates with a server.  While it is
> > > > > communicating, it shows a progress dialog.  The way this actually
> > > > > works is that I have a class that I call my NetworkGateway.  Each
> > > > > method takes a Handler as acallbackso that the gateway can send back
> > > > > the response as a bundle when it has finished.
>
> > > > > Right now when someone changes orientation while a network operation
> > > > > is occuring, the activity doesn't know that a thread is running the
> > > > > network code and then thecallbackmight be invalid.
>
> > > > > What's the right way to do this?  I want to make it so that after the
> > > > > orientation switch, the activity can check something to see if a
> > > > > network operation is running and if so, display the progress dialog
> > > > > again and wait for thecallback, or set itself as thecallbackhandler
> > > > > now, invalidating the old one.
>
> > > > > My first guess is that this is exactly the kind of thing services were
> > > > > designed for, but I'd like specifics if anyone can supply them.
>
> > > > > Thanks!- Hide quoted text -
>
> > > - Show quoted text -- Hide quoted text -
>
> - Show quoted text -
Robert Green
2009-05-27 21:12:50 UTC
Permalink
Yup, I found it.

RemoteService.java
IRemoteService.aidl
IRemoteServiceCallback.aidl

Is that what you're talking about?

I'm looking at those now and am going to try to code this up in the
next few hours.

On May 27, 4:08 pm, Streets Of Boston <***@gmail.com> wrote:
> Your steps below are basically correct, but take a look at the API
> Demoes source code.
> There is one for demoeing how to write a Service, using AIDL.
> It also shows how to write a callback method (service calling back
> into activities bound to that service).
>
> I use it for monitoring image-upload progress. The activity binds to
> the service and registers itself as interested in upload progress.
> When the service is uploading images, it calls back to any registered
> activity. The activity then updates, on these callbacks, various
> progress indicators.
>
> On May 27, 4:33 pm, Robert Green <***@gmail.com> wrote:
>
> > I'm searching all of the documentation I can find but I'm not seeing
> > any mechanism to register for callbacks from a service or to callback
> > to whatever handler is registered as the service.
>
> > I see the AIDL binding stuff, and so far I think maybe this sort of
> > thing might work?
>
> > Activity
> > -- Starts Service (this is to make the service keep going after this
> > context is destroyed)
> > -- Binds to Service, calls remote interface to check if the service is
> > busy, it's not, so nothing happens.
> > - User clicks on form submission
> > -- Starts Service (this is to make the service keep going after this
> > context is destroyed, it won't hurt to start again because it's
> > already running)
> > -- Binds to Service, calls remote interface to set self as callback
> > handler
> > -- Orientation change, destroyed
> > New Activity
> > -- Starts Service (this is to make the service keep going after this
> > context is destroyed)
> > -- Binds to Service, calls remote interface to check if the service is
> > busy, if so, sets self as callback handler
> > -- Service finishes working, calls back and ends itself.
>
> > Does this sound correct?  So far as I understand from the APIs, this
> > may be the only way to do it.  Please let me know of an easier way if
> > one exists!
>
> > Thanks!
>
> > On May 27, 3:22 pm, Streets Of Boston <***@gmail.com> wrote:
>
> > > I agree you should use aservice.
> > > But for optimization, i would use this method.
>
> > > You should have a call to theserviceto query if theserviceis still
> > > busy. If so, show a progress dialog and start listening to theservice
> > > to know when it no longer is busy (callbackfrom theserviceinto your
> > > app)
>
> > > On May 27, 4:07 pm, Robert Green <***@gmail.com> wrote:
>
> > > > I just looked at it.
>
> > > > 1)  They state that it is only an optimization and that you are not to
> > > > rely on the method being called.
>
> > > > 2)  My design is a little too complex to use that elegantly.  I do
> > > > network calls from multiple activities and some dialogs on those
> > > > activities, which need to chain to other actions upon completion.
>
> > > > I'm learning about Services right now and I think that if I could have
> > > > a networkservicethat I can register a specificcallbackwith, like a
> > > > "User Updated"callback, it would work really well.  When theservice
> > > > finishes updating a user, it simply notifies the user updated
> > > >callback.  It won't care if it was the original activity/dialog or a
> > > > new one.
>
> > > > Does that sound feasible?
>
> > > > On May 27, 2:22 pm, Streets Of Boston <***@gmail.com> wrote:
>
> > > > > Take a look at the method onRetainNonConfigurationInstance() of the
> > > > > Activity class. :-)
>
> > > > >http://developer.android.com/reference/android/app/Activity.html#onRe...()
>
> > > > > On May 27, 2:01 pm, Robert Green <***@gmail.com> wrote:
>
> > > > > > I have an app that communicates with a server.  While it is
> > > > > > communicating, it shows a progress dialog.  The way this actually
> > > > > > works is that I have a class that I call my NetworkGateway.  Each
> > > > > > method takes a Handler as acallbackso that the gateway can send back
> > > > > > the response as a bundle when it has finished.
>
> > > > > > Right now when someone changes orientation while a network operation
> > > > > > is occuring, the activity doesn't know that a thread is running the
> > > > > > network code and then thecallbackmight be invalid.
>
> > > > > > What's the right way to do this?  I want to make it so that after the
> > > > > > orientation switch, the activity can check something to see if a
> > > > > > network operation is running and if so, display the progress dialog
> > > > > > again and wait for thecallback, or set itself as thecallbackhandler
> > > > > > now, invalidating the old one.
>
> > > > > > My first guess is that this is exactly the kind of thing services were
> > > > > > designed for, but I'd like specifics if anyone can supply them.
>
> > > > > > Thanks!- Hide quoted text -
>
> > > > - Show quoted text -- Hide quoted text -
>
> > - Show quoted text -
>
>
Mike Hearn
2009-05-28 14:32:38 UTC
Permalink
You don't need a Service, that's way too complicated for what you
need. Especially if you use the RPC stuff (optional but the docs don't
tell you that!)

If you create the progress dialog using the onCreateDialog() method
then it'll be automatically reconstructed after an orientation
change.

To receive callbacks as to progress, you can just send to a static
Handler. Create the Handler in your onCreate if it's not already
created, so it's shared between all instances of your activity. Your
thread can then post updates to it.

When your activity is stopped or paused, you can interrupt() that
thread to tell it to shut down.
Streets Of Boston
2009-05-28 14:40:50 UTC
Permalink
Hi Mike,

Is it safe to cache a Handler (in a static variable)? Some objects,
such as Activities or Drawables, are not safe to cache statically and
share amongst multiple activity-instances due to possible memory leaks
(memory referencing to destroyed activities that doesn't get cleaned
up in a timely manner).


On May 28, 10:32 am, Mike Hearn <***@gmail.com> wrote:
> You don't need a Service, that's way too complicated for what you
> need. Especially if you use the RPC stuff (optional but the docs don't
> tell you that!)
>
> If you create the progress dialog using the onCreateDialog() method
> then it'll be automatically reconstructed after an orientation
> change.
>
> To receive callbacks as to progress, you can just send to a static
> Handler. Create the Handler in your onCreate if it's not already
> created, so it's shared between all instances of your activity. Your
> thread can then post updates to it.
>
> When your activity is stopped or paused, you can interrupt() that
> thread to tell it to shut down.
Mike Hearn
2009-05-29 16:12:36 UTC
Permalink
On May 28, 4:40 pm, Streets Of Boston <***@gmail.com> wrote:
> Is it safe to cache a Handler (in a static variable)?

It should be OK, from my reading of the code. It keeps a reference to
the current threads looper, but that should exist for as long as the
process does anyway.

I *think* you'd code it up like this, although I haven't actually done
it :)

public class MyActivity extends Activity implements Handler.Callback {
static Object sHandlerLock = new Object();
static Handler sHandler;

public void handleMessage(Message msg) { .... }

public void onCreate() {
synchronized (MyActivity.sHandlerLock) {
sHandler = new Handler(this);
}
}

public void onDestroy() { // Could be onStop as well I think
synchronized (MyActivity.sHandlerLock) {
sHandler = null;
}
if (isFinishing) myThread.interrupt(); // tell the worker thread
to shut down.
}
}

then in your thread:

public void run() {
// ... do some work ....
synchronized (MyActivity.sHandlerLock) {
if (MyActivity.sHandler != null) MyActivity.sHandler.sendMessage
(whatever);
}
}

You have to lock because otherwise you could test sHandler against
null to see if the activity is still around to receive your status
update, find it's set, then the main thread destroys the activity
resulting in your worker thread crashing when it tries to send a
message to the main thread.

Note the call to interrupt() in onDestroy. You don't want your worker
thread to hang around doing stuff when the user is actually done with
your app. I'm not 100% sure this is correct though - the javadoc for
isFinishing() is kinda vague. Eg I don't know if using the home button
counts as "finishing" an activity or just task switching away.
Robert Green
2009-05-28 22:06:45 UTC
Permalink
I dunno, I wrote a really awesome service that can do things a more
simple solution can not - such as, if it is processing something and
the registered callback unregisters, then it finishes processing, I
have it queuing the result. The next callback that registers will get
that result fired immediately, which is the desired result because
this handles the problem of, "What happens if the network process
finishes between when activity 1 is destroyed and activity 2 is
registered?"

So I got everything working with aidl and binding and my queue and all
of that but I have a question about stopping the service. I use
startService() to start it and bindService() to bind to it. I'm not
sure when I should be stopping it because AFAIK, my activity doesn't
know that it's being paused/stopped/destroyed because of a call or
because of an orientation change. Also, I'd like to keep the same
service running for the life of the application - that is, while any
activities are still running in that application. That is the idea of
the service, isn't it? Does anyone have suggestions on how I can
accomplish that?

I'm wondering if I just leave it running, if the OS will eventually
kill it because nothing is bound to it and it is inactive. Can I
count on that?

On May 28, 9:32 am, Mike Hearn <***@gmail.com> wrote:
> You don't need aService, that's way too complicated for what you
> need. Especially if you use the RPC stuff (optional but the docs don't
> tell you that!)
>
> If you create the progress dialog using the onCreateDialog() method
> then it'll be automatically reconstructed after an orientation
> change.
>
> To receive callbacks as to progress, you can just send to a static
> Handler. Create the Handler in your onCreate if it's not already
> created, so it's shared between all instances of your activity. Your
> thread can then post updates to it.
>
> When your activity is stopped or paused, you can interrupt() that
> thread to tell it to shut down.
Mike Hearn
2009-05-28 22:39:04 UTC
Permalink
> I'm wondering if I just leave it running, if the OS will eventually
> kill it because nothing is bound to it and it is inactive.  Can I
> count on that?

No. If you start a service with startService() it is supposed to quit
itself, otherwise it will never die. It's best to pick one of bind or
start and stick with it, unless you are really sure what you are
doing. Don't worry about the service dying, remember that a service is
just a lifecycle construct. If you bind() to it in each activity when
your activities are gone the service will go away too.
Robert Green
2009-05-29 02:58:50 UTC
Permalink
I'm just worried about using bindService alone because I need the
service to stay alive between orientation changes of the activity.
There will be a period when the activity unbinds and the new activity
binds but the service can not be stopped then or it will defeat the
whole purpose of using it.

On May 28, 5:39 pm, Mike Hearn <***@gmail.com> wrote:
> > I'm wondering if I just leave it running, if the OS will eventually
> > kill it because nothing is bound to it and it is inactive.  Can I
> > count on that?
>
> No. If you start a service with startService() it is supposed to quit
> itself, otherwise it will never die. It's best to pick one of bind or
> start and stick with it, unless you are really sure what you are
> doing. Don't worry about the service dying, remember that a service is
> just a lifecycle construct. If you bind() to it in each activity when
> your activities are gone the service will go away too.
Robert Green
2009-05-29 03:53:09 UTC
Permalink
I just tested using only bindService and now it's not doing what I
need it to do. The requirement is to have the service stay running
between orientation changes. Now it stops when the first activity
unbinds and starts new when the new activity binds, losing the current
work (which is a form submission), so now the server has processed
something but the client isn't going to get a response. That doesn't
work for me.

Just in case you guys are wondering, my use case is this (and EVERYONE
that I've seen use the app tries this)

1) User flips open keyboard to fill out text fields
2) User clicks on submit button
3) App contacts server, starts processing, shows progress dialog
4) User flips phone shut
5) App reorients
6) App shows user the result of the operation.

So, how do I keep the service alive between orientations but shut it
down when the user has totally exited the app?

I just came up with a way. What do you think about this?

I have a shut down on a timer if my service isn't doing anything. I
just tested it and it works perfectly. It also ensures that the
service stops in a timely fashion. I know only about 2-3 seconds are
needed for even the worst orientation changes but I just wanted to be
safe. I have my activities calling startService and bindService
onResume and calling unbindService onPause. The whole thing works
well, is seamless to the user, seems really sound and plays nice with
the OS by shutting down when no longer in use.

private void startShutdownThread() {
Log.d(TAG, "Starting shutdown thread");
shutDownThread = new Thread() {
@Override
public void run() {
while (shuttingDown && shutDownCount > 0) {
//Log.d(TAG, "Shutting down in " + shutDownCount);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
shutDownCount--;
}
// if the shut down hasn't been interrupted, then shut 'er down.
if (shuttingDown) {
shuttingDown = false;
stopSelf();
} else {
Log.d(TAG, "Shutdown thread exiting...");
}
}
};
shutDownThread.start();
}

public IBinder onBind(Intent intent) {
Log.d(TAG, "onBind()");
bindCount++;
// if the shutDownThread is running, stop it.
if (shuttingDown) {
Log.d(TAG, "Shutdown thread stopped");
shuttingDown = false;
shutDownThread = null;
}
return mBinder;
}


@Override
public void onRebind(Intent intent) {
Log.d(TAG, "onRebind()");
bindCount++;
// if the shutDownThread is running, stop it.
if (shuttingDown) {
Log.d(TAG, "Shutdown thread stopped");
shuttingDown = false;
shutDownThread = null;
}
}

@Override
public boolean onUnbind(Intent intent) {
Log.d(TAG, "onUnbind()");
bindCount--;
if (bindCount == 0) {
// if no one is bound, start the countdown
shutDownCount = 30;
shuttingDown = true;
startShutdownThread();
}
return true;
}

Done! Man I'm happy to have that working. I've been retrofitting all
the netcode with this service for the past 20 hours of coding and I
can't wait to not be working on this anymore!

On May 28, 9:58 pm, Robert Green <***@gmail.com> wrote:
> I'm just worried about using bindService alone because I need the
> service to stay alive between orientation changes of the activity.
> There will be a period when the activity unbinds and the new activity
> binds but the service can not be stopped then or it will defeat the
> whole purpose of using it.
>
> On May 28, 5:39 pm, Mike Hearn <***@gmail.com> wrote:
>
> > > I'm wondering if I just leave it running, if the OS will eventually
> > > kill it because nothing is bound to it and it is inactive.  Can I
> > > count on that?
>
> > No. If you start a service with startService() it is supposed to quit
> > itself, otherwise it will never die. It's best to pick one of bind or
> > start and stick with it, unless you are really sure what you are
> > doing. Don't worry about the service dying, remember that a service is
> > just a lifecycle construct. If you bind() to it in each activity when
> > your activities are gone the service will go away too.
>
>
Robert Green
2009-05-29 04:58:48 UTC
Permalink
I used the example in APIDemos for the bindable service.

I created AIDL interfaces for it, then I did what I said in my last
post.

It's a ton of code and a lot of overhead for interfaces but once you
get it right, it works really well. I'll probably write a tutorial on
how I did it at some point.

On May 28, 11:24 pm, iDeveloper <***@gmail.com> wrote:
> Hi Robert
>
> Can you please post how you're using the service. I had the same  
> problem and asked this question on 22 May but didn't get a reply.  
> Using managed dialogs gives out errors too on orientation change.
>
> Thanks.
>
> On 29-May-09, at 9:23 AM, Robert Green wrote:
>
>
>
> > I just tested using only bindService and now it's not doing what I
> > need it to do.  The requirement is to have the service stay running
> > between orientation changes.  Now it stops when the first activity
> > unbinds and starts new when the new activity binds, losing the current
> > work (which is a form submission), so now the server has processed
> > something but the client isn't going to get a response.  That doesn't
> > work for me.
>
> > Just in case you guys are wondering, my use case is this (and EVERYONE
> > that I've seen use the app tries this)
>
> > 1) User flips open keyboard to fill out text fields
> > 2) User clicks on submit button
> > 3) App contacts server, starts processing, shows progress dialog
> > 4) User flips phone shut
> > 5) App reorients
> > 6) App shows user the result of the operation.
>
> > So, how do I keep the service alive between orientations but shut it
> > down when the user has totally exited the app?
>
> > I just came up with a way.  What do you think about this?
>
> > I have a shut down on a timer if my service isn't doing anything.  I
> > just tested it and it works perfectly.  It also ensures that the
> > service stops in a timely fashion.  I know only about 2-3 seconds are
> > needed for even the worst orientation changes but I just wanted to be
> > safe.  I have my activities calling startService and bindService
> > onResume and calling unbindService onPause.  The whole thing works
> > well, is seamless to the user, seems really sound and plays nice with
> > the OS by shutting down when no longer in use.
>
> >    private void startShutdownThread() {
> >            Log.d(TAG, "Starting shutdown thread");
> >            shutDownThread = new Thread() {
> >                    @Override
> >                    public void run() {
> >                            while (shuttingDown && shutDownCount > 0) {
> >                                    //Log.d(TAG, "Shutting down in " + shutDownCount);
> >                                    try {
> >                                            Thread.sleep(1000);
> >                                    } catch (InterruptedException e) {
> >                                    }
> >                                    shutDownCount--;
> >                            }
> >                            // if the shut down hasn't been interrupted, then shut 'er down.
> >                            if (shuttingDown) {
> >                                    shuttingDown = false;
> >                                    stopSelf();
> >                            } else {
> >                                    Log.d(TAG, "Shutdown thread exiting...");
> >                            }
> >                    }
> >            };
> >            shutDownThread.start();
> >    }
>
> >    public IBinder onBind(Intent intent) {
> >            Log.d(TAG, "onBind()");
> >            bindCount++;
> >            // if the shutDownThread is running, stop it.
> >            if (shuttingDown) {
> >                    Log.d(TAG, "Shutdown thread stopped");
> >                    shuttingDown = false;
> >                    shutDownThread = null;
> >            }
> >            return mBinder;
> >    }
>
> >    @Override
> >    public void onRebind(Intent intent) {
> >            Log.d(TAG, "onRebind()");
> >            bindCount++;
> >            // if the shutDownThread is running, stop it.
> >            if (shuttingDown) {
> >                    Log.d(TAG, "Shutdown thread stopped");
> >                    shuttingDown = false;
> >                    shutDownThread = null;
> >            }
> >    }
>
> >    @Override
> >    public boolean onUnbind(Intent intent) {
> >            Log.d(TAG, "onUnbind()");
> >            bindCount--;
> >            if (bindCount == 0) {
> >                    // if no one is bound, start the countdown
> >                    shutDownCount = 30;
> >                    shuttingDown = true;
> >                    startShutdownThread();
> >            }
> >            return true;
> >    }
>
> > Done!  Man I'm happy to have that working.  I've been retrofitting all
> > the netcode with this service for the past 20 hours of coding and I
> > can't wait to not be working on this anymore!
>
> > On May 28, 9:58 pm, Robert Green <***@gmail.com> wrote:
> >> I'm just worried about using bindService alone because I need the
> >> service to stay alive between orientation changes of the activity.
> >> There will be a period when the activity unbinds and the new activity
> >> binds but the service can not be stopped then or it will defeat the
> >> whole purpose of using it.
>
> >> On May 28, 5:39 pm, Mike Hearn <***@gmail.com> wrote:
>
> >>>> I'm wondering if I just leave it running, if the OS will eventually
> >>>> kill it because nothing is bound to it and it is inactive.  Can I
> >>>> count on that?
>
> >>> No. If you start a service with startService() it is supposed to  
> >>> quit
> >>> itself, otherwise it will never die. It's best to pick one of bind  
> >>> or
> >>> start and stick with it, unless you are really sure what you are
> >>> doing. Don't worry about the service dying, remember that a  
> >>> service is
> >>> just a lifecycle construct. If you bind() to it in each activity  
> >>> when
> >>> your activities are gone the service will go away too.
>
>
Robert Green
2009-05-29 16:29:42 UTC
Permalink
Mike:

I DO need it to run in the background, that is, while orientation is
changing. The service is also really nice because I can do things
like submit a score in the background while the user is going from the
game back to the game menu. I don't like the static handler idea
because it can't have more advanced capabilities like the queue my
service has. Basically my service guarantees that the network request
will finish and the response will be available to the next registered
callback handler. I really like that.

I know it's more complicated but my app feels really nice and polished
now.


Streets of Boston:

Each bind is prefaced with a startService. This ensures that the
service will be running and will continue to run after the unbind.
The service is smart and shuts itself down so this approach works
perfectly for me. If a rebind happens 30 seconds later, the service
will just start back up in persistent-run-mode like always because
startService will have been called. Since the really important stuff
always happens within a few seconds of an unbind, the restarting later
doesn't matter at all. Also, it will never restart while a user is in
an activity because the activity binds onResume and unbinds onPause,
so it remains bound the entire time it is visible.

I think the way I did it is responsible because the service is always
available when needed but doesn't stick around more than 30 seconds
longer than the user was last in the app.

I'm sure there are other ways but this is coded, well-tested and on
the market so I'm not changing it anytime soon :)

On May 29, 10:43 am, Mike Hearn <***@gmail.com> wrote:
> > Done!  Man I'm happy to have that working.  I've been retrofitting all
> > the netcode with this service for the past 20 hours of coding and I
> > can't wait to not be working on this anymore!
>
> Well, I did show you a simpler way to do it. I'm not sure you should
> write a tutorial on this - like I said, it's a lot more complicated
> than is necessary. You only need a service if you want to run in the
> background when your activities aren't on-screen, which it sounds like
> isn't warranted here.
Robert Green
2009-05-29 20:29:12 UTC
Permalink
Are you trying to tell me that it's totally safe to throw stuff in
static fields? I've always avoided it because of years of shared
space in a JVM in web apps. I know Android uses separate processes
for each application but is it safe to say that it will kill all of
your static allocations even if you don't clean them up properly?

If that's the case, then yes, I probably could have gotten away with
using a static gateway instead of a remote service.

On May 29, 12:18 pm, Mike Hearn <***@gmail.com> wrote:
> > I DO need it to run in the background, that is, while orientation is
> > changing.
>
> That's not "in the background" - the activity manager will keep your
> process alive during configuration changes anyway, regardless of
> whether you have a service or not. The only reason to use a service is
> if you need your process to live on when the activities are not on
> screen.
>
> > I don't like the static handler idea
> > because it can't have more advanced capabilities like the queue my
> > service has.
>
> Sorry, I don't understand this. You can pass any objects you like
> through a handler and handlers use the threads message queue anyway.
> So I don't see why you can't have a queue using a handler.
Mark Murphy
2009-05-29 20:33:17 UTC
Permalink
Robert Green wrote:
> Are you trying to tell me that it's totally safe to throw stuff in
> static fields?

I wouldn't go with "totally safe", but it's an unfortunate requirement
in some Android cases (e.g., sharing a WakeLock between a
BroadcastReceiver triggered by AlarmManager and a Service doing the
actual work being scheduled to run in the background).

> I've always avoided it because of years of shared
> space in a JVM in web apps. I know Android uses separate processes
> for each application but is it safe to say that it will kill all of
> your static allocations even if you don't clean them up properly?

Garbage collection rules still hold, until the whole process is killed
(or, I assume, recycled -- I sincerely hope they flush the heap when
they reuse an existing process).

--
Mark Murphy (a Commons Guy)
http://commonsware.com | http://twitter.com/commonsguy

Need Android talent? Ask on HADO! http://wiki.andmob.org/hado
iDeveloper
2009-05-30 04:42:31 UTC
Permalink
Check out this link - http://www.paxmodept.com/telesto/blogitem.htm?id=766

This works great without calling a service.



On 30-May-09, at 2:03 AM, Mark Murphy wrote:

>
> Robert Green wrote:
>> Are you trying to tell me that it's totally safe to throw stuff in
>> static fields?
>
> I wouldn't go with "totally safe", but it's an unfortunate requirement
> in some Android cases (e.g., sharing a WakeLock between a
> BroadcastReceiver triggered by AlarmManager and a Service doing the
> actual work being scheduled to run in the background).
>
>> I've always avoided it because of years of shared
>> space in a JVM in web apps. I know Android uses separate processes
>> for each application but is it safe to say that it will kill all of
>> your static allocations even if you don't clean them up properly?
>
> Garbage collection rules still hold, until the whole process is killed
> (or, I assume, recycled -- I sincerely hope they flush the heap when
> they reuse an existing process).
>
> --
> Mark Murphy (a Commons Guy)
> http://commonsware.com | http://twitter.com/commonsguy
>
> Need Android talent? Ask on HADO! http://wiki.andmob.org/hado
>
> >
iDeveloper
2009-05-29 04:24:55 UTC
Permalink
Hi Robert

Can you please post how you're using the service. I had the same
problem and asked this question on 22 May but didn't get a reply.
Using managed dialogs gives out errors too on orientation change.

Thanks.



On 29-May-09, at 9:23 AM, Robert Green wrote:

>
> I just tested using only bindService and now it's not doing what I
> need it to do. The requirement is to have the service stay running
> between orientation changes. Now it stops when the first activity
> unbinds and starts new when the new activity binds, losing the current
> work (which is a form submission), so now the server has processed
> something but the client isn't going to get a response. That doesn't
> work for me.
>
> Just in case you guys are wondering, my use case is this (and EVERYONE
> that I've seen use the app tries this)
>
> 1) User flips open keyboard to fill out text fields
> 2) User clicks on submit button
> 3) App contacts server, starts processing, shows progress dialog
> 4) User flips phone shut
> 5) App reorients
> 6) App shows user the result of the operation.
>
> So, how do I keep the service alive between orientations but shut it
> down when the user has totally exited the app?
>
> I just came up with a way. What do you think about this?
>
> I have a shut down on a timer if my service isn't doing anything. I
> just tested it and it works perfectly. It also ensures that the
> service stops in a timely fashion. I know only about 2-3 seconds are
> needed for even the worst orientation changes but I just wanted to be
> safe. I have my activities calling startService and bindService
> onResume and calling unbindService onPause. The whole thing works
> well, is seamless to the user, seems really sound and plays nice with
> the OS by shutting down when no longer in use.
>
> private void startShutdownThread() {
> Log.d(TAG, "Starting shutdown thread");
> shutDownThread = new Thread() {
> @Override
> public void run() {
> while (shuttingDown && shutDownCount > 0) {
> //Log.d(TAG, "Shutting down in " + shutDownCount);
> try {
> Thread.sleep(1000);
> } catch (InterruptedException e) {
> }
> shutDownCount--;
> }
> // if the shut down hasn't been interrupted, then shut 'er down.
> if (shuttingDown) {
> shuttingDown = false;
> stopSelf();
> } else {
> Log.d(TAG, "Shutdown thread exiting...");
> }
> }
> };
> shutDownThread.start();
> }
>
> public IBinder onBind(Intent intent) {
> Log.d(TAG, "onBind()");
> bindCount++;
> // if the shutDownThread is running, stop it.
> if (shuttingDown) {
> Log.d(TAG, "Shutdown thread stopped");
> shuttingDown = false;
> shutDownThread = null;
> }
> return mBinder;
> }
>
>
> @Override
> public void onRebind(Intent intent) {
> Log.d(TAG, "onRebind()");
> bindCount++;
> // if the shutDownThread is running, stop it.
> if (shuttingDown) {
> Log.d(TAG, "Shutdown thread stopped");
> shuttingDown = false;
> shutDownThread = null;
> }
> }
>
> @Override
> public boolean onUnbind(Intent intent) {
> Log.d(TAG, "onUnbind()");
> bindCount--;
> if (bindCount == 0) {
> // if no one is bound, start the countdown
> shutDownCount = 30;
> shuttingDown = true;
> startShutdownThread();
> }
> return true;
> }
>
> Done! Man I'm happy to have that working. I've been retrofitting all
> the netcode with this service for the past 20 hours of coding and I
> can't wait to not be working on this anymore!
>
> On May 28, 9:58 pm, Robert Green <***@gmail.com> wrote:
>> I'm just worried about using bindService alone because I need the
>> service to stay alive between orientation changes of the activity.
>> There will be a period when the activity unbinds and the new activity
>> binds but the service can not be stopped then or it will defeat the
>> whole purpose of using it.
>>
>> On May 28, 5:39 pm, Mike Hearn <***@gmail.com> wrote:
>>
>>>> I'm wondering if I just leave it running, if the OS will eventually
>>>> kill it because nothing is bound to it and it is inactive. Can I
>>>> count on that?
>>
>>> No. If you start a service with startService() it is supposed to
>>> quit
>>> itself, otherwise it will never die. It's best to pick one of bind
>>> or
>>> start and stick with it, unless you are really sure what you are
>>> doing. Don't worry about the service dying, remember that a
>>> service is
>>> just a lifecycle construct. If you bind() to it in each activity
>>> when
>>> your activities are gone the service will go away too.
>>
>>
> >
Streets Of Boston
2009-05-29 15:18:55 UTC
Permalink
"So, how do I keep the service alive between orientations but shut it
down when the user has totally exited the app?"

I use this 'trick' to figure out if an onDestroy is really a destroy
or just a configuration change by the user (e.g. closing keyboard):

Use onRetainNonConfigurationInstance() and
getLastNonConfigurationInstance().

...
boolean mDoDestroy = true;
...
public Object onRetainNonConfigurationInstance() {
mDoDestroy = false;
return someObject;
}

protected void onDestroy() {
if (mDoDestroy) {
// shut down your services or something that is necessary
// after your app is actuall destroyed. Clean up everything.
}
else {
// A configuration-change happened.. e.g. the user
// just opened or closed the keyboard. Don't destroy/cleanup
// everything. Keep things around that are necessary for the next
// instance of this activity.
}
}


On May 28, 11:53 pm, Robert Green <***@gmail.com> wrote:
> I just tested using only bindService and now it's not doing what I
> need it to do.  The requirement is to have the service stay running
> between orientation changes.  Now it stops when the first activity
> unbinds and starts new when the new activity binds, losing the current
> work (which is a form submission), so now the server has processed
> something but the client isn't going to get a response.  That doesn't
> work for me.
>
> Just in case you guys are wondering, my use case is this (and EVERYONE
> that I've seen use the app tries this)
>
> 1) User flips open keyboard to fill out text fields
> 2) User clicks on submit button
> 3) App contacts server, starts processing, shows progress dialog
> 4) User flips phone shut
> 5) App reorients
> 6) App shows user the result of the operation.
>
> So, how do I keep the service alive between orientations but shut it
> down when the user has totally exited the app?
>
> I just came up with a way.  What do you think about this?
>
> I have a shut down on a timer if my service isn't doing anything.  I
> just tested it and it works perfectly.  It also ensures that the
> service stops in a timely fashion.  I know only about 2-3 seconds are
> needed for even the worst orientation changes but I just wanted to be
> safe.  I have my activities calling startService and bindService
> onResume and calling unbindService onPause.  The whole thing works
> well, is seamless to the user, seems really sound and plays nice with
> the OS by shutting down when no longer in use.
>
>         private void startShutdownThread() {
>                 Log.d(TAG, "Starting shutdown thread");
>                 shutDownThread = new Thread() {
>                         @Override
>                         public void run() {
>                                 while (shuttingDown && shutDownCount > 0) {
>                                         //Log.d(TAG, "Shutting down in " + shutDownCount);
>                                         try {
>                                                 Thread.sleep(1000);
>                                         } catch (InterruptedException e) {
>                                         }
>                                         shutDownCount--;
>                                 }
>                                 // if the shut down hasn't been interrupted, then shut 'er down.
>                                 if (shuttingDown) {
>                                         shuttingDown = false;
>                                         stopSelf();
>                                 } else {
>                                         Log.d(TAG, "Shutdown thread exiting...");
>                                 }
>                         }
>                 };
>                 shutDownThread.start();
>         }
>
>         public IBinder onBind(Intent intent) {
>                 Log.d(TAG, "onBind()");
>                 bindCount++;
>                 // if the shutDownThread is running, stop it.
>                 if (shuttingDown) {
>                         Log.d(TAG, "Shutdown thread stopped");
>                         shuttingDown = false;
>                         shutDownThread = null;
>                 }
>                 return mBinder;
>         }
>
>         @Override
>         public void onRebind(Intent intent) {
>                 Log.d(TAG, "onRebind()");
>                 bindCount++;
>                 // if the shutDownThread is running, stop it.
>                 if (shuttingDown) {
>                         Log.d(TAG, "Shutdown thread stopped");
>                         shuttingDown = false;
>                         shutDownThread = null;
>                 }
>         }
>
>         @Override
>         public boolean onUnbind(Intent intent) {
>                 Log.d(TAG, "onUnbind()");
>                 bindCount--;
>                 if (bindCount == 0) {
>                         // if no one is bound, start the countdown
>                         shutDownCount = 30;
>                         shuttingDown = true;
>                         startShutdownThread();
>                 }
>                 return true;
>         }
>
> Done!  Man I'm happy to have that working.  I've been retrofitting all
> the netcode with this service for the past 20 hours of coding and I
> can't wait to not be working on this anymore!
>
> On May 28, 9:58 pm, Robert Green <***@gmail.com> wrote:
>
>
>
> > I'm just worried about using bindService alone because I need the
> > service to stay alive between orientation changes of the activity.
> > There will be a period when the activity unbinds and the new activity
> > binds but the service can not be stopped then or it will defeat the
> > whole purpose of using it.
>
> > On May 28, 5:39 pm, Mike Hearn <***@gmail.com> wrote:
>
> > > > I'm wondering if I just leave it running, if the OS will eventually
> > > > kill it because nothing is bound to it and it is inactive.  Can I
> > > > count on that?
>
> > > No. If you start a service with startService() it is supposed to quit
> > > itself, otherwise it will never die. It's best to pick one of bind or
> > > start and stick with it, unless you are really sure what you are
> > > doing. Don't worry about the service dying, remember that a service is
> > > just a lifecycle construct. If you bind() to it in each activity when
> > > your activities are gone the service will go away too.- Hide quoted text -
>
> - Show quoted text -
Streets Of Boston
2009-05-29 15:25:49 UTC
Permalink
This code seems to rely on the fact that your background thread does
not die immediately. If your service is rebound within 30 * 1000
milliseconds, then it all works well.

- This is an unlikely scenario, but what if the re-bind happens more
than 30 seconds later?
- What if the service is stopped entirely and - when your activity (re)
binds - a brand new instance of your service is started? Not very
likely scenario either, but i'm not sure that it could never happen.

Why, instead, don't you keep your service alive by calling startService
()? This makes sure that any subsequent 'unbind' does not stop and
destroy your service.

On May 28, 11:53 pm, Robert Green <***@gmail.com> wrote:
> I just tested using only bindService and now it's not doing what I
> need it to do.  The requirement is to have the service stay running
> between orientation changes.  Now it stops when the first activity
> unbinds and starts new when the new activity binds, losing the current
> work (which is a form submission), so now the server has processed
> something but the client isn't going to get a response.  That doesn't
> work for me.
>
> Just in case you guys are wondering, my use case is this (and EVERYONE
> that I've seen use the app tries this)
>
> 1) User flips open keyboard to fill out text fields
> 2) User clicks on submit button
> 3) App contacts server, starts processing, shows progress dialog
> 4) User flips phone shut
> 5) App reorients
> 6) App shows user the result of the operation.
>
> So, how do I keep the service alive between orientations but shut it
> down when the user has totally exited the app?
>
> I just came up with a way.  What do you think about this?
>
> I have a shut down on a timer if my service isn't doing anything.  I
> just tested it and it works perfectly.  It also ensures that the
> service stops in a timely fashion.  I know only about 2-3 seconds are
> needed for even the worst orientation changes but I just wanted to be
> safe.  I have my activities calling startService and bindService
> onResume and calling unbindService onPause.  The whole thing works
> well, is seamless to the user, seems really sound and plays nice with
> the OS by shutting down when no longer in use.
>
>         private void startShutdownThread() {
>                 Log.d(TAG, "Starting shutdown thread");
>                 shutDownThread = new Thread() {
>                         @Override
>                         public void run() {
>                                 while (shuttingDown && shutDownCount > 0) {
>                                         //Log.d(TAG, "Shutting down in " + shutDownCount);
>                                         try {
>                                                 Thread.sleep(1000);
>                                         } catch (InterruptedException e) {
>                                         }
>                                         shutDownCount--;
>                                 }
>                                 // if the shut down hasn't been interrupted, then shut 'er down.
>                                 if (shuttingDown) {
>                                         shuttingDown = false;
>                                         stopSelf();
>                                 } else {
>                                         Log.d(TAG, "Shutdown thread exiting...");
>                                 }
>                         }
>                 };
>                 shutDownThread.start();
>         }
>
>         public IBinder onBind(Intent intent) {
>                 Log.d(TAG, "onBind()");
>                 bindCount++;
>                 // if the shutDownThread is running, stop it.
>                 if (shuttingDown) {
>                         Log.d(TAG, "Shutdown thread stopped");
>                         shuttingDown = false;
>                         shutDownThread = null;
>                 }
>                 return mBinder;
>         }
>
>         @Override
>         public void onRebind(Intent intent) {
>                 Log.d(TAG, "onRebind()");
>                 bindCount++;
>                 // if the shutDownThread is running, stop it.
>                 if (shuttingDown) {
>                         Log.d(TAG, "Shutdown thread stopped");
>                         shuttingDown = false;
>                         shutDownThread = null;
>                 }
>         }
>
>         @Override
>         public boolean onUnbind(Intent intent) {
>                 Log.d(TAG, "onUnbind()");
>                 bindCount--;
>                 if (bindCount == 0) {
>                         // if no one is bound, start the countdown
>                         shutDownCount = 30;
>                         shuttingDown = true;
>                         startShutdownThread();
>                 }
>                 return true;
>         }
>
> Done!  Man I'm happy to have that working.  I've been retrofitting all
> the netcode with this service for the past 20 hours of coding and I
> can't wait to not be working on this anymore!
>
> On May 28, 9:58 pm, Robert Green <***@gmail.com> wrote:
>
>
>
> > I'm just worried about using bindService alone because I need the
> > service to stay alive between orientation changes of the activity.
> > There will be a period when the activity unbinds and the new activity
> > binds but the service can not be stopped then or it will defeat the
> > whole purpose of using it.
>
> > On May 28, 5:39 pm, Mike Hearn <***@gmail.com> wrote:
>
> > > > I'm wondering if I just leave it running, if the OS will eventually
> > > > kill it because nothing is bound to it and it is inactive.  Can I
> > > > count on that?
>
> > > No. If you start a service with startService() it is supposed to quit
> > > itself, otherwise it will never die. It's best to pick one of bind or
> > > start and stick with it, unless you are really sure what you are
> > > doing. Don't worry about the service dying, remember that a service is
> > > just a lifecycle construct. If you bind() to it in each activity when
> > > your activities are gone the service will go away too.- Hide quoted text -
>
> - Show quoted text -
Mike Hearn
2009-05-29 15:43:54 UTC
Permalink
> Done!  Man I'm happy to have that working.  I've been retrofitting all
> the netcode with this service for the past 20 hours of coding and I
> can't wait to not be working on this anymore!

Well, I did show you a simpler way to do it. I'm not sure you should
write a tutorial on this - like I said, it's a lot more complicated
than is necessary. You only need a service if you want to run in the
background when your activities aren't on-screen, which it sounds like
isn't warranted here.
Mike Hearn
2009-05-29 17:18:05 UTC
Permalink
> I DO need it to run in the background, that is, while orientation is
> changing.

That's not "in the background" - the activity manager will keep your
process alive during configuration changes anyway, regardless of
whether you have a service or not. The only reason to use a service is
if you need your process to live on when the activities are not on
screen.

> I don't like the static handler idea
> because it can't have more advanced capabilities like the queue my
> service has.

Sorry, I don't understand this. You can pass any objects you like
through a handler and handlers use the threads message queue anyway.
So I don't see why you can't have a queue using a handler.
Mike Hearn
2009-05-30 12:16:54 UTC
Permalink
> Are you trying to tell me that it's totally safe to throw stuff in
> static fields?

You have to be careful you don't accidentally pin things into memory,
eg, putting a View or a Drawable or anything that inherits from
Context into a static field would be a bad idea. Otherwise it's not a
problem.

I wish Android provided a nicer way to solve this problem though. The
AsyncTask stuff helps but it still breaks on orientation change.
Loading...