Hi Bob,

Thanks a lot for this. This helped me to understand a lot of things.
I found out a good way for starting/stopping a service here:
http://www.brighthub.com/mobile/google-android/articles/34861.aspx

What do you think of this one ?
Cheers,
Tejas

On Apr 18, 7:03 pm, Bob Kerns <[email protected]> wrote:
> OK, I understand your thinking a bit better, so hopefully I can
> explain a bit better.
>
> onDestroy() is only called when your application is idle. The system
> will NEVER directly call a lifecycle method except when the main
> thread is idle If you are running some long-lived function from, say,
> onStart(), or a handler in the main thread.  All of these are handled
> one at a time by the main thread's Looper.
>
> So there will be no abrupt termination of your function when
> onDestroy() is called. That only happens if it kills off the process.
> Which is a lot more likely to happen if you block the main thread --
> after a while, the user will get a dialog offering to kill or wait for
> the busy process!
>
> Java used to support interrupting and abruptly terminating threads.
> However, there is absolutely NO way to make this a safe operation.
> Android does kill off processes, which can leave things outside the
> process in an inconsistent state, but that's not as bad as having your
> application still running, but in an inconsistent state internally! So
> abruptly force-quitting a method is not part of the model of any Java
> system. (But you can still check, and throw an exception to get out of
> a loop -- that will properly invoke all finally() clauses on the way
> out, etc.).
>
> It's hard for me to tell you the "proper" way to stop your service,
> because it depends on just what you're doing. You have part of the
> idea, by checking for a termination flag in your loop. You can set
> that in your onDestroy() method -- akin to what you're trying to do
> with your call to the undocumented Looper.quit() method.  But what you
> want to do is to set your CARuntimes.MainServiceRunFlag  instead.
> (Except I'd make that an instance member of your Service class, rather
> than a static of some other class. Better modularity, though you can
> make it work this way).
>
> It looks to me like what you're really trying to do, is what the
> system already provides for you better -- IntentService. I really
> don't know what their intent was, calling it this -- I think I'd call
> it ThreadedService, since the relevant point is that it runs your code
> in a separate thread. Or maybe HandlerThreadService, since it uses a
> handler to serialize the requests for work. You still have to be
> careful about things that queue up things to the current thread's
> looper -- like Toast, for example. Any deferred processing you want to
> queue up to a handler you set up in the IntentService's onCreate
> method (i.e. on the main thread).
>
> Anyway, the purpose of HandlerThread's and Handler's is not clean
> shutdown, but rather the queuing of messages via a Looper and
> associated MessageQueue.  If you're only handling one message, ever,
> then creating your own thread would make sense. An AsyncTask would be
> a good choice if you're only running for a short time (but too long
> for the main thread). But if this is something that runs for an
> extended period of time, it would potentially block other uses of
> AsyncTask, so your own thread is a better choice.
>
> So anyway, to summarize -- Handler's, HandlerThread's, and
> IntentService give you a way to do one thing at a time in another
> thread. AsyncTasks give you a way to do a small number of small things
> in parallel (in some versions of the system, one thing at a time).
> Long-lived things need their own threads -- HandlerThread and
> IntentService can provide this. You stop a thread by testing for some
> condition in the loop in the thread. If the thread needs to wait, use
> wait(), and use notifyAll() to wake it up after you set the flag. Be
> sure to use the synchronized keyword to coordinate in this case! And
> if you loop within a handler, you're basically occupying that thread
> while you're looping. So be careful not to queue up any additional
> work to that thread's looper. (And often it needs to go to the main
> thread anyway -- for example, all GUI operations need to be run
> there).
>
> Sorry I can't make all that simple! Threading is never really simple.
> But there are simple patterns, and if you carefully stay within those
> simple patterns, you can avoid most of the complexity.
>
> Finally, about getApplicationContext() -- unfortunately, in the
> released versions of the documentation, there are some bad examples
> around this. I understand they've been fixed for the next release of
> the SDK. But if you're in an Activity or a Service, you just supply
> that activity or service, via the "this" pseudo-variable. However, in
> your case, your use isn't directly in the service, but in your nested
> ServiceHandler class, so "this" will refer to that instance instead.
> But you can still refer to the outer instance's this, by writing
> "ManagerService.this". You could also arrange to pass the context in
> ass a parameter when you create your ManagerService -- but since the
> system already does that work for you with a nested class, there's no
> reason. Just replace getApplicationContext() with ManagerService.this,
> and you're set.
>
> .
> On Apr 18, 11:08 am, Tejas <[email protected]> wrote:
>
>
>
> > > If you're going to do that, why involve a handler
> > > at all?
>
> > Now suppose, I use any other function in my service class instead of
> > handler and say I'm performing a time consuming task in that function.
> > If the onDestroy method of the service is called, I assume that it
> > will terminate my function abruptly. I'm not sure of this, but I
> > thought so and hence used the Handler thread to have a proper
> > shutdown. please correct me if I'm wrong. Also let me know the right
> > way to stop the service.
>
> > > Finally, never, ever, call getApplicationContext(). The return value
> > > is not useful to us mortals. Supply the service itself as the context.
>
> > I'm still not sure what are you saying. How will you supply the
> > service as the context ? Can you provide an example ?
>
> > On Apr 18, 2:56 am, Bob Kerns <[email protected]> wrote:
>
> > > Actually, just because something is a background service does NOT mean
> > > it is running in a different thread.
>
> > > Background services run in the main thread. I suspect that this point
> > > of confusion may be involved in your problem, though I don't quite
> > > spot the problem.
>
> > > Also, you have a handler there that basically loops forever. That's
> > > kind of an oxymoron. If you're going to do that, why involve a handler
> > > at all? If I parse it correctly, it's not the main thread it'll be
> > > blocking, but still... if something in that thread is posting via that
> > > thread's looper rather than the context, that won't be processed.
>
> > > Finally, never, ever, call getApplicationContext(). The return value
> > > is not useful to us mortals. Supply the service itself as the context.
> > > To make things maximally confusing, getApplicationContext() will
> > > appear to work in most circumstances. But it's always the wrong way to
> > > get a context to use.
>
> > > On Apr 17, 2:05 pm, Tejas <[email protected]> wrote:
>
> > > > Ah... I got this working. Still I'm not sure of the reason for this
> > > > (some thread issue I suppose) It would be great if someone can throw
> > > > some light on this.
>
> > > > I was instantiating the sensor class in a background service.So the
> > > > thread in which it was running was different than the main thread.
> > > > I was doing something like this:
>
> > > > public class ManagerService extends Service {
>
> > > >         private final String LTAG = this.getClass().getName();
> > > >         private volatile Looper mServiceLooper;
> > > >         private volatile ServiceHandler mServiceHandler;
>
> > > >         private final class ServiceHandler extends Handler{
> > > >                 public ServiceHandler(Looper myLooper) {
> > > >                         super(myLooper);
> > > >                 }
>
> > > >                 public void handleMessage(Message msg) {
> > > >                         Log.v(LTAG, "handleMessage Called");
> > > >                         super.handleMessage(msg);
>
> > > >                         // Class Instantiation
> > > >                         GPSSensor gs = new GPSSensor();
> > > >                         gs.setContext(getApplicationContext());
> > > >                         gs.startSensing()
>
> > > >                         // Main service loop
> > > >                         while(CARuntimes.MainServiceRunFlag == true){
> > > >                                 Log.v(LTAG, "In service Loop");
> > > >                                 // Do something
>
> > > >                                 SystemClock.sleep(60000);
>
> > > >                         }//while
>
> > > >                 }
> > > >         }
>
> > > >         public void onCreate() {
> > > >                 super.onCreate();
> > > >                 HandlerThread myThread = new HandlerThread("Main 
> > > > Service Thread");
> > > >                 myThread.start();
>
> > > >                 mServiceLooper = myThread.getLooper();
> > > >                 mServiceHandler = new ServiceHandler(mServiceLooper);
> > > >         }
>
> > > >         public void onStart(Intent intent, int startId) {
> > > >                 super.onStart(intent, startId);
>
> > > >                 Message msg = mServiceHandler.obtainMessage();
> > > >                 //msg.obj = blah blah
> > > >                 mServiceHandler.sendMessage(msg);
>
> > > >         }
>
> > > >         public void onDestroy() {
> > > >                 Log.v(LTAG, "onDestroy called, quitting looper");
> > > >                 super.onDestroy();
>
> > > >                 mServiceLooper.quit();
> > > >         }
>
> > > >         public IBinder onBind(Intent arg0) {
> > > >                 return
>
> ...
>
> read more »

-- 
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en

Reply via email to