Feb 2 | 8:50 PM |
Mark M. | has entered the room |
Mark M. | turned on guest access |
Feb 2 | 8:55 PM |
Terry S. | has entered the room |
Terry S. | Hello again. |
Mark M. | howdy! |
Terry S. | You opened a little early -- at least according to my atomic clock. Too bad I only came to observe. LOL |
Mark M. | I usually open a few minutes early |
Terry S. | OK |
Feb 2 | 9:00 PM |
Sean S. | has entered the room |
Mark M. | Not sure if we'll get many people -- Lost premiere right now |
Mark M. | but Sean's here! |
Mark M. | hi, Sean! |
Scott Q. | has entered the room |
Sean S. | Hi, how's it going! |
Mark M. | in the middle of week #3 of a 4-week Android training round |
Mark M. | I'll be grateful when I can get (and stay) home for a bit |
Sean S. | Thanks for the books - just bought them today - and thanks for all the Android answers I've been finding through Google searches |
Mark M. | happy to help! |
Terry S. | Geez, I am usually wiped out after a day of training. |
Mark M. | hi, Scott! |
Scott Q. | Hi Mark |
Sean S. | May I start with a question? |
Mark M. | go right ahead! |
Sean S. | I
have noticed that after you start an Activity form the onReceive()
method of a BroadcastReceiver, that the application will appear in the
"recent apps" list (press-hold HOME key.) |
Sean S. | Android seems to reuse this Intent when the user selects the application from the "recent apps" list. |
Sean S. | How might my Activity differentiate between the two senders (my onReceive method vs. the application manager?) |
Mark M. | Well, you have a few options |
Feb 2 | 9:05 PM |
Sean S. | I like options! |
Mark M. | If you would prefer the activity from the receiver not be in the recent apps list, use FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS. |
Mark M. | (in the Intent, that is) |
Sean S. | Great! I needed to know that. |
Sean S. | (I'm from the Java ME space; Android has a bazillion more tweaks and options that I'm still learning) |
Mark M. | Or,
if you wanted it to appear in the recent-apps list but just tell them
apart, have your Activity look at its Intent (via getIntent()), and if
FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY is set, then it was started from
the recent-apps list |
Mark M. | I haven't tried either of these, mind you, but that what those flags' roles appear to be from the docs |
Sean S. | Cool. And how might I detect if Android has restarted a Service of mine that it killed? |
Sean S. | (apparently there is no way to detect that you are being killed) |
Mark M. | Well, that depends on how you're being killed. |
Mark M. | If it's a normal shutdown, your service will be called with onDestroy(). |
Mark M. | If Android decided to terminate your process, you won't get any notice. |
Mark M. | In either case, your service will be called with onCreate() when it is next started. |
Mark M. | Usually,
Android only kills services that try to live for a long time, which is
why you really want to try to avoid long-lived services where possible. |
Mark M. | See http://www.androidguys.com/2009/09/09/diam… for more |
Feb 2 | 9:10 PM |
Sean S. | Right.
I thought I was terminating the service after it timed out, but
discovered it running again some time later "by itself". Perhaps I did
not really kill it. Thanks. |
Sean S. | I have another question but I'll let others ask theirs for a while. |
Terry S. | I am good, go ahead. |
Mark M. | Scott: got any questions? |
Scott Q. | Sean can finish up |
Mark M. | Sean: go ahead, then |
Scott Q. | still forming mine :) |
Sean S. | OK then... |
Sean S. | I've learned the hard way that Services can't run forever and TimerTasks in services sometimes are not started. |
Mark M. | Yup |
Sean S. | So I'm looking at using AlarmManager/BroadcastIntent/WakeLock/Service to do this |
Sean S. | This gives me three Broadcast intents I have to deal with: |
Sean S. | (well first let me describe the background activity - I need to send a message periodically) |
Sean S. | The first broadcast Intent is a custom Intent from another application to start the background activity. |
Feb 2 | 9:15 PM |
Mark M. | "background activity"? |
Feb 2 | 9:15 PM |
Sean S. | Basically, send a group of text messages. Sorry, I am overloading Android terminology |
Mark M. | Ah, OK |
Sean S. | it's not an Activity and it is not a "background"/"foreground" thing, sorry |
Sean S. | The
second broadcast(s) will be from the AlarmManager. Planning to schedule
a repeated alarm and send a group of messages each time |
Sean S. | The
third broadcast is BOOT_COMPLETED. Since the repeated alarm goes away
when the phone is powered off, and I have to finish sending the
messages, I use BOOT_COMPLETED to continue when the phone restarts. |
Mark M. | OK, that all seems reasonable |
Sean S. | I
*think* I want to do the message sending from a Service - aquire a
WakeLock in the BroadcastReceiver and release it when the last message
is sent |
Mark M. | Yup |
Mark M. | You can even use my WakefulIntentService for that |
Sean S. | I
am concerned about not completing the sending task in the Service
before I get the next Broadcast Intent. I am not clear about the
Service lifecycle, possible reentrance???? |
Mark M. | Another reason to use WakefulIntentService |
Mark M. | It will queue up the tasks |
Sean S. | Can
you suggest a pattern? For example, the "trigger" can happen any time,
even while I'm sending messages (I would just ignore it) |
Sean S. | OK, I will check out that API |
Mark M. | |
Mark M. | It gets that from IntentService -- the "wakeful" part is what I've added |
Feb 2 | 9:20 PM |
Mark M. | Used
properly, it will keep the device awake until all your queued up
requests are processed, then the service will release the WakeLock and
the service will shut down |
Mark M. | OK, who is up next? |
Scott Q. | I'm ready unless Terry has something |
Terry S. | Still good. |
Scott Q. | I have some fundamental questions regarding best practices for using LocationManager. |
Scott Q. | I
have what I would think is a pretty common scenario -- I need to access
the current gps location from one of my activities, which I do with
getLastKnownLocation. I'd like to ensure this is not stale, so I've set
up a LocationListener called w/ requestLocationUpdates. |
Mark M. | Um, OK |
Mark M. | Yup. |
Scott Q. | I've
noticed that when I am somewhere I cannot acquire location, the gps
icon remains indefinitely as it keeps trying to acquire, killing the
battery. |
Scott Q. | I
could implement my own timeout mechanism and then call removeUpdates,
an manage when/if I want to try again, but do not know if this is what
I should be doing. |
Feb 2 | 9:25 PM |
Mark M. | I'm not sure what else you can really do |
Mark M. | There's no event saying "um, there's no event" for GPS |
Scott Q. | Also,
potentially compounding the problem is that I don't think I am setting
up th LM in the right place -- my app has several activites none of
which are guaranteed to be open at a given time |
Mark M. | Would be nice if the API supported some sort of failure listener and timeout |
Scott Q. | yeah, that is what I thought I might be missing |
Mark M. | Sounds like perhaps the location management should be coordinated by a service |
Mark M. | Use the local binding pattern so the service only runs when there is 1+ activities needing location info |
Sean S. | that is a neat idea |
Scott Q. | Ok, I will look into that, thanks |
Sean S. | btw, thanks for pointing me towards the IntentService API; I had completely missed that one. that will help me a LOT |
Mark M. | Yeah, it's a little-known gem. |
Feb 2 | 9:30 PM |
Sean S. | If
I care about how old the Intent is (if it took me a long time to get
around to dealing with it), I should probably do something like store
System.currentTimeMillis as an extra? |
Mark M. | yes, but... |
Mark M. | if you use extras, you will want to be careful when wrapping your Intents in PendingIntents (e.g., for AlarmManager) |
Mark M. | Specifically, you'll probably want to use PendingIntent.FLAG_ONE_SHOT |
Mark M. | PendingIntents have this annoying habit of recycling existing Intents that match on criteria other than extras |
Mark M. | Hence, the PendingIntent would have an old time, not the newer time from your newer Intent |
Mark M. | FLAG_ONE_SHOT should inhibit that behavior |
Sean S. | That's good to know. |
Feb 2 | 9:35 PM |
Sean S. | So
to use IntentService, does my Service class extend IntentService, and
then every time my BroadcastReceiver gets an Intent I need to act on,
in onReceive() I create a new Intent with my service class as the
target and call startService, and in my service class, onHandleIntent
will be called? (ignoring wake locks for a sec) |
Mark M. | No |
Mark M. | Step #1: Create a custom service that extends IntentService |
Mark M. | Oh, wait |
Mark M. | No, what you have is correct |
Mark M. | I got confused when reading what you had there |
Feb 2 | 9:40 PM |
Sean S. | I was going to apologize for trying to figure out the API in 15 seconds ;-) |
Mark M. | Note
that onHandleIntent() is called on a background thread (managed by
Android), so you can take as long as you need without timeout concerns |
Scott Q. | has left the room |
Sean S. | so
"all I need to do" is make sure that I'm doing my work (and saving my
work's state) in a threadsafe way, in case onHandleIntent is called
while a prior onHandleIntent method is still running. Sounds like
onHandleIntent is kind of like a run() method. |
Mark M. | I think there's only one thread for onHandleIntent() |
Sean S. | really! so it is automatically threadsafe? cool! |
Mark M. | "An
abstract Service that serializes the handling of the Intents passed
upon service start and handles them on a handler thread. " |
Sean S. | yep |
Sean S. | will have to write a test app to confirm that, but cool |
Feb 2 | 9:45 PM |
Sean S. | do
you think I might have to worry about Android coalescing Intents or
dropping any if they start building up? (I think I will need to send
them at one minute intervals at the most. I don't expect them to bunch
up.) |
Mark M. | I don't think so |
Mark M. | Bear in mind, though, that you're going to really eat up the battery if you do work at that pace |
Sean S. | OK, if there is one thing I've learned about Android, it is to expect the unexpected. the source does come in handy |
Sean S. | right |
Sean S. | does Terry have any questions? |
Terry S. | No, just watching. |
Gerardo B. | has entered the room |
Sean S. | After
seeing Android stop services and drop TimerTasks, I am concerned that
the AlarmManager might stop delivering recurring alarms at some point.
Is this something you've seen? |
Gerardo B. | hello |
Mark M. | howdy, Gerardo! |
Sean S. | Hi, Gerardo! |
Mark M. | Sean: I have not heard of problems like that with AlarmManager, other than if the device reboots |
Mark M. | The
one exception are the notorious "task killer" apps, which exploit an
SDK loophole and will cause your alarms to become deregistered, along
with killing off everything of yours that runs |
Sean S. | Any way to detect that one of those has killed you? |
Mark M. | Not that I am awareof |
Feb 2 | 9:50 PM |
Mark M. | er, aware of |
Gerardo B. | Has
anybody gotten "WARN/System.err(727): Can't dispatch DDM chunk
46454154: no handler defined" later? I didn't see this before, but
yesterday it starting appearing when launching emulators. I can still
run but I'd like to know what that is... |
Sean S. | well,
just will have to let my customer know this. I'll let Gerardo have the
floor now. thanks, do have another Q but may run out of time. |
Gerardo B. | thanks Sean |
Mark M. | Gerardo: that used to occur to me on occasion |
Mark M. | mostly, it was when I had one version of the adb daemon (say, 1.5) and a different version of the emulator (say, 1.6) |
Mark M. | I haven't run into that problem in recent months, though |
Mark M. | Not
sure if that's just because I cleaned up my SDK installations or due to
the new way the SDKs are distributed (downloaded via the AVD Manager) |
Gerardo B. | k, as I said it's mostly an annoyance... I'll check the versions |
Sean S. | Here's a clue: http://groups.google.com/group/android-dev… |
Sean S. | sounds like versioning may be the ticket |
Feb 2 | 9:55 PM |
Mark M. | OK, well, that's a wrap for this week's office hours chat |
Sean S. | Mark,
I have your three books now; which might give a good description of the
Activity history and the concept of tasks? It is almost as if a Task
was going to be an object but then was removed from the API? (or have I
missed it?) |
Mark M. | Sean: none of them at present |
Gerardo B. | (Mark, great books, btw) |
Mark M. | Thanks! |
Feb 2 | 10:00 PM |
Mark M. | I have an hour scheduled for next week, and then I hope to get back to two hours a week for a while |
Mark M. | Have a pleasant evening, everyone! |
Gerardo B. | cool... thanks |
Sean S. | OK, thanks. I will use the FLAGs you suggested earlier to better manage history. Thanks so much for your time. |
Terry S. | Thanks! |
Sean S. | bye |
Terry S. | has left the room |
Sean S. | has left the room |
Gerardo B. | has left the room |
Mark M. | turned off guest access |