Office Hours — Today, March 26

Saturday, March 23

Mar 26
7:25 PM
Mark M.
has entered the room
Mark M.
turned on guest access
Suleyman O.
has entered the room
Mark M.
hello, Suleyman!
Suleyman O.
Hey Mark!
Mark M.
how can I help you today?
Suleyman O.
I prepared my question to save us some time, so here it is :D
View paste
I’m implementing an app widget which contains some text and a button, the text needs to be updated whenever a button is pressed. The data for the text comes from a weather api, so I need to perform the update action in a service. 

My current flow is as follows:

1. In onUpdate of the WidgerProvider I set the OnClickPendingIntent
2. This pending intent is handled in the onReceive method of the same WidgetProvider and calls enqueueWork of the service.

My questions are, 

1. Do you think that this flow is acceptable? Given that widget provider is handling the pending intent, which also means that enqueue work is called when the widget is first added.
2. Is JobIntentService a good choice in this case? Given that it does not guarantee that the job is executed straight away. I know that a simple service or IntentService is not an option, I also considered a WorkManager, but then read your article about it producing an infinite loop….
7:30 PM
Mark M.
"I know that a simple service or IntentService is not an option" -- well, they are not options if you want them to be in the background, if they will run for more than a minute
my hope is that the weather API will be more responsive than that
so, this is a case where an IntentService should still be OK
Suleyman O.
Yeah I hope it's more responsive than that :) Would I have to display a notification while the widget is updated?
Mark M.
no, that should not be needed, so long as you can live with the one-minute runtime
a foreground service, with a notification, would be needed if you intended to run for longer
oh, wait
I am thinking more of starting the service from an activity
I have not tried starting a background service from an AppWidgetProvider, and that may be a problem, as that will be considered to be background itself
it's possible that they provide special support for app widgets starting services, so you can give it a try if you want, but my guess is that you will get the cannot-start-in-background error
Suleyman O.
Yeah I think so too, that's why I was looking towards the JobIntentService
Mark M.
another trick you can consider is that an AppWidgetProvider is a BroadcastReceiver, so in theory you could use goAsync()
7:35 PM
Suleyman O.
Yep, I've seen that being used as well
Mark M.
I am not a big fan of goAsync(), as it is poorly documented, but for your scenario, we are running out of good options
Suleyman O.
So would that be a more acceptable option than a WorkManager?
Mark M.
it would be easier than WorkManager
the WorkManager/app widget problem means that you would have to be very careful about firing off work just because onUpdate() got called
Suleyman O.
Aha, and that would enable the widget to update without the activity running
Mark M.
goAsync() would allow you ~10 seconds of runtime to get your API call in, before Android will consider terminating your process
it is possible that somebody has worked out a WorkManager/app widget recipe that safely avoids the infinite-loop problem, though I do not recall running across one
Suleyman O.
Yeah, I did a small research and didn't find any news on that issue either
Mark M.
but, Android is a big place nowadays, so there are lots and lots of niche things like that where I might not hear about it
particularly for the button clicks, the possible delay with JobIntentService could be annoying
so I agree that if you could avoid that solution, it would be best
Suleyman O.
Yeah that's what I was afraid of, having a flaky update logic
I'll have a look around, in the meantime implementing the goAsync option
Mark M.
do you need to do much work beyond make the weather API call? if not, goAsync() is probably your best bet
7:40 PM
Suleyman O.
Not really, retrieving current temperature and displaying it
Mark M.
OK, then the 10-second-ish window should be sufficient
Suleyman O.
Yeah, I believe so, anything else beyond that will be a timeout for me :D
Mark M.
yeah, I'd try goAsync()
Suleyman O.
Thanks a lot for clearing that up, I was unsure with so many options available
Mark M.
app widgets are a bit of a forgotten area in Android, and a lot of the background limitations do not seem to take them into account
Suleyman O.
That's true, I haven't seen any significant change in that area comparing some articles from years ago to now
Anyways, thanks a lot for your time, this was very useful, and now I have some work to do :D
Mark M.
you're welcome!
Suleyman O.
Have a great evening!
Mark M.
you too!
7:45 PM
Tad F.
has entered the room
Mark M.
hello, Tad!
Tad F.
Hi all
Are you in the middle of a conversation, or can I ask a question?
Mark M.
Tad: how can I help you today?
go right ahead!
Tad F.
I've been continuing to work on my app we've discussed before - i.e. Dropbox DocumentsProvider et al
I've been implementing video streaming using ExoPlayer
Have you worked at all with it?
Mark M.
no, sorry
Tad F.
I have a fairly detailed question about a custom CacheDataSourceFactory I'm working on
Oh, ok.
Mark M.
a DocuemntsProvider and streaming players are going to be tricky to get working together in general
if your Uri is backed by a file on the filesystem, you may be OK
Tad F.
Well - I actually have the streaming part done and it is working great.
Using the Pipe approach from your book actually
Mark M.
seriously? ExoPlayer holds up with that?
Tad F.
Yeah
Mark M.
if so, that's surprising and awesome
don't count on that being the case for other clients :-)
Tad F.
The question I posted today is here: https://stackoverflow.com/questions/28700391/us...
But in a nutshell, it is clear from looking at the source code in CacheDataSource, that the authors anticipate a condition by which media is streamed.
7:50 PM
Tad F.
View paste
/**
 * A {@link DataSource} that reads and writes a {@link Cache}. Requests are fulfilled from the cache
 * when possible. When data is not cached it is requested from an upstream {@link DataSource} and
 * written into the cache.
 *
 * <p>By default requests whose length can not be resolved are not cached. This is to prevent
 * caching of progressive live streams, which should usually not be cached. Caching of this kind of
 * requests can be enabled per request with {@link DataSpec#FLAG_ALLOW_CACHING_UNKNOWN_LENGTH}.
 */
