Office Hours — Today, May 1

Saturday, April 29

May 1
3:50 PM
Mark M.
has entered the room
Mark M.
turned on guest access
3:55 PM
Mathias
has entered the room
Mathias
Hi Mark
Mark M.
hello, Mathias!
how can I help you today?
Mathias
Hope all is well
we talked last week about geofences and notifications, and that i should create a service to handle the server calls, not sure if you remember
Mark M.
vaguely
Mathias
hehe
Mark M.
I remember geofences being a chat topic
Mathias
great. well, i have some issues, have prepared a question:
View paste
Hi there,

i have a problem getting a notification to be created from within my intent-service.

I previously used a broadcastreceiver that worked fine (triggered by geofence alerts), but since i now need to call my server and create a notification when i get the response, i have moved my notification code to a service, call the server in the service, and create notifications in the async callback.

If i create the notification directly from the service, in the onHandleIntent method, it is created properly.

But, when i do it in the async response method, nothing is created, even though the server call is made, and i can see from the logs that all code is run through (i log and also update local data storage, all works fine).

I am not sure why the notification is not created. Do i need to call it in a different thread? do i need to re-call the service and create the notification there?
Mark M.
whoa
either do not do an async callback inside your IntentService, or do not use IntentService
4:00 PM
Mark M.
IntentService already gives you a background thread
you don't need another one
and, once onHandleIntent() returns, the IntentService is destroyed
which means you cannot use it to show a Notification
(frankly, I would expect a crash here, though I haven't tried this scenario specifically)
Patrick B.
has entered the room
Patrick B.
Hello all
Mark M.
(BTW, hello, Patrick -- I will be with you shortly!)
Patrick B.
(ok :) )
Mark M.
Mathias: depending on what you are using for your server call, you may be able to switch to a synchronous API
(e.g., execute() vs. enqueue() with OkHttp3)
Mathias
But you, and threads on stackoverflow say that if you need something to run in the background, like asyncs, you should have the service do the job
Mark M.
correct
Service itself has no background threads, forcing you to implement that yourself
IntentService has a background thread, with specific rules for its use
Mathias
yeah, and i do that by doing an async call?
Mark M.
and you are welcome to do that... if you switch from IntentService to Service
move your async call to onStartCommand()
and call stopSelf() when the async call is completed
this gives you the effect of an IntentService (only around when it is doing work), without the dueling background threads
personally, I tend to use IntentService, but with synchronous work in onHandleIntent()
but, either way works
let me take a question from Patrick, and I will return to you in a bit
Patrick: your turn! do you have a question?
4:05 PM
Mathias
ok
Patrick B.
View paste
I do, three actually, but I'll take turns with Matthias.
First, I have to say it's a great - and voluminous - book you write there :)
Mark M.
thanks!
Patrick B.
View paste
My first question: Was the cwac-endless Project deprecated?
I used it in my (spare time) project and suddenly both the source on GitHub, and the repository for building is gone.
I haven't found any announcement in your newsletters that it was going away.
Is there a replacement or suggested migration?
Mark M.
"Was the cwac-endless Project deprecated?" -- yes
"and the repository for building is gone" -- I think it is marked as private now
"I haven't found any announcement in your newsletters that it was going away" -- the README had a "discontinued" notice for quite some time
"Is there a replacement or suggested migration?" -- I have no idea
I was not using it, and my implementation sucked, which is why I discontinued it
I moved a bunch of the discontinued projects to private repos last year
I imagine that there are some endless options out on the Android Arsenal
ack
Patrick B.
View paste
Ok, thanks. There are some approaches for endless scrolling for RecyclerView. I guess I'll have a look at those.
But for what it's worth - it worked quite nicely for me :)
Mark M.
if you need a copy of the source, for your own repo, drop me an email at mmurphy }at{ commonsware.com, and I'll send it to you
Patrick B.
View paste
Ok great, thanks!
That was my first question. Shall Matthias & I take turns?
Mark M.
yes, let me switch back to Mathias, and I'll return in a bit for your second question
4:10 PM
Mark M.
Mathias: your turn! do you have another question?
Mathias?
Mathias, let me know when you're back in the chat
in the meantime...
Mathias
hey
Mark M.
Patrick: on to your next question!
Mathias
do patrick!
:)
im reading
Mark M.
OK
Patrick B.
Ok great :)
View paste
2) I am feeling bit lost with the different options for asynchronous operations.
As far as I know, there is AsyncTask, Loaders, and the "bring your own implementation" approaches.
Which would you suggest for an app that populates endless lists on the fly (example: Reddit, Google+ apps) from a webservice.
I found no recommendation by Google - and I would like to go with the best practice.
Mark M.
"As far as I know, there is AsyncTask, Loaders, and the "bring your own implementation" approaches" -- oh, there are many more than that :-)
Patrick B.
I am not surprised to hear that ;)
Mark M.
when you retrieve data, are you saving it to disk, or is it only going to the UI, being discarded as the user navigates?
4:15 PM
Patrick B.
It varies. For some parts (messaging) I store it in SQLite. but mostly it is discarded and reloaded on demand.
Mark M.
for the stuff that you are persisting, I'd lean towards an IntentService, coupled with an event bus to let the UI layer know about the new data
for the stuff that is more or less disposable, the "cool kids" are using Rx, which is why I added a chapter on it
personally, I'm happy with bare threads and an event bus
there is no single "best practice" in this area
so, by and large, if it is working for you, and you are comfortable with it, it's all good
Patrick B.
Ok great. I'll definitely check out Rx as well.
Mathias
+1 for eventbus, makes code much more readable than broadcasting everywhere
Patrick B.
I wasn't sure especially with the "war on background processing" as you put it
Mark M.
nothing of what you're doing here is background processing, though
by "background processing", I don't mean threads
I mean doing work when you're not in the foreground
Patrick B.
Ah ok, my mistake
4:20 PM
Patrick B.
(end of my second question :) )
Mark M.
Mathias: do you have another question?
Mathias
sure
in my intentservice right now, i fire up a locationmanager, fetch my location via callbacks, when i have one i make an async server call, then create a notification. all the callbacks are methods in the intentservice itself.
all works fine, except for the final notification-creation
Mark M.
all works fine temporarily
your process might be terminated before that work gets done
because your work is extending beyond the timeframe of when your service is running
Mathias
reading up now, i notice that intentservice works basically like broadcastreceiver, so my understanding is now that i basically have gained nothing by calling the intentservice from my broadcastreceiver, since they both die at the end of the method?
Mark M.
no
Mathias
ok?
Mark M.
first, onReceive() is called on the main application thread; onHandleIntent() is called on a background thread
hence, a BroadcastReceiver, alone, is not suitable for doing anything significant (i.e., over a millisecond or so)
Mathias
not sure that can be true, my broadcastreceiver is a geofence callback, called when the app is killed
(called by the system)
Mark M.
so?
every Android SDK app process has a main application thread
Mathias
so how can it be "on the application th" ah! ok
Mark M.
that is why we call it the "main application thread" nowadays, and not the "UI thread"
Mathias
gotcha
Mark M.
so, we team up a manifest-registered receiver with some sort of service, where the service handles the long-running work
your job is to ensure that the service is running until the work is completed
the two patterns for this are:
Mathias
ok... so my intentservice can live way longer, but only until the method exits, or at least no guarantees
Mark M.
1. use IntentService, but without asynchronous work
4:25 PM
Mark M.
2. use Service, with asynchronous work, and calling stopSelf() yourself when you are done
in your case, asynchronous work is unavoidable, assuming that you're not just relying upon getLastKnownLocation()
Mathias
precisely
what i was going to say... :)
Mark M.
so, use Service, and call stopSelf() when you are dong with all your asynchronous work
Mathias
so i have to do 2.
Mark M.
I used to have a CWAC-LocPoll library that demonstrated this
like CWAC-Endless, it sucked
Mathias
hehehe ok
Mark M.
and so it was discontinued, etc.
I don't think that I have an example of this pattern in the book
Mathias
well, i will have to code it. this seems like a classical case of "better not forget to close up shop afterwards"...
Mark M.
most of my services either are IntentServices or are manual shutdown by the user (e.g., via some Notification)
Mathias
stopSelf seems scary
Mark M.
why? it's the service equivalent of finish() on an activity
Mathias
yes, but you usually don't call finish yourself
Mark M.
it says "I'm done here -- see ya!"
sure you do
most activities started with startActivityForResult() call finish()
for example
Mathias
yeah, true
Mark M.
most splash screens call finish() (for those folk who insist upon splash screens)
it's not typical for "traditional" activities, but it certainly gets used
and, under the covers, IntentService is calling stopSelf(), after onHandleIntent() returns, if no more commands had been queued up
Mathias
yes, but i don't have to remember to make sure i clean up
4:30 PM
Mark M.
:: shrug ::
Mathias
hehe yep
well thanks, i guess i'll get on it
Mark M.
OK
Patrick: back to you for question #3!
Patrick B.
Fantastic, I have some overlap with Mathias' question. I haven't quite caught all so it might be a bit repetitive
View paste
I've been planning to implement a function in my app for messaging that is offline-capable (like Whatsapp).
It should immediately put it into the SQLite DB for persistence, and an async "job" send it if and when Network is available.

