-
-
Notifications
You must be signed in to change notification settings - Fork 673
Description
Android 10 introduces significant changes in how apps access the device's photos, other media of several types, and files in general. Gone, in that future, are the days where your photos and documents live in a single shared storage area which lots and lots of apps have unrestricted access to, like on a desktop OS. The new model is called "scoped storage".
That future is opt-out for apps targeting Android 10, and we've had to take that opt-out -- see #3665 (comment) and #4282. But it will be mandatory for apps targeting Android 11, and targeting Android 11 will presumably be mandatory for updates on Google Play in about a year. So our opt-out is only a temporary extension of the deadline; we'll need to adapt to scoped storage
The known issues we currently run into with scoped storage are all within the react-native-image-picker library, which we use both for taking a photo to send via Zulip and picking an existing image on the device to send via Zulip. Both of those features encounter trouble:
- On trying to take a photo (the "camera" icon), an error modal appears before the camera widget even shows up. Detailed report: Update Android targetSdkVersion to 29 (Android 10), by 2020-11 deadline #3665 (comment)
- On trying to pick an existing image (the "photo" icon), the symptoms are different; I saw them earlier today but have forgotten exactly how it went wrong. ISTR the picker appeared successfully, but then an error occurred upon actually choosing an image.
The basic problem is that r-n-image-picker tries to handle the photos as if it had unrestricted access to them as files, and with scoped storage it no longer does. Several upstream issues seem related (I think some of them are duplicates): at least
- Camera doesn't open and error "Couldn't get file path for photo" is reported react-native-image-picker/react-native-image-picker#1269,
- Couldn't get file path for photo on ANDROID 10 EMU react-native-image-picker/react-native-image-picker#1350,
- Android 10: Camera Doesn't Open After Granting Permission react-native-image-picker/react-native-image-picker#1393,
- When is android 29 compatible react-native-image-picker/react-native-image-picker#1443;
- and there's an open PR Fix android 10+ public folders access react-native-image-picker/react-native-image-picker#1439.
The PR is quite simple, and the main reason it isn't already merged seems to be (react-native-image-picker/react-native-image-picker#1439 (comment)) that it gives up entirely on putting the captured image, when you use the camera, into the central "Pictures" folder shared with other apps. That is a useful feature. As a Zulip user, I prefer to keep that feature too.
The Android release notes on this change point to a guide doc on how to handle media files in the new world. I believe these are the key points for us, and for react-native-image-picker:
- We still need READ_EXTERNAL_STORAGE permission, to read images/etc. added by other apps.
- We no longer need WRITE_EXTERNAL_STORAGE permission, and shouldn't request it on newer Android versions.
- Whenever we're creating an image file ourselves -- either with the camera, or by resizing or rotating:
- We need to do it in our own storage area; in other words
storageOptions.privateDirectory
should be ignored and effectively treated as true. - If we want to make the new image available to other apps (so, if
storageOptions.cameraRoll
is true), we can add it to the MediaStore.Images "media collection". (Or MediaStore.Video, for videos.) Once we do that, other apps that have READ_EXTERNAL_STORAGE permission will be able to see the image. Here's an example showing how to add it.
- We need to do it in our own storage area; in other words
- It might not be possible to go and read the EXIF data, which the existing code does in order to perform auto-rotation. But instead, we should be able to get it with a MediaStore query, using the
MediaStore.MediaColumns.ORIENTATION
column. That should be more efficient anyway, because it's already there in the database rather than having to parse through the image file. (In Zulip we don't use this feature.)