I wrote a custom cache.
But when I stream, the files don't wind up in it.
Mark M.
BTW, that question is from 2015
Tad F.
Yeah but the issue still remains
The DataSpec defaults to not allowing caching of something with unknown length
Mark M.
OK, just wasn't sure if you pasted the wrong link, that's all, as you said you asked it today
are you getting caught by "By default requests whose length can not be resolved are not cached"?
Tad F.
And there still doesn't appear to be a way to set that flag that I can find.
That was from earlier today
Which is precisely what I'm running into.
But no updates since last December
So I was hoping you'd have the magic answer - I'm faced now with essentially re-creating a CacheDataSource simply to be able to override the default value in the DataSpec passed into the open() method.
Ugh.
That class is declared final so you can't override anything.
Yes to answer your question - getting caught by the indeterminate length issue.
Mark M.
can't you fork it? clone it to your own class with the changes?
IOW, how much "re-creating" is actually needed?
7:55 PM
Tad F.
Sorry - not sure what that even means (showing my ignorance here).
What's the difference between "clone" (i.e. just copying the source code) into my own class - which is what I was gonna do...
So maybe "re-create" was the wrong term.
Mark M.
yes, that's what I mean
Tad F.
"copy the file with my own class name" is more accurate
Which is what I think the poster ended up doing too.
But of course, that doesn't help me when that file gets updated, etc.
Mark M.
sure, but if nothing else, you can supply it as a proof of concept on the issue
Tad F.
Right
Btw - what did you mean when you said "don't count on that being the case for other clients"?
Mark M.
you need that issue to get unstuck, and saying "here's my hack that worked -- can you formalize something for this?" might help
Tad F.
What clients are you talking about?
Mark M.
MediaPlayer
Tad F.
Ah - it appears MediaPlayer is on the way out, doesn't it?
Mark M.
possibly MediaPlayer2 in Android Q -- not sure if that is ExoPlayer-based or some other beast entirely
yeah, I have no idea what Google's plans are there
I had assumed they would steer everyone to ExoPlayer... then MediaPlayer2 showed up in Q
Tad F.
Another question - have you worked with XMPP?
Mark M.
not in a very long time
like, pre-Android
Tad F.
I'm thinking of using this in order to peer-to-peer share files via the file transfer capability. Just starting to look into it.
8:00 PM
Tad F.
There is a surprising lack of robust truly peer-to-peer (i.e. no middle-man manager of the actual bytes transfer) out there.
Suleyman O.
has left the room
Tad F.
WebRTC was another tack I was considering.
Mark M.
I was going to recommend WebRTC
P2P is difficult due to NAT translation (i.e., everyone has a private IP address), last I checked
Tad F.
Well, this is precisely what the good XMPP servers are supposed to handle (and the more robust ones include STUN and TURN server capability if needed)
But I don't have any real experience - only reading war stories at this point.
And playing with SMACH
SMACK
Mark M.
right -- I was commenting more on the "no middle-man manager" part of your earlier comment
Tad F.
Yeah - for chat it's pretty impossible. There is always a middle server. But file transfer is a different animal.
Apparently.
I looked at File.Pizza on the WebRTC front.
The fact that it's based on a bunch of JavaScript kind of gives me the willies.
I just have come to distrust support for varying flavors of JS across the bazillion browser versions out there.
But maybe I'm just paranoid.
Mark M.
I looked into WebRTC for Android ~18 months ago and concluded that I didn't know what everyone was using
Tad F.
Only recently has Apple supported it in Safari.
And there are some significant restrictions.
8:05 PM
Tad F.
I may have asked you this before but - I'm also interested to hear about robust apps built using Flutter.
Can you point me to any resources>
Mark M.
no, sorry
Tad F.
This app I'm working on uses some pretty Android-y capabilities. I can't imagine how a cross-platform system would be able to handle it.
That's what I'm really curious about I guess - where the *practical* limits are with Flutter and Dart.
There have been a few articles on Medium that chronicle people's experiences that I've read.
Mark M.
my assumption is that it's a bit like all the other cross-platform frameworks, in that somebody has to build glue code for each individual bit of a platform that needs to be surfaced in the cross-platform framework
that's why there are zillions of questions asking about React Native plugins for this-and-such, for example
Tad F.
Yeah - well apparently it does't use native components.
At least, not on the UI side
I'm not sure what it does when you want to use a Media Player, for example.
Mark M.
agreed, they bundle their own copy of the Skia graphics library and draw everything themselves
and in terms of platform services like that, until somebody writes the glue code, it is probably unavailable
and I don't know how easy those bits are to write and distribute
Tad F.
Or do something with sockets, or threads, or lots of other things that I would expect be implemented differently on the two platforms.
8:10 PM
Tad F.
Broadcast intents...
What's the equivalent on iOS?
How is it handled in a unified platform?
Notifications, etc.
Mark M.
historically, a cross-platform framework is fine for narrow and shallow apps, but break down after that
Tad F.
Yeah - the examples I saw at the last I/O seemed pretty light.
Mark M.
I have not heard anything about Flutter that suggests they have made a quantum leap in that eara
Tad F.
It's not even 1.0 yet, I don't think.
Mark M.
I think it went 1.0 early this year
Tad F.
Oh, ok
Mark M.
and since we're only in late March, that would have been fairly recently :-)
Tad F.
I recently switched to be running AS 3.4 RC2 and when I did that I didn't re-add the Flutter plug-in so I am behind the times there...
8:15 PM
Tad F.
OK - well thanks as always for the conversation, good evening!
Mark M.
sorry I couldn't help more!
Tad F.
has left the room
8:25 PM
Mark M.
turned off guest access

Saturday, March 23

 

Office Hours

People in this transcript

  • Mark Murphy
  • Suleyman Orazgulyyev
  • Tad Frysinger