Repository navigation
v2.4.3-fix-gps-preview - UNOFFICIAL PREVIEW: Fix EXIF/GPS Metadata (#274)
Pre-release
Pre-release
·
1 commit
to master
since this release
⚠️ UNOFFICIAL PRE-RELEASE / PREVIEW BUILD
Warning
IMPORTANT NOTICE FOR TESTERS: YOU MUST UNINSTALL THE OFFICIAL APP FIRST
Because this unofficial preview APK is signed with a standalone testing key rather than the official Google Play Store private key, Android will reject an in-place upgrade with INSTALL_FAILED_UPDATE_INCOMPATIBLE.
To install and test this build:
- Uninstall the existing official Piwigo NG application from your device.
- Download and install
app-release.apkattached below. - Log in to your Piwigo instance and test uploading with/without "Strip Private Metadata".
🎯 Summary of Changes & Fixes
This build addresses upstream Issue #274 (Pull Request Piwigo/piwigo-flutter-app#279) to preserve photo EXIF and GPS coordinates when picking or sharing media on Android 10+ (API 29+), while guaranteeing data safety and respecting user privacy preferences.
Key Highlights & Critical Fixes:
- Zero Destructive Actions on Local Files:
- Original local photos on device storage (camera roll, DCIM, downloads) are strictly read-only and never modified or overwritten in place.
- When metadata removal is requested, files are copied into isolated temporary subdirectories in
cacheDirfirst, and only the temporary copy uploaded to Piwigo is scrubbed.
- Clean Filenames & Gallery Titles Preserved:
- Original filenames (e.g.
IMG_20240101_123456.jpg) are kept clean on disk by isolating files inside dedicated unique subfolders (original_media/<uuid>/filename.jpgandcompressed/<uuid>/filename.jpg) instead of prepending prefixes, ensuring Piwigo displays pristine photo titles.
- Original filenames (e.g.
- Upload Retry Protection:
- Temporary cache files are deleted only upon verified successful upload. Failed uploads retain their temporary source files so users can tap "Retry" without encountering
FileSystemException.
- Temporary cache files are deleted only upon verified successful upload. Failed uploads retain their temporary source files so users can tap "Retry" without encountering
- SAF Document URI Resolution for MediaStore.setRequireOriginal:
- Resolves Storage Access Framework (SAF) document URIs back to their underlying MediaStore content URIs (
EXTERNAL_CONTENT_URI) before applyingMediaStore.setRequireOriginal(), ensuring Android 10+ does not redact GPS.
- Resolves Storage Access Framework (SAF) document URIs back to their underlying MediaStore content URIs (
- System Media Picker Avoiding Photo Picker GPS Redaction:
- Uses
Intent.ACTION_GET_CONTENTwith the system chooser across all Android versions. This ensures Android 13/14 does not route media through the system Photo Picker which enforces hardcoded GPS location stripping by design.
- Uses
- Lossy Compression EXIF Preservation:
- When user-configured upload quality (<100%) triggers compression, EXIF tags (including GPS latitude, longitude, altitude, and timestamp) are explicitly re-injected into the compressed output via
ExifInterfaceif metadata removal is disabled.
- When user-configured upload quality (<100%) triggers compression, EXIF tags (including GPS latitude, longitude, altitude, and timestamp) are explicitly re-injected into the compressed output via
- Cross-Platform Metadata Removal (HEIC, JPEG, PNG, WEBP):
- Pairs
androidx.exifinterfacewithFlutterImageCompress(keepExif: false)to reliably strip metadata from HEIC, JPEG, PNG, and WEBP files across both Android and iOS when "Strip Private Metadata" is ON.
- Pairs
- Case-Insensitive Extension Support:
- File extensions are normalized to lowercase (
.jpg,.jpeg,.png,.heic,.webp), preventing.JPG/.PNGcamera photos from being dropped.
- File extensions are normalized to lowercase (
- Cold-Start Share Intent & Authentication Safety:
- Resolves incoming shares via
ReceiveSharingIntent.instance.getInitialMedia()with intent reset, and holds pending media until authentication succeeds if the app is launched into a logged-out state.
- Resolves incoming shares via
- Android 14 (API 34) Partial Photo Access:
- Supports
Permission.photos.isLimitedso "Select photos and videos" does not abort upload.
- Supports
- Activity Lifecycle Resilience & Memory Leak Prevention:
- Removed static companion object references for
MethodChannel.Result. Result callbacks are bound to the instance lifecycle, preventing memory leaks and avoiding hanging method channels if Android recreates the activity.
- Removed static companion object references for
- External Share Intent GPS Preservation:
- Automatically requests/checks runtime
ACCESS_MEDIA_LOCATIONpermissions before resolving incoming shared media inreceive_sharing.dartandupload.dart, preventing Android 10+ from throwingSecurityExceptionand falling back to redacted location-free media when shared directly from external gallery apps.
- Automatically requests/checks runtime
- Cache Storage Hygiene & Zero Disk Leaks:
- Automatically purges intermediate uncompressed copies in
original_media/as soon as compression and EXIF transfer complete, preventing orphaned cache files and eliminating risk of out-of-space (ENOSPC) errors during large batch uploads.
- Automatically purges intermediate uncompressed copies in
Upstream PR Reference:
- Pull Request: Piwigo/piwigo-flutter-app#279 on
develop.