Преглед на файлове

feat(Android): guard against missing EXIF info (#2965)

Fynn Petersen-Frey преди 2 години
родител
ревизия
99f85fb359
променени са 2 файла, в които са добавени 37 реда и са изтрити 16 реда
  1. 11 0
      mobile/lib/modules/backup/services/backup.service.dart
  2. 26 16
      mobile/lib/modules/onboarding/providers/gallery_permission.provider.dart

+ 11 - 0
mobile/lib/modules/backup/services/backup.service.dart

@@ -16,7 +16,9 @@ import 'package:immich_mobile/shared/providers/db.provider.dart';
 import 'package:immich_mobile/shared/services/api.service.dart';
 import 'package:immich_mobile/utils/files_helper.dart';
 import 'package:isar/isar.dart';
+import 'package:logging/logging.dart';
 import 'package:openapi/api.dart';
+import 'package:permission_handler/permission_handler.dart';
 import 'package:photo_manager/photo_manager.dart';
 import 'package:http_parser/http_parser.dart';
 import 'package:path/path.dart' as p;
@@ -33,6 +35,7 @@ class BackupService {
   final httpClient = http.Client();
   final ApiService _apiService;
   final Isar _db;
+  final Logger _log = Logger("BackupService");
 
   BackupService(this._apiService, this._db);
 
@@ -203,6 +206,14 @@ class BackupService {
     Function(CurrentUploadAsset) setCurrentUploadAssetCb,
     Function(ErrorUploadAsset) errorCb,
   ) async {
+    if (Platform.isAndroid &&
+        !(await Permission.accessMediaLocation.status).isGranted) {
+      // double check that permission is granted here, to guard against
+      // uploading corrupt assets without EXIF information
+      _log.warning("Media location permission is not granted. "
+          "Cannot access original assets for backup.");
+      return false;
+    }
     final String deviceId = Store.get(StoreKey.deviceId);
     final String savedEndpoint = Store.get(StoreKey.serverEndpoint);
     File? file;

+ 26 - 16
mobile/lib/modules/onboarding/providers/gallery_permission.provider.dart

@@ -6,7 +6,7 @@ import 'package:permission_handler/permission_handler.dart';
 
 class GalleryPermissionNotifier extends StateNotifier<PermissionStatus> {
   GalleryPermissionNotifier()
-    : super(PermissionStatus.denied)  // Denied is the intitial state
+      : super(PermissionStatus.denied) // Denied is the intitial state
   {
     // Sets the initial state
     getGalleryPermissionStatus();
@@ -16,19 +16,20 @@ class GalleryPermissionNotifier extends StateNotifier<PermissionStatus> {
 
   /// Requests the gallery permission
   Future<PermissionStatus> requestGalleryPermission() async {
+    PermissionStatus result;
     // Android 32 and below uses Permission.storage
     if (Platform.isAndroid) {
       final androidInfo = await DeviceInfoPlugin().androidInfo;
       if (androidInfo.version.sdkInt <= 32) {
         // Android 32 and below need storage
         final permission = await Permission.storage.request();
-        state = permission;
-        return permission;
+        result = permission;
       } else {
         // Android 33 need photo & video
         final photos = await Permission.photos.request();
         if (!photos.isGranted) {
           // Don't ask twice for the same permission
+          state = photos;
           return photos;
         }
         final videos = await Permission.videos.request();
@@ -45,28 +46,32 @@ class GalleryPermissionNotifier extends StateNotifier<PermissionStatus> {
           status = PermissionStatus.denied;
         }
 
-        state = status;
-        return status;
+        result = status;
+      }
+      if (result == PermissionStatus.granted &&
+          androidInfo.version.sdkInt >= 29) {
+        result = await Permission.accessMediaLocation.request();
       }
     } else {
       // iOS can use photos
       final photos = await Permission.photos.request();
-      state = photos;
-      return photos;
+      result = photos;
     }
+    state = result;
+    return result;
   }
 
   /// Checks the current state of the gallery permissions without
   /// requesting them again
   Future<PermissionStatus> getGalleryPermissionStatus() async {
+    PermissionStatus result;
     // Android 32 and below uses Permission.storage
     if (Platform.isAndroid) {
       final androidInfo = await DeviceInfoPlugin().androidInfo;
       if (androidInfo.version.sdkInt <= 32) {
         // Android 32 and below need storage
         final permission = await Permission.storage.status;
-        state = permission;
-        return permission;
+        result = permission;
       } else {
         // Android 33 needs photo & video
         final photos = await Permission.photos.status;
@@ -84,18 +89,23 @@ class GalleryPermissionNotifier extends StateNotifier<PermissionStatus> {
           status = PermissionStatus.denied;
         }
 
-        state = status;
-        return status;
+        result = status;
+      }
+      if (state == PermissionStatus.granted &&
+          androidInfo.version.sdkInt >= 29) {
+        result = await Permission.accessMediaLocation.status;
       }
     } else {
       // iOS can use photos
       final photos = await Permission.photos.status;
-      state = photos;
-      return photos;
+      result = photos;
     }
+    state = result;
+    return result;
   }
 }
 
-final galleryPermissionNotifier
-  = StateNotifierProvider<GalleryPermissionNotifier, PermissionStatus>
-    ((ref) => GalleryPermissionNotifier());
+final galleryPermissionNotifier =
+    StateNotifierProvider<GalleryPermissionNotifier, PermissionStatus>(
+  (ref) => GalleryPermissionNotifier(),
+);