Dec 12 | 3:50 PM |
Mark M. | has entered the room |
Dec 12 | 3:55 PM |
Mark M. | turned on guest access |
Kai H. | has entered the room |
Mark M. |
hello, Kai!
|
Mark M. |
how can I help you today?
|
Steve | has entered the room |
Kai H. |
Hello, Mark.
|
Kai H. |
Before Android 11 the user could choose an external storage location for the app
|
Mark M. |
and, hello, Steve!
|
Steve |
hi, Mark!
|
Kai H. |
Like the SD-Card. I choosing the SD-Card as an external storage location still possible? Have there been any changes?
|
Mark M. |
(Steve: Kai arrived a bit before you, so I'll be with you shortly!)
|
Steve |
sure. thanks, Mark
|
Mark M. |
Kai: if by "choose" you mean via ACTION_OPEN_DOCUMENT and similar actions, yes, that is still allowed, though the user cannot choose the root of removable storage for ACTION_OPEN_DOCUMENT_TREE
|
Mark M. |
I have material on this in *Elements of Android R*
|
Kai H. |
I was hoping this was possible without any ACTION_OPEN_* action
|
Mark M. |
then, what specifically do you mean by "choose"?
|
Dec 12 | 4:00 PM |
Kai H. |
Display a dialog with possible storage locations (internal, external, sd-card(s)) and then choose one.
|
Kai H. |
And then (some) data of the app will be written there.
|
Mark M. |
but, um, where is the dialog coming from? do you mean a dialog that you are creating yourself?
|
Kai H. |
Yes.
|
Mark M. |
I think that's possible for a few more months via android:requestLegacyExternalStorage="true", but, long-term, that's impractical, other than the locations unique to your app (getExternalFilesDirs() and kin on Context)
|
Mark M. |
I didn't test removable storage much with Android 11, in part because none of the Pixels have an micro SD card slot, and testing with a USB C thumb drive, frankly, is annoying
|
Kai H. |
Would you get sd-cards and the like with getExternalFilesDirs?
|
Kai H. |
I do testing with an emulator.
|
Kai H. |
Dunno if that counts
|
Mark M. |
with the plural form, yes (getExternalFilesDirs())
|
Kai H. |
So I guess that answers my question. Should be good enough for us.
|
Mark M. |
that will return one location per storage volume, where your app can read and write, no permissions required
|
Kai H. |
It's not important if it's app-unique, the important part is that the user is able to choose a medium, as some want to use more storage than the phone has internally.
|
Mark M. |
then, hopefully, getExternalFilesDirs() will suffice for your needs
|
Kai H. |
thank you.
|
Mark M. |
let me take a question from Steve, and I'll be back to you in a bit
|
Dec 12 | 4:05 PM |
Mark M. |
Steve: your turn! how can I help you today?
|
Steve |
I'll paste in my question:
|
Steve |
View paste
|
Mark M. |
I don't know of a way to create (1) and (2) in parallel, though advanced media stuff is out of my depth
|
Steve |
ok
|
Mark M. |
for your other option, historically I think people have wound up using stuff like ffmpeg
|
Mark M. |
and that has issues (native binaries, not really designed for this sort of use)
|
Mark M. |
it's possible there is some newer option for that of which I am unaware -- again, this isn't really my cup o' tea
|
Mark M. |
if you have a server, you could always consider uploading the full video and ripping out the voice recording on the server
|
Mark M. |
as you have a lot more horsepower and options there, albeit with a much larger upload
|
Mark M. |
and, on Android 11, you might peek at MediaParser
|
Mark M. |
I'm not certain if it can do what you need, but it's the closest thing that I am seeing in the SDK, given a quick scan
|
Steve |
great, i'll take a look
|
Dec 12 | 4:10 PM |
Mark M. |
but, alas, that's all I have at my fingertips
|
Steve |
thanks, Mark
|
Mark M. |
happy to help!
|
Steve |
I have a second, unrelated question
|
Mark M. |
let me take another question from Kai, and I'll return to you for your second one shortly
|
Steve |
of course
|
Mark M. |
Kai: back to you! do you have another question?
|
Kai H. |
Yes
|
Kai H. |
When taking a picture, did you ever experience a phone saving the rotation data in EXIF and then having a picture rotated "the wrong way" when using some programs?
|
Mark M. |
do you know if those programs pay attention to EXIF headers?
|
Kai H. |
I figured not.
|
Kai H. |
One of the programs is the server users upload pictures to that can be taken with our app :D
|
Kai H. |
And when viewing the pictures on Windows, some honor the flag, some ask, some don't
|
Mark M. |
push come to shove, you can rotate the image yourself, either on the phone or on that server
|
Mark M. |
IOW, you check to see if the EXIF header is there and if it is, create a new image rotated based on that header, and save that rotated image
|
Dec 12 | 4:15 PM |
Kai H. |
Ok
|
Mark M. |
I might have code in *The Busy Coder's Guide to Android Development* for that -- I know I wrote some for my early camera libraries
|
Mark M. |
the biggest downside is that you might get an OutOfMemoryError, if you cannot hold two copies of the image
|
Mark M. |
and, of course, if you do the work on the server, you have more power and more options
|
Mark M. |
but that's really the only way to defend yourself against software that ignores those headers
|
Kai H. |
So you encountered that sometime too. Good to know.
|
Mark M. |
oh, yeah, it's reasonably common, particularly for Android apps where developers aren't using a decent image-loading library
|
Mark M. |
in my camera libraries, I offered options for rotating the image, just to deal with that problem
|
Mark M. |
let me take Steve's second question, and I'll be back to you afterwards
|
Dec 12 | 4:20 PM |
Mark M. |
Steve: back to you! hit me with your next question! :-)
|
Steve |
I'm getting back into Android development after not doing it for a couple of years. My Android devices are old. Do you have any suggestions on an inexpensive Android device I could buy that would be good for development?
|
Kai H. |
Is 300 $ inexpensive?
|
Kai H. |
What is the price range, what does it have to have?
|
Mark M. |
Samsung's low end devices are fairly decent (e.g., Galaxy A20/A21), but, as Kai suggested, more parameters might help
|
Steve |
The app I'm working on now needs to be able to record AV, but that's about it in terms of anything like special features
|
Mark M. |
just using the normal device camera and microphone?
|
Steve |
yes. i don't need anything special
|
Steve |
i'm willing to get something with fewer parameters to spend less money - i'd prefer well under $300
|
Dec 12 | 4:25 PM |
Mark M. |
pretty much anything that has the Play Store on it works for development
|
Steve |
ok. the Samsung devices you mentioned would probably be fine. i'll look into those. thanks
|
Mark M. |
Nokia also has a bunch of entry-level devices (e.g., 5.3)
|
Steve |
great - i'll look into those as well
|
Mark M. |
the thing to watch out with Nokia is some of those are fairly low-spec, with Android One -- that may be specifically useful if you expect your user base to be working with low-spec phones, but it can be annoying during ordinary development
|
Steve |
k
|
Mark M. |
and, of course, there's always buying used on eBay or similar sites
|
Steve |
sure
|
Mark M. |
for example, I just picked up a Pixel 3a XL, in preparation for next year's Android R release
|
Mark M. |
used for $120
|
Steve |
i see. i'll definitely keep that in mind
|
Mark M. |
so, sub-$200 options exist, and sub-$300 shouldn't really be a big problem
|
Steve |
great, thanks
|
Kai H. |
The OnePlus have pretty good value and can usually be brought up to the latest Android versions with custom roms.
|
Dec 12 | 4:30 PM |
Steve |
thanks, Kai. i'll look into those as well
|
Mark M. |
they aren't as widespread in the US, though I saw one pop up in Amazon when I was poking around while answering the question
|
Mark M. |
make sure it has the Play Store on it, though, as I forget if OnePlus is purely a Google Play ecosystem firm or whether they also ship devices without Play
|
Mark M. |
it might still be useful for development even without the Play Store, but there are risks of stumbling blocks
|
Steve |
sure. i'll keep that in mind
|
Mark M. |
let me take another question from Kai, and I'll return to you in a bit
|
Mark M. |
Kai: back to you! do you have another question?
|
Steve |
thanks
|
Kai H. |
I read your book about Kotlin Coroutines and got the impression that LiveData is going out already, being replaced by Flows, which are already being replaced by Channels iirc.
|
Mark M. |
you have part of that backwards
|
Mark M. |
flows are replacing channels, not the other way around
|
Kai H. |
Ok
|
Mark M. |
I think it may even be more accurate to say "flows are wrapping around channels, and most developers will only wind up using flows"
|
Mark M. |
I get a bit lost in the coroutines statements of what is and is not being deprecated
|
Dec 12 | 4:35 PM |
Kai H. |
It has just been like half a year that I looked into LiveData. It seems that things are getting replaced VERY quickly.
|
Kai H. |
Is that just the normal flow of (android|developer) things or do you think there will be some kind of (temporary) stabilisation at one point?
|
Mark M. |
LiveData debuted in 2017, so that's not super-new
|
Mark M. |
and, coroutines isn't an option for Java developers
|
Mark M. |
LiveData's timing wasn't stellar in terms of long-term usage
|
Mark M. |
in 2017, Google had not yet endorsed Kotlin, and I forget if the first coroutines even existed
|
Mark M. |
so, it's more that JetBrains is living up to the "jet" portion of their name and are moving fairly rapidly
|
Kai H. |
They do SO much it's really staggering.
|
Mark M. |
and, along the way, flows are stealing LiveData's thunder
|
Mark M. |
yeah, JetBrains has tremendous momentum
|
Mark M. |
so, LiveData itself isn't going anywhere
|
Kai H. |
With a lot of quite good products, covering a very wide areay.
|
Mark M. |
however, you will see more and more developers skipping it in favor of StateFlow, either to stick purely with coroutines or with an eye toward Kotlin/Multiplatform
|
Dec 12 | 4:40 PM |
Kai H. |
Let's say I have an old Java code base and I want to implement new features in a "modern" way, with like 20 % in Kotlin. What's the best way to deal with that?
|
Mark M. |
that's kinda broad
|
Mark M. |
can you narrow the scope of "deal with that"?
|
Kai H. |
I mean considering LiveData/Channels/Flows/...
|
Mark M. |
at 20% Kotlin? stick with LiveData
|
Mark M. |
otherwise, you may find yourself needing to ratchet up that percentage faster than you want
|
Mark M. |
of the three items you cited, channels are not really worth thinking too much about now for new development
|
Kai H. |
So LiveData if I really want to stick with Java, Flows if I am open to do "as much Kotlin as needed"?
|
Mark M. |
that's a reasonable summary
|
Kai H. |
Thank you
|
Mark M. |
though the first part might be more of "LiveData if I'm not in position to convert legacy Java and I don't want to run the risk of painting myself in a corner"
|
Mark M. |
LiveData can work equally well with Java and Kotlin; coroutines work great with Kotlin... and aren't really something that Java can use much
|
Kai H. |
Well. It's more that I would be very afraid of breaking the undocumented unspecified functionality currently represented by a lot of AsyncTasks than not being in the position ;-)
|
Dec 12 | 4:45 PM |
Mark M. |
the problem is that some of that code that contains those AsyncTasks might need to interoperate with some of your new stuff
|
Mark M. |
it will be less risky if the new stuff is using LiveData, so you do not necessarily have to switch languages for the AsyncTask-laden code
|
Mark M. |
bear in mind that, unlike framework classes, LiveData comes from libraries, and so has a long lifespan
|
Mark M. |
it is possible that some framework change in Android 17 will break today's LiveData, but outside of that, LiveData will still work 6 years from now
|
Mark M. |
it may not be as popular
|
Mark M. |
but, popularity is only one criterion
|
Kai H. |
Yes
|
Mark M. |
let me take another question from Steve
|
Mark M. |
Steve: do you have another question?
|
Steve |
yes
|
Steve |
following up on my media question:
|
Dec 12 | 4:50 PM |
Steve |
do you have any suggestions on resources that might help me figure out a solution?
|
Mark M. |
not specifically in terms of media
|
Steve |
ok
|
Mark M. |
obviously, there are your standard Q-and-A options (Stack Overflow, reddit, etc.)
|
Steve |
sure
|
Mark M. |
and it is possible that there is some dedicated Android media programming site that I do not know of
|
Steve |
i appreciate your help, Mark. thanks so much!
|
Mark M. |
I have seen that there are some specific books on the subject, but traditionally-published books have a short half-life, so those media books might be out of date already
|
Mark M. |
outside of that, I cannot think of anything specific to your problem spare
|
Mark M. |
er, space
|
Steve |
i haven't found most Android books helpful for that reason
|
Steve |
thanks so much!
|
Mark M. |
you're welcome!
|
Mark M. |
we're running out of chat time, so it's open season -- if either of you have a question, go right ahead!
|
Kai H. |
When refactoring AsyncTask, I guess testing them means wrapping their main functionality into a function and then testing that function? Which means that function can also be moved other means of background work?
|
Steve | has left the room |
Mark M. |
Kai: if that's practical, then yes, that's a nice approach
|
Mark M. |
all too often, AsyncTasks are not well-isolated
|
Mark M. |
and so testing their current functionality is hard
|
Mark M. |
AsyncTasks often pre-date modern Android architecture considerations, so you'll have activities and fragments directly executing the AsyncTasks
|
Dec 12 | 4:55 PM |
Mark M. |
in fact, a retained fragment was kinda the go-to approach for running AsyncTasks and dealing with configuration changes
|
Kai H. |
We use a "static task" inside an Activity/Fragment usually.
|
Kai H. |
And have a class hierarchy of AsyncTasks.
|
Mark M. |
any last questions?
|
Dec 12 | 5:00 PM |
Kai H. |
:D
|
Kai H. |
X)
|
Mark M. |
I'm going to take that as a "no"
|
Mark M. |
:-)
|
Mark M. |
anyway, that's a wrap for today's chat
|
Mark M. |
next one is Tuesday, 8:30am US Eastern
|
Mark M. |
have a pleasant evening!
|
Kai H. |
Same
|
Kai H. |
Have a good time.
|
Kai H. | has left the room |
Mark M. | turned off guest access |