Skip to content

fix: preserve GPS metadata in uploaded photos and videos - #234

Open
bluecasita wants to merge 1 commit into
opencloud-eu:mainfrom
bluecasita:fix/preserve_gps_exif_on_upload
Open

bluecasita wants to merge 1 commit into
opencloud-eu:mainfrom
bluecasita:fix/preserve_gps_exif_on_upload

Conversation

@bluecasita

Copy link
Copy Markdown

Fixes #218

Problem

Since Android 10, the system redacts location metadata (the GPS EXIF block) from photos and videos an app reads through the media store or the Storage Access Framework, unless the app holds ACCESS_MEDIA_LOCATION and asks for the original via MediaStore.setRequireOriginal(). The app never declared that permission, so every automatic upload (and every upload of a shared/picked media file) arrived on the server with all EXIF intact except the GPS tags. Details and reproduction in #218; Nextcloud's client had the identical bug (nextcloud/android#12188).

Fix

  • Manifest: declare ACCESS_MEDIA_LOCATION.
  • Runtime request, scoped as discussed in GPS metadata stripped from uploaded photos #218: the permission is requested only from the picture / video automatic-uploads settings screens — when the user enables uploads, or once when opening the screen with uploads already enabled (covers users upgrading with auto-upload on). It is never requested on app start. A denial shows a snackbar explaining that uploads will lose their location, and nothing else changes.
  • Reading the original: new MediaLocationUtils resolves the content URI to its unredacted original when possible — a media store URI directly, a SAF document URI (what automatic uploads use) via MediaStore.getMediaUri() — and applies setRequireOriginal(). Used at the two places upload sources are read: UploadFileFromContentUriWorker (automatic uploads) and CopyAndUploadContentUrisTask (files shared to / picked in the app). Any failure to open the original falls back to the previous behaviour, so an upload can never fail because of this change; below Android 10 or without the permission the code path is a no-op.

Testing

  • Unit tests for MediaLocationUtils (Robolectric): implicit grant below API 29, no-op without permission, requireOriginal applied to media store URIs, non-media URIs untouched.
  • Manual, on a Pixel 11 Pro XL (Android 16) with the camera's location saving on and picture automatic uploads enabled (SAF source folder = DCIM/Camera): the permission prompt appears once in the picture-uploads settings screen; a photo taken afterwards was uploaded automatically and the server copy retains the complete GPS block (GPSLatitude, GPSLongitude, GPSAltitude, GPSDateStamp, checked with exiftool) with the rest of the EXIF unchanged — the same setup that reproduced GPS metadata stripped from uploaded photos #218 before the fix. Denying the permission keeps uploads working (location stripped, as before).

Notes for review

  • The permission has no user-visible dialog on API < 29 and is a normal runtime permission on 29+; Play requires no special declaration for it.
  • MediaStore.getMediaUri() throws for non-media documents and for providers other than the external storage / media documents providers — that is caught and the plain URI is used.

Since Android 10 the system redacts location EXIF from media read through
the media store or SAF unless the app holds ACCESS_MEDIA_LOCATION and asks
for the original with MediaStore.setRequireOriginal(). The app never
declared the permission, so automatic uploads (and uploads of shared or
picked media) lost their GPS tags while the rest of the EXIF survived.

- declare ACCESS_MEDIA_LOCATION in the manifest
- request it only from the picture/video automatic-uploads settings, when
  uploads are enabled (not on app start), with a snackbar on denial
- add MediaLocationUtils to resolve a content URI to its unredacted
  original (media store URIs directly, SAF document URIs via
  MediaStore.getMediaUri) and use it where upload sources are read:
  UploadFileFromContentUriWorker and CopyAndUploadContentUrisTask; any
  failure falls back to the previous behaviour
- Robolectric tests for MediaLocationUtils

Fixes opencloud-eu#218

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

GPS metadata stripped from uploaded photos

1 participant