Office Hours — Today, October 10

Thursday, October 8

Oct 10
3:50 PM
Mark M.
has entered the room
Mark M.
turned on guest access
4:15 PM
Kai H.
has entered the room
Kai H.
Hi there
Mark M.
hello, Kai!
(sorry if there was a delay from when you arrived -- I was distracted)
Kai H.
I have a couple of questions about scoped storage
Mark M.
how can I help you today?
oboy
Kai H.
Like when I target API Level 30 but I run on Android 9, does anything about scoped storage apply?
Mark M.
no
scoped storage started with Android 10
Kai H.
Or will there be some kind of emulation when using the new apis
Mark M.
what new APIs are you referring to?
Kai H.
LIke the call to get the external storage volume
The new MediaStore collections
And so on
I am rather confused about scoped storage, as you might get ;-)
Mark M.
if the method is new to API Level 29, you can only use them on Android 10 and higher
and so you do something else on the older devices
4:20 PM
Mark M.
so, for example, you might use MediaStore on Android 10+ where you might use Environment.getExternalStoragePublicDirectory() on older devices
Kai H.
So effectively I might have to do some kind of if (apiLevel < 29) ... switch?
Mark M.
yes
Kai H.
That feels so... old.
Mark M.
you mean, compared to having ...Compat classes handle that?
Kai H.
Like something you had to do in times of kitkat and that you shouldn't do anymore nowadays
Yes.
Mark M.
I do not know if they plan on a Jetpack library to try to hide the differences or not
since the differences are substantial, my guess is that they will not
Kai H.
So there is no "one size fits all" solution this time?
Mark M.
...Compat strategies tend to work for either minor changes or where the library can offer a backport
it depends a *lot* on exactly what you are doing and where you want to do it
Kai H.
If I only knew... I am about to find that out.
Mark M.
bear in mind that android:requestLegacyExternalStorage="true" on <application> works for Android 10, and will do so indefinitely
Kai H.
Or in the process, rather.
Mark M.
and it also works on Android 11 until you need targetSdkVersion 30 next year sometime
Kai H.
Ok. I don't think we need that though. "getExternalFilesDir()" should continue working as always and we use that for a lot of storing
Mark M.
plus, Android 11's "raw paths" means that reading external storage works mostly as it did back on Android 9.0
yes, getExternalFilesDir() is stable
Kai H.
But you have to opt into "raw paths" with some kind of special permission
Which I would like to not do if possible.
Mark M.
just READ_EXTERNAL_STORAGE
4:25 PM
Kai H.
Isn't "raw paths" connected to READ_EXTERNAL_STORAGE?
Mark M.
yes
(at least, for read operations)
*write* operations in arbitrary locations are a bigger problem
Kai H.
I think we only need to write within our own storage.
Mark M.
in that case, you're probably not going to get hit much by scoped storage effects
Kai H.
How would I write to an SD card?
Mark M.
with difficulty
Kai H.
Currently the user can select if he wants to store the app files on an sd card and that should continue to work.
By "app files" I mean files that the app will download from a server.
Mark M.
getExternalFilesDirs() (note the plural) should still work
where the second and subsequent locations returned by that method are on removable storage
and you can read and write those without permissions
if you need to write to arbitrary locations on removable storage, ACTION_CREATE_DOCUMENT is probably your best option
Kai H.
Ok, then nothing will change in that regard, hopefully.
4:30 PM
Kai H.
Another thing I am confused about is if I need to change everything to URIs or if I can still do something like File(getExternalFilesDir() + "my_name" + fileName);
Mark M.
I'm not a fan of + for assembling paths, but for filesystem locations that you can work with, File() is fine
Kai H.
How would you assemble the file path?
Mark M.
Java or Kotlin?
Kai H.
Java
Mark M.
the simplest I'd do is new File(getExternalFilesDir(), "my_name/" + fileName);
you don't know whether getExternalFilesDir() will come back with a trailing / or not
(BTW, I'm assuming my_name was a directory name)
Kai H.
Yes.
4:35 PM
Kai H.
How would I test if my app supports scoped storage if I have no device with Android >= 10?
And the emulator doesn't work for me.
Mark M.
then you will need to buy a device, I guess
used on eBay, cheap models on Amazon, etc.
Kai H.
I guess my company will have to do that.
I shall request a Pixel 4a
Mark M.
that's a reasonable choice: not too expensive, and likely to get upgrades for a couple of years
Kai H.
Exactly
Will the "Documents" location not gonna be used anymore? I think it's not part of the MediaStore collections and there seems to nothing in the API to write to it, short of using "raw paths" and such.
Mark M.
Kai H.
Ah, I even read that X)
4:40 PM
Mark M.
I don't know whether Google is backing away from Documents, or if it was an oversight, or what
Kai H.
Huh. An Oversight would be something.
Mark M.
the fact that they didn't add it in Android 11 suggests that it wasn't an oversight
so, probably they're just not emphasizing that location anymore
it will be interesting if devices that ship with Android 11 have that directory at the outset
Kai H.
I used it heavily personally, for PDFs, word files and such.
Wouldn't know where else to put those kind of file.s
And Downloads is for Downloads, not for things I want to keep. So not having Documents anymore is a bit of a strange thing.
Mark M.
agreed
Kai H.
Is it safe to keep using File() internal to our app or is it a good idea to move everything to uris?
Mark M.
you asked that earlier :-)
4:45 PM
Mark M.
if you can work with the filesystem location, File() is fine
Kai H.
Kinda, I am still confused though by an article they wrote with "Viber" where they mention changing to some sort of internal ContentProvider.
Mark M.
I don't know what that would buy you, other than unnecessary complexity
Kai H.
Ok
Mark M.
pffft
that is pointless on two levels
Kai H.
:D
Mark M.
first, I am skeptical that standardizing on a Uri is necessary
second, even if it is... file: is a valid Uri scheme
so running everything through a FileProvider is really unnecessary
Kai H.
Ok
So seems like there isn't too much change needed for our app :)
But I say that now. Let's see what happens when I try and use it on a device with Android 11.
And have all kind of things break on me.
Mark M.
I agree that storage is a lot more complicated than it used to be
4:50 PM
Kai H.
And it's a bit complicated in our app to begin with ;-)
Now I have to find all the places where we use storage, try to see if there is any change needed and implement it if necessary.
Mark M.
hopefully, it's a relatively short list of places
Kai H.
Not too many. The hard part is finding them all and not missing one.
Or rather that is what I am a bit afraid about.
Ah well. The live of a legacy Android app dev ;-)
life
Mark M.
in Android Studio, you can do "Find Uses" for the File() constructor
by default, it will scan your libraries as well, but it still might be useful
sorry, "Find Usages"
(which is a really awkward name, now that I think about it...)
4:55 PM
Kai H.
What would you call it?
Mark M.
"Find Uses", apparently :-)
Kai H.
I guess that is like "utilize"
"use" would be too simple
Mark M.
"Usages" just seems contorted
Kai H.
So everyone uses "utilize" nowadays.
Mark M.
well, you used "uses" rather than "utilizes" :-)
Kai H.
Isn't a "usage" diffeent from a "use"?
I hate "utilize"
If it's used where you would use "use" normally.
Mark M.
probably, but I can't think of anywhere else where I see "usage" in a plural form
Kai H.
Ah well
I hope I know everything I need about Scoped Storage now X)
5:00 PM
Mark M.
OK, that's all for today's chat
next one is Tuesday at 7:30pm US Eastern
Kai H.
Have a good one
And thanks for the answers
Mark M.
you too!
you're welcome!
Kai H.
has left the room
Mark M.
turned off guest access

Thursday, October 8

 

Office Hours

People in this transcript

  • Kai Hatje
  • Mark Murphy