Oct 10 | 3:50 PM |
Mark M. | has entered the room |
Mark M. | turned on guest access |
Oct 10 | 4:15 PM |
Kai H. | has entered the room |
Kai H. |
Hi there
|
Mark M. |
hello, Kai!
|
Mark M. |
(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?
|
Mark M. |
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
|
Mark M. |
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
|
Kai H. |
The new MediaStore collections
|
Kai H. |
And so on
|
Kai H. |
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
|
Mark M. |
and so you do something else on the older devices
|
Oct 10 | 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
|
Kai H. |
Yes.
|
Mark M. |
I do not know if they plan on a Jetpack library to try to hide the differences or not
|
Mark M. |
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
|
Mark M. |
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
|
Mark M. |
yes, getExternalFilesDir() is stable
|
Kai H. |
But you have to opt into "raw paths" with some kind of special permission
|
Kai H. |
Which I would like to not do if possible.
|
Mark M. |
just READ_EXTERNAL_STORAGE
|
Oct 10 | 4:25 PM |
Kai H. |
Isn't "raw paths" connected to READ_EXTERNAL_STORAGE?
|
Mark M. |
yes
|
Mark M. |
(at least, for read operations)
|
Mark M. |
*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.
|
Kai H. |
By "app files" I mean files that the app will download from a server.
|
Mark M. |
getExternalFilesDirs() (note the plural) should still work
|
Mark M. |
where the second and subsequent locations returned by that method are on removable storage
|
Mark M. |
and you can read and write those without permissions
|
Mark M. |
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.
|
Oct 10 | 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);
|
Mark M. |
you don't know whether getExternalFilesDir() will come back with a trailing / or not
|
Mark M. |
(BTW, I'm assuming my_name was a directory name)
|
Kai H. |
Yes.
|
Oct 10 | 4:35 PM |
Kai H. |
How would I test if my app supports scoped storage if I have no device with Android >= 10?
|
Kai H. |
And the emulator doesn't work for me.
|
Mark M. |
then you will need to buy a device, I guess
|
Mark M. |
used on eBay, cheap models on Amazon, etc.
|
Kai H. |
I guess my company will have to do that.
|
Kai H. |
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
|
Kai H. |
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)
|
Oct 10 | 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
|
Mark M. |
so, probably they're just not emphasizing that location anymore
|
Mark M. |
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.
|
Kai H. |
Wouldn't know where else to put those kind of file.s
|
Kai H. |
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 :-)
|
Oct 10 | 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. | |
Kai H. |
Ok
|
Mark M. |
pffft
|
Mark M. |
that is pointless on two levels
|
Kai H. |
:D
|
Mark M. |
first, I am skeptical that standardizing on a Uri is necessary
|
Mark M. |
second, even if it is... file: is a valid Uri scheme
|
Mark M. |
so running everything through a FileProvider is really unnecessary
|
Kai H. |
Ok
|
Kai H. |
So seems like there isn't too much change needed for our app :)
|
Kai H. |
But I say that now. Let's see what happens when I try and use it on a device with Android 11.
|
Kai H. |
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
|
Oct 10 | 4:50 PM |
Kai H. |
And it's a bit complicated in our app to begin with ;-)
|
Kai H. |
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.
|
Kai H. |
Or rather that is what I am a bit afraid about.
|
Kai H. |
Ah well. The live of a legacy Android app dev ;-)
|
Kai H. |
life
|
Mark M. |
in Android Studio, you can do "Find Uses" for the File() constructor
|
Mark M. |
by default, it will scan your libraries as well, but it still might be useful
|
Mark M. |
sorry, "Find Usages"
|
Mark M. |
(which is a really awkward name, now that I think about it...)
|
Oct 10 | 4:55 PM |
Kai H. |
What would you call it?
|
Mark M. |
"Find Uses", apparently :-)
|
Kai H. |
I guess that is like "utilize"
|
Kai H. |
"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"?
|
Kai H. |
I hate "utilize"
|
Kai H. |
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
|
Kai H. |
I hope I know everything I need about Scoped Storage now X)
|
Oct 10 | 5:00 PM |
Mark M. |
OK, that's all for today's chat
|
Mark M. |
next one is Tuesday at 7:30pm US Eastern
|
Kai H. |
Have a good one
|
Kai H. |
And thanks for the answers
|
Mark M. |
you too!
|
Mark M. |
you're welcome!
|
Kai H. | has left the room |
Mark M. | turned off guest access |