My original idea was to use an IntentService to perform the network IO, persist the result ("sent"/"error") in the database, and then notify the UI that the message is actually sent.
Notifying the Service: I'd have done via Intents (IntentService).
Now, I'm not quite sure this is the way to go, since you wrote above " use IntentService, but without asynchronous work"
Would this be a good implementation or am I way off?
Mark M.
by that, I mean that IntentService should not make asynchronous calls itself
IntentService already has a background thread, and so synchronous calls are the way to go
if you are working with some API that has no synchronous option (e.g., requesting location updates), a Service may be fine, but IntentService is not
Patrick B.
Ah I see, so an IntentService should not request LocationCallbacks for example. Gotcha.
Mark M.
right, because that API is intrinsically asynchronous
(much to the chagrin of many a new developer)
using an IntentService for posting the information to the server is a reasonable approach
4:35 PM
Mark M.
particularly if this stuff needs to be done quasi-real-time
Patrick B.
Great. And combined with the Eventbus input the feedback to the UI sounds nice too.
Mark M.
right
if you get into a situation where you cannot perform the work now (e.g., no network connectivity), JobScheduler is a fine solution, if your minSdkVersion is 21 or higher
in fact, over time, we are likely to move more work to JobScheduler and away from IntentService, given some Android O changes to service behavior
Patrick B.
ok. currently still at 16 (will have to check that)
Mark M.
yeah, you'll need to figure out how you want to handle a long-term lack of connectivity, then
push come to shove, you would use AlarmManager to retry every so often, until the work can get completed
Patrick B.
I'd have subscribed to network events for that and simply rescheduled the IntentService...
(put a new Intent once network was up)
Mark M.
that will work pre-7.0 AFAIK
it definitely will not work on Android O
and I forget if the events that you are interested in are eligible as broadcasts in the 7.x versions
the challenge comes when you have this work to be done, but the user navigates away from the app
then, you need something outside of your process to be able to start up a process for you, as your original process may have been terminated
JobScheduler handles this, plus the connectivity checks
and so represents a nice "all in one" solution
4:40 PM
Mark M.
on older devices, JobScheduler is not an option, so you can try watching for connectivity-change broadcasts
Patrick B.
Ok, that is going to make my life complicated. Especially since the penetration of new Android versions is so slow.
Mark M.
yup
Patrick B.
View paste
Ok, but that wraps up my questions. Thank you!
(Except one: Do you happen to be at Google I/O?)
Mark M.
no, I haven't attended I|O in person in a few years
Mathias: back to you! do you have another question?
Patrick B.
Ok, in that case: Thank you again for your answers!
Mark M.
you're very welcome!
Patrick B.
I'll be signing off. Have a nice afternoon!
Mark M.
you too!
Patrick B.
has left the room
4:55 PM
Mathias
Hey mark. let me first quickly say thanks for the great explanations, hadn't gotten all about intentservice dying as soon after method exit
i might have something more, going to check my notes
Right! one quick one about eventbus register/deregister
Mark M.
go ahead
Mathias
my app is tabbed, with a activity with fragments as tabs
5:00 PM
Mathias
the fragment onstop/onstart are called when showing and not showing, but since they are brought back when user clicks tab, i want them to recieve my data-update events even when not showing.
so i register/unregister in oncreateview/ondestroyview. I have not found much about this, almost all examples are onstart/onstop or pause/resume. But do you see a problem with this approach?
Mark M.
that's probably OK
Mathias
my thoughts here is so that i don't have to redraw all components in onresume every time if you see what i mean
ok great
Mark M.
OTOH, you are potentially wasting CPU cycles for UI updates that the user will never see
you need to decide which is better
Mathias
true
Mark M.
and that's a wrap for today's chat
Mathias
have a good one
Mark M.
the transcript will be posted to https://commonsware.com/office-hours/ in a bit
the next chat is Wednesday at 7:30pm US Eastern
have a pleasant day!
Mathias
has left the room
Mark M.
turned off guest access

Saturday, April 29

 

Office Hours

People in this transcript

  • Mark Murphy
  • Mathias
  • Patrick B.