diff --git a/mobile/android/app/src/main/kotlin/app/alextran/immich/BackgroundServicePlugin.kt b/mobile/android/app/src/main/kotlin/app/alextran/immich/BackgroundServicePlugin.kt
index 8520413cff..ae2ec22a71 100644
--- a/mobile/android/app/src/main/kotlin/app/alextran/immich/BackgroundServicePlugin.kt
+++ b/mobile/android/app/src/main/kotlin/app/alextran/immich/BackgroundServicePlugin.kt
@@ -1,25 +1,42 @@
 package app.alextran.immich
 
+import android.app.Activity
+import android.content.ContentResolver
+import android.content.ContentUris
 import android.content.Context
+import android.content.Intent
+import android.net.Uri
+import android.os.Build
+import android.os.Bundle
+import android.provider.MediaStore
+import android.provider.Settings
 import android.util.Log
+import androidx.annotation.RequiresApi
 import io.flutter.embedding.engine.plugins.FlutterPlugin
+import io.flutter.embedding.engine.plugins.activity.ActivityAware
+import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
 import io.flutter.plugin.common.BinaryMessenger
 import io.flutter.plugin.common.MethodCall
 import io.flutter.plugin.common.MethodChannel
+import io.flutter.plugin.common.MethodChannel.Result
+import io.flutter.plugin.common.PluginRegistry
 import java.security.MessageDigest
 import java.io.FileInputStream
 import kotlinx.coroutines.*
+import androidx.core.net.toUri
 
 /**
- * Android plugin for Dart `BackgroundService`
- *
- * Receives messages/method calls from the foreground Dart side to manage
- * the background service, e.g. start (enqueue), stop (cancel)
+ * Android plugin for Dart `BackgroundService` and file trash operations
  */
-class BackgroundServicePlugin : FlutterPlugin, MethodChannel.MethodCallHandler {
+class BackgroundServicePlugin : FlutterPlugin, MethodChannel.MethodCallHandler, ActivityAware, PluginRegistry.ActivityResultListener {
 
   private var methodChannel: MethodChannel? = null
+  private var fileTrashChannel: MethodChannel? = null
   private var context: Context? = null
+  private var pendingResult: Result? = null
+  private val permissionRequestCode = 1001
+  private val trashRequestCode = 1002
+  private var activityBinding: ActivityPluginBinding? = null
 
   override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) {
     onAttachedToEngine(binding.applicationContext, binding.binaryMessenger)
@@ -29,6 +46,10 @@ class BackgroundServicePlugin : FlutterPlugin, MethodChannel.MethodCallHandler {
     context = ctx
     methodChannel = MethodChannel(messenger, "immich/foregroundChannel")
     methodChannel?.setMethodCallHandler(this)
+
+    // Add file trash channel
+    fileTrashChannel = MethodChannel(messenger, "file_trash")
+    fileTrashChannel?.setMethodCallHandler(this)
   }
 
   override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
@@ -38,11 +59,14 @@ class BackgroundServicePlugin : FlutterPlugin, MethodChannel.MethodCallHandler {
   private fun onDetachedFromEngine() {
     methodChannel?.setMethodCallHandler(null)
     methodChannel = null
+    fileTrashChannel?.setMethodCallHandler(null)
+    fileTrashChannel = null
   }
 
-  override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
+  override fun onMethodCall(call: MethodCall, result: Result) {
     val ctx = context!!
     when (call.method) {
+      // Existing BackgroundService methods
       "enable" -> {
         val args = call.arguments<ArrayList<*>>()!!
         ctx.getSharedPreferences(BackupWorker.SHARED_PREF_NAME, Context.MODE_PRIVATE)
@@ -114,10 +138,184 @@ class BackgroundServicePlugin : FlutterPlugin, MethodChannel.MethodCallHandler {
         }
       }
 
+      // File Trash methods moved from MainActivity
+      "moveToTrash" -> {
+        val mediaUrls = call.argument<List<String>>("mediaUrls")
+        if (mediaUrls != null) {
+          if ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) && hasManageMediaPermission()) {
+              moveToTrash(mediaUrls, result)
+          } else {
+            result.error("PERMISSION_DENIED", "Media permission required", null)
+          }
+        } else {
+          result.error("INVALID_NAME", "The mediaUrls is not specified.", null)
+        }
+      }
+
+      "restoreFromTrash" -> {
+        val fileName = call.argument<String>("fileName")
+        val type = call.argument<Int>("type")
+        if (fileName != null && type != null) {
+          if ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) && hasManageMediaPermission()) {
+            restoreFromTrash(fileName, type, result)
+          } else {
+            result.error("PERMISSION_DENIED", "Media permission required", null)
+          }
+        } else {
+          result.error("INVALID_NAME", "The file name is not specified.", null)
+        }
+      }
+
+      "requestManageMediaPermission" -> {
+        if (!hasManageMediaPermission()) {
+          requestManageMediaPermission(result)
+        } else {
+          Log.e("Manage storage permission", "Permission already granted")
+          result.success(true)
+        }
+      }
+
       else -> result.notImplemented()
     }
   }
+
+  private fun hasManageMediaPermission(): Boolean {
+    return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+      MediaStore.canManageMedia(context!!);
+    } else  {
+      false
+    }
+  }
+
+  private fun requestManageMediaPermission(result: Result) {
+    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+      pendingResult = result // Store the result callback
+      val activity = activityBinding?.activity ?: return
+
+      val intent = Intent(Settings.ACTION_REQUEST_MANAGE_MEDIA)
+      intent.data = "package:${activity.packageName}".toUri()
+      activity.startActivityForResult(intent, permissionRequestCode)
+    } else {
+      result.success(false)
+    }
+  }
+
+  @RequiresApi(Build.VERSION_CODES.R)
+  private fun moveToTrash(mediaUrls: List<String>, result: Result) {
+    val urisToTrash = mediaUrls.map { it.toUri() }
+    if (urisToTrash.isEmpty()) {
+      result.error("INVALID_ARGS", "No valid URIs provided", null)
+      return
+    }
+
+    toggleTrash(urisToTrash, true, result);
+  }
+
+  @RequiresApi(Build.VERSION_CODES.R)
+  private fun restoreFromTrash(name: String, type: Int, result: Result) {
+    val uri = getTrashedFileUri(name, type)
+    if (uri == null) {
+      Log.e("TrashError", "Asset Uri cannot be found obtained")
+      result.error("TrashError", "Asset Uri cannot be found obtained", null)
+      return
+    }
+    Log.e("FILE_URI", uri.toString())
+    uri.let { toggleTrash(listOf(it), false, result) }
+  }
+
+  @RequiresApi(Build.VERSION_CODES.R)
+  private fun toggleTrash(contentUris: List<Uri>, isTrashed: Boolean, result: Result) {
+      val activity = activityBinding?.activity
+      val contentResolver = context?.contentResolver
+      if (activity == null || contentResolver == null) {
+        result.error("TrashError", "Activity or ContentResolver not available", null)
+        return
+      }
+
+      try {
+        val pendingIntent = MediaStore.createTrashRequest(contentResolver, contentUris, isTrashed)
+        pendingResult = result // Store for onActivityResult
+        activity.startIntentSenderForResult(
+          pendingIntent.intentSender,
+          trashRequestCode,
+          null, 0, 0, 0
+        )
+      } catch (e: Exception) {
+        Log.e("TrashError", "Error creating or starting trash request", e)
+        result.error("TrashError", "Error creating or starting trash request", null)
+    }
+  }
+
+  @RequiresApi(Build.VERSION_CODES.R)
+  private fun getTrashedFileUri(fileName: String, type: Int): Uri? {
+    val contentResolver = context?.contentResolver ?: return null
+    val queryUri = MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL)
+    val projection = arrayOf(MediaStore.Files.FileColumns._ID)
+
+    val queryArgs = Bundle().apply {
+      putString(
+        ContentResolver.QUERY_ARG_SQL_SELECTION,
+        "${MediaStore.Files.FileColumns.DISPLAY_NAME} = ?"
+      )
+      putStringArray(ContentResolver.QUERY_ARG_SQL_SELECTION_ARGS, arrayOf(fileName))
+      putInt(MediaStore.QUERY_ARG_MATCH_TRASHED, MediaStore.MATCH_ONLY)
+    }
+
+    contentResolver.query(queryUri, projection, queryArgs, null)?.use { cursor ->
+      if (cursor.moveToFirst()) {
+        val id = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns._ID))
+        // same order as AssetType from dart
+        val contentUri = when (type) {
+          1 -> MediaStore.Images.Media.EXTERNAL_CONTENT_URI
+          2 -> MediaStore.Video.Media.EXTERNAL_CONTENT_URI
+          3 -> MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
+          else -> queryUri
+        }
+        return ContentUris.withAppendedId(contentUri, id)
+      }
+    }
+    return null
+  }
+
+  // ActivityAware implementation
+  override fun onAttachedToActivity(binding: ActivityPluginBinding) {
+    activityBinding = binding
+    binding.addActivityResultListener(this)
+  }
+
+  override fun onDetachedFromActivityForConfigChanges() {
+    activityBinding?.removeActivityResultListener(this)
+    activityBinding = null
+  }
+
+  override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) {
+    activityBinding = binding
+    binding.addActivityResultListener(this)
+  }
+
+  override fun onDetachedFromActivity() {
+    activityBinding?.removeActivityResultListener(this)
+    activityBinding = null
+  }
+
+  // ActivityResultListener implementation
+  override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?): Boolean {
+    if (requestCode == permissionRequestCode) {
+      val granted = hasManageMediaPermission()
+      pendingResult?.success(granted)
+      pendingResult = null
+      return true
+    }
+
+    if (requestCode == trashRequestCode) {
+      val approved = resultCode == Activity.RESULT_OK
+      pendingResult?.success(approved)
+      pendingResult = null
+      return true
+    }
+    return false
+  }
 }
 
 private const val TAG = "BackgroundServicePlugin"
-private const val BUFFER_SIZE = 2 * 1024 * 1024;
+private const val BUFFER_SIZE = 2 * 1024 * 1024
diff --git a/mobile/android/app/src/main/kotlin/app/alextran/immich/MainActivity.kt b/mobile/android/app/src/main/kotlin/app/alextran/immich/MainActivity.kt
index 4ffb490c77..2b6bf81148 100644
--- a/mobile/android/app/src/main/kotlin/app/alextran/immich/MainActivity.kt
+++ b/mobile/android/app/src/main/kotlin/app/alextran/immich/MainActivity.kt
@@ -2,14 +2,12 @@ package app.alextran.immich
 
 import io.flutter.embedding.android.FlutterActivity
 import io.flutter.embedding.engine.FlutterEngine
-import android.os.Bundle
-import android.content.Intent
+import androidx.annotation.NonNull
 
 class MainActivity : FlutterActivity() {
-
-    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
+    override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
         super.configureFlutterEngine(flutterEngine)
         flutterEngine.plugins.add(BackgroundServicePlugin())
+        // No need to set up method channel here as it's now handled in the plugin
     }
-
 }
diff --git a/mobile/lib/domain/models/store.model.dart b/mobile/lib/domain/models/store.model.dart
index e6d9ecaf48..8a5a908e0d 100644
--- a/mobile/lib/domain/models/store.model.dart
+++ b/mobile/lib/domain/models/store.model.dart
@@ -65,6 +65,7 @@ enum StoreKey<T> {
 
   // Video settings
   loadOriginalVideo<bool>._(136),
+  manageLocalMediaAndroid<bool>._(137),
 
   // Experimental stuff
   photoManagerCustomFilter<bool>._(1000);
diff --git a/mobile/lib/interfaces/local_files_manager.interface.dart b/mobile/lib/interfaces/local_files_manager.interface.dart
new file mode 100644
index 0000000000..07274b7e29
--- /dev/null
+++ b/mobile/lib/interfaces/local_files_manager.interface.dart
@@ -0,0 +1,5 @@
+abstract interface class ILocalFilesManager {
+  Future<bool> moveToTrash(List<String> mediaUrls);
+  Future<bool> restoreFromTrash(String fileName, int type);
+  Future<bool> requestManageMediaPermission();
+}
diff --git a/mobile/lib/providers/websocket.provider.dart b/mobile/lib/providers/websocket.provider.dart
index f92d2c8421..72dbda8b6f 100644
--- a/mobile/lib/providers/websocket.provider.dart
+++ b/mobile/lib/providers/websocket.provider.dart
@@ -23,6 +23,7 @@ enum PendingAction {
   assetDelete,
   assetUploaded,
   assetHidden,
+  assetTrash,
 }
 
 class PendingChange {
@@ -160,7 +161,7 @@ class WebsocketNotifier extends StateNotifier<WebsocketState> {
         socket.on('on_upload_success', _handleOnUploadSuccess);
         socket.on('on_config_update', _handleOnConfigUpdate);
         socket.on('on_asset_delete', _handleOnAssetDelete);
-        socket.on('on_asset_trash', _handleServerUpdates);
+        socket.on('on_asset_trash', _handleOnAssetTrash);
         socket.on('on_asset_restore', _handleServerUpdates);
         socket.on('on_asset_update', _handleServerUpdates);
         socket.on('on_asset_stack_update', _handleServerUpdates);
@@ -207,6 +208,26 @@ class WebsocketNotifier extends StateNotifier<WebsocketState> {
     _debounce.run(handlePendingChanges);
   }
 
+  Future<void> _handlePendingTrashes() async {
+    final trashChanges = state.pendingChanges
+        .where((c) => c.action == PendingAction.assetTrash)
+        .toList();
+    if (trashChanges.isNotEmpty) {
+      List<String> remoteIds = trashChanges
+          .expand((a) => (a.value as List).map((e) => e.toString()))
+          .toList();
+
+      await _ref.read(syncServiceProvider).handleRemoteAssetRemoval(remoteIds);
+      await _ref.read(assetProvider.notifier).getAllAsset();
+
+      state = state.copyWith(
+        pendingChanges: state.pendingChanges
+            .whereNot((c) => trashChanges.contains(c))
+            .toList(),
+      );
+    }
+  }
+
   Future<void> _handlePendingDeletes() async {
     final deleteChanges = state.pendingChanges
         .where((c) => c.action == PendingAction.assetDelete)
@@ -267,6 +288,7 @@ class WebsocketNotifier extends StateNotifier<WebsocketState> {
     await _handlePendingUploaded();
     await _handlePendingDeletes();
     await _handlingPendingHidden();
+    await _handlePendingTrashes();
   }
 
   void _handleOnConfigUpdate(dynamic _) {
@@ -285,6 +307,10 @@ class WebsocketNotifier extends StateNotifier<WebsocketState> {
   void _handleOnAssetDelete(dynamic data) =>
       addPendingChange(PendingAction.assetDelete, data);
 
+  void _handleOnAssetTrash(dynamic data) {
+    addPendingChange(PendingAction.assetTrash, data);
+  }
+
   void _handleOnAssetHidden(dynamic data) =>
       addPendingChange(PendingAction.assetHidden, data);
 
diff --git a/mobile/lib/repositories/local_files_manager.repository.dart b/mobile/lib/repositories/local_files_manager.repository.dart
new file mode 100644
index 0000000000..c2e234d14d
--- /dev/null
+++ b/mobile/lib/repositories/local_files_manager.repository.dart
@@ -0,0 +1,25 @@
+import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:immich_mobile/interfaces/local_files_manager.interface.dart';
+import 'package:immich_mobile/utils/local_files_manager.dart';
+
+final localFilesManagerRepositoryProvider =
+    Provider((ref) => const LocalFilesManagerRepository());
+
+class LocalFilesManagerRepository implements ILocalFilesManager {
+  const LocalFilesManagerRepository();
+
+  @override
+  Future<bool> moveToTrash(List<String> mediaUrls) async {
+    return await LocalFilesManager.moveToTrash(mediaUrls);
+  }
+
+  @override
+  Future<bool> restoreFromTrash(String fileName, int type) async {
+    return await LocalFilesManager.restoreFromTrash(fileName, type);
+  }
+
+  @override
+  Future<bool> requestManageMediaPermission() async {
+    return await LocalFilesManager.requestManageMediaPermission();
+  }
+}
diff --git a/mobile/lib/services/app_settings.service.dart b/mobile/lib/services/app_settings.service.dart
index cc57b8d3a3..6413b69fce 100644
--- a/mobile/lib/services/app_settings.service.dart
+++ b/mobile/lib/services/app_settings.service.dart
@@ -61,6 +61,7 @@ enum AppSettingsEnum<T> {
     0,
   ),
   advancedTroubleshooting<bool>(StoreKey.advancedTroubleshooting, null, false),
+  manageLocalMediaAndroid<bool>(StoreKey.manageLocalMediaAndroid, null, false),
   logLevel<int>(StoreKey.logLevel, null, 5), // Level.INFO = 5
   preferRemoteImage<bool>(StoreKey.preferRemoteImage, null, false),
   loopVideo<bool>(StoreKey.loopVideo, "loopVideo", true),
diff --git a/mobile/lib/services/sync.service.dart b/mobile/lib/services/sync.service.dart
index 11a9dcb56a..80950d8c00 100644
--- a/mobile/lib/services/sync.service.dart
+++ b/mobile/lib/services/sync.service.dart
@@ -1,4 +1,5 @@
 import 'dart:async';
+import 'dart:io';
 
 import 'package:collection/collection.dart';
 import 'package:hooks_riverpod/hooks_riverpod.dart';
@@ -16,8 +17,10 @@ import 'package:immich_mobile/interfaces/album_api.interface.dart';
 import 'package:immich_mobile/interfaces/album_media.interface.dart';
 import 'package:immich_mobile/interfaces/asset.interface.dart';
 import 'package:immich_mobile/interfaces/etag.interface.dart';
+import 'package:immich_mobile/interfaces/local_files_manager.interface.dart';
 import 'package:immich_mobile/interfaces/partner.interface.dart';
 import 'package:immich_mobile/interfaces/partner_api.interface.dart';
+import 'package:immich_mobile/providers/app_settings.provider.dart';
 import 'package:immich_mobile/providers/infrastructure/exif.provider.dart';
 import 'package:immich_mobile/providers/infrastructure/user.provider.dart';
 import 'package:immich_mobile/repositories/album.repository.dart';
@@ -25,8 +28,10 @@ import 'package:immich_mobile/repositories/album_api.repository.dart';
 import 'package:immich_mobile/repositories/album_media.repository.dart';
 import 'package:immich_mobile/repositories/asset.repository.dart';
 import 'package:immich_mobile/repositories/etag.repository.dart';
+import 'package:immich_mobile/repositories/local_files_manager.repository.dart';
 import 'package:immich_mobile/repositories/partner.repository.dart';
 import 'package:immich_mobile/repositories/partner_api.repository.dart';
+import 'package:immich_mobile/services/app_settings.service.dart';
 import 'package:immich_mobile/services/entity.service.dart';
 import 'package:immich_mobile/services/hash.service.dart';
 import 'package:immich_mobile/utils/async_mutex.dart';
@@ -48,6 +53,8 @@ final syncServiceProvider = Provider(
     ref.watch(userRepositoryProvider),
     ref.watch(userServiceProvider),
     ref.watch(etagRepositoryProvider),
+    ref.watch(appSettingsServiceProvider),
+    ref.watch(localFilesManagerRepositoryProvider),
     ref.watch(partnerApiRepositoryProvider),
     ref.watch(userApiRepositoryProvider),
   ),
@@ -69,6 +76,8 @@ class SyncService {
   final IUserApiRepository _userApiRepository;
   final AsyncMutex _lock = AsyncMutex();
   final Logger _log = Logger('SyncService');
+  final AppSettingsService _appSettingsService;
+  final ILocalFilesManager _localFilesManager;
 
   SyncService(
     this._hashService,
@@ -82,6 +91,8 @@ class SyncService {
     this._userRepository,
     this._userService,
     this._eTagRepository,
+    this._appSettingsService,
+    this._localFilesManager,
     this._partnerApiRepository,
     this._userApiRepository,
   );
@@ -238,8 +249,22 @@ class SyncService {
     return null;
   }
 
+  Future<void> _moveToTrashMatchedAssets(Iterable<String> idsToDelete) async {
+    final List<Asset> localAssets = await _assetRepository.getAllLocal();
+    final List<Asset> matchedAssets = localAssets
+        .where((asset) => idsToDelete.contains(asset.remoteId))
+        .toList();
+
+    final mediaUrls = await Future.wait(
+      matchedAssets
+          .map((asset) => asset.local?.getMediaUrl() ?? Future.value(null)),
+    );
+
+    await _localFilesManager.moveToTrash(mediaUrls.nonNulls.toList());
+  }
+
   /// Deletes remote-only assets, updates merged assets to be local-only
-  Future<void> handleRemoteAssetRemoval(List<String> idsToDelete) {
+  Future<void> handleRemoteAssetRemoval(List<String> idsToDelete) async {
     return _assetRepository.transaction(() async {
       await _assetRepository.deleteAllByRemoteId(
         idsToDelete,
@@ -249,6 +274,12 @@ class SyncService {
         idsToDelete,
         state: AssetState.merged,
       );
+      if (Platform.isAndroid &&
+          _appSettingsService.getSetting<bool>(
+            AppSettingsEnum.manageLocalMediaAndroid,
+          )) {
+        await _moveToTrashMatchedAssets(idsToDelete);
+      }
       if (merged.isEmpty) return;
       for (final Asset asset in merged) {
         asset.remoteId = null;
@@ -790,10 +821,43 @@ class SyncService {
     return (existing, toUpsert);
   }
 
+  Future<void> _toggleTrashStatusForAssets(List<Asset> assetsList) async {
+    final trashMediaUrls = <String>[];
+
+    for (final asset in assetsList) {
+      if (asset.isTrashed) {
+        final mediaUrl = await asset.local?.getMediaUrl();
+        if (mediaUrl == null) {
+          _log.warning(
+            "Failed to get media URL for asset ${asset.name} while moving to trash",
+          );
+          continue;
+        }
+        trashMediaUrls.add(mediaUrl);
+      } else {
+        await _localFilesManager.restoreFromTrash(
+          asset.fileName,
+          asset.type.index,
+        );
+      }
+    }
+
+    if (trashMediaUrls.isNotEmpty) {
+      await _localFilesManager.moveToTrash(trashMediaUrls);
+    }
+  }
+
   /// Inserts or updates the assets in the database with their ExifInfo (if any)
   Future<void> upsertAssetsWithExif(List<Asset> assets) async {
     if (assets.isEmpty) return;
 
+    if (Platform.isAndroid &&
+        _appSettingsService.getSetting<bool>(
+          AppSettingsEnum.manageLocalMediaAndroid,
+        )) {
+      _toggleTrashStatusForAssets(assets);
+    }
+
     try {
       await _assetRepository.transaction(() async {
         await _assetRepository.updateAll(assets);
diff --git a/mobile/lib/utils/local_files_manager.dart b/mobile/lib/utils/local_files_manager.dart
new file mode 100644
index 0000000000..a4cf41a6e6
--- /dev/null
+++ b/mobile/lib/utils/local_files_manager.dart
@@ -0,0 +1,38 @@
+import 'package:flutter/services.dart';
+import 'package:logging/logging.dart';
+
+abstract final class LocalFilesManager {
+  static final Logger _logger = Logger('LocalFilesManager');
+  static const MethodChannel _channel = MethodChannel('file_trash');
+
+  static Future<bool> moveToTrash(List<String> mediaUrls) async {
+    try {
+      return await _channel
+          .invokeMethod('moveToTrash', {'mediaUrls': mediaUrls});
+    } catch (e, s) {
+      _logger.warning('Error moving file to trash', e, s);
+      return false;
+    }
+  }
+
+  static Future<bool> restoreFromTrash(String fileName, int type) async {
+    try {
+      return await _channel.invokeMethod(
+        'restoreFromTrash',
+        {'fileName': fileName, 'type': type},
+      );
+    } catch (e, s) {
+      _logger.warning('Error restore file from trash', e, s);
+      return false;
+    }
+  }
+
+  static Future<bool> requestManageMediaPermission() async {
+    try {
+      return await _channel.invokeMethod('requestManageMediaPermission');
+    } catch (e, s) {
+      _logger.warning('Error requesting manage media permission', e, s);
+      return false;
+    }
+  }
+}
diff --git a/mobile/lib/widgets/settings/advanced_settings.dart b/mobile/lib/widgets/settings/advanced_settings.dart
index a2e0e5b95c..d65186a191 100644
--- a/mobile/lib/widgets/settings/advanced_settings.dart
+++ b/mobile/lib/widgets/settings/advanced_settings.dart
@@ -1,11 +1,13 @@
 import 'dart:io';
 
+import 'package:device_info_plus/device_info_plus.dart';
 import 'package:easy_localization/easy_localization.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_hooks/flutter_hooks.dart' hide Store;
 import 'package:hooks_riverpod/hooks_riverpod.dart';
 import 'package:immich_mobile/domain/services/log.service.dart';
 import 'package:immich_mobile/providers/user.provider.dart';
+import 'package:immich_mobile/repositories/local_files_manager.repository.dart';
 import 'package:immich_mobile/services/app_settings.service.dart';
 import 'package:immich_mobile/utils/hooks/app_settings_update_hook.dart';
 import 'package:immich_mobile/utils/http_ssl_cert_override.dart';
@@ -25,6 +27,8 @@ class AdvancedSettings extends HookConsumerWidget {
 
     final advancedTroubleshooting =
         useAppSettingsState(AppSettingsEnum.advancedTroubleshooting);
+    final manageLocalMediaAndroid =
+        useAppSettingsState(AppSettingsEnum.manageLocalMediaAndroid);
     final levelId = useAppSettingsState(AppSettingsEnum.logLevel);
     final preferRemote = useAppSettingsState(AppSettingsEnum.preferRemoteImage);
     final allowSelfSignedSSLCert =
@@ -40,6 +44,16 @@ class AdvancedSettings extends HookConsumerWidget {
           LogService.I.setlogLevel(Level.LEVELS[levelId.value].toLogLevel()),
     );
 
+    Future<bool> checkAndroidVersion() async {
+      if (Platform.isAndroid) {
+        DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
+        AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo;
+        int sdkVersion = androidInfo.version.sdkInt;
+        return sdkVersion >= 31;
+      }
+      return false;
+    }
+
     final advancedSettings = [
       SettingsSwitchListTile(
         enabled: true,
@@ -47,6 +61,29 @@ class AdvancedSettings extends HookConsumerWidget {
         title: "advanced_settings_troubleshooting_title".tr(),
         subtitle: "advanced_settings_troubleshooting_subtitle".tr(),
       ),
+      FutureBuilder<bool>(
+        future: checkAndroidVersion(),
+        builder: (context, snapshot) {
+          if (snapshot.hasData && snapshot.data == true) {
+            return SettingsSwitchListTile(
+              enabled: true,
+              valueNotifier: manageLocalMediaAndroid,
+              title: "advanced_settings_sync_remote_deletions_title".tr(),
+              subtitle: "advanced_settings_sync_remote_deletions_subtitle".tr(),
+              onChanged: (value) async {
+                if (value) {
+                  final result = await ref
+                      .read(localFilesManagerRepositoryProvider)
+                      .requestManageMediaPermission();
+                  manageLocalMediaAndroid.value = result;
+                }
+              },
+            );
+          } else {
+            return const SizedBox.shrink();
+          }
+        },
+      ),
       SettingsSliderListTile(
         text: "advanced_settings_log_level_title".tr(args: [logLevel]),
         valueNotifier: levelId,
diff --git a/mobile/test/modules/shared/sync_service_test.dart b/mobile/test/modules/shared/sync_service_test.dart
index 3879e64237..2029ade018 100644
--- a/mobile/test/modules/shared/sync_service_test.dart
+++ b/mobile/test/modules/shared/sync_service_test.dart
@@ -60,6 +60,9 @@ void main() {
     final MockAlbumMediaRepository albumMediaRepository =
         MockAlbumMediaRepository();
     final MockAlbumApiRepository albumApiRepository = MockAlbumApiRepository();
+    final MockAppSettingService appSettingService = MockAppSettingService();
+    final MockLocalFilesManagerRepository localFilesManagerRepository =
+        MockLocalFilesManagerRepository();
     final MockPartnerApiRepository partnerApiRepository =
         MockPartnerApiRepository();
     final MockUserApiRepository userApiRepository = MockUserApiRepository();
@@ -106,6 +109,8 @@ void main() {
         userRepository,
         userService,
         eTagRepository,
+        appSettingService,
+        localFilesManagerRepository,
         partnerApiRepository,
         userApiRepository,
       );
diff --git a/mobile/test/repository.mocks.dart b/mobile/test/repository.mocks.dart
index 1c698297dc..d2f0da4231 100644
--- a/mobile/test/repository.mocks.dart
+++ b/mobile/test/repository.mocks.dart
@@ -10,6 +10,7 @@ import 'package:immich_mobile/interfaces/auth_api.interface.dart';
 import 'package:immich_mobile/interfaces/backup_album.interface.dart';
 import 'package:immich_mobile/interfaces/etag.interface.dart';
 import 'package:immich_mobile/interfaces/file_media.interface.dart';
+import 'package:immich_mobile/interfaces/local_files_manager.interface.dart';
 import 'package:immich_mobile/interfaces/partner.interface.dart';
 import 'package:immich_mobile/interfaces/partner_api.interface.dart';
 import 'package:mocktail/mocktail.dart';
@@ -41,6 +42,9 @@ class MockAuthApiRepository extends Mock implements IAuthApiRepository {}
 
 class MockAuthRepository extends Mock implements IAuthRepository {}
 
+class MockPartnerRepository extends Mock implements IPartnerRepository {}
+
 class MockPartnerApiRepository extends Mock implements IPartnerApiRepository {}
 
-class MockPartnerRepository extends Mock implements IPartnerRepository {}
+class MockLocalFilesManagerRepository extends Mock
+    implements ILocalFilesManager {}
diff --git a/mobile/test/service.mocks.dart b/mobile/test/service.mocks.dart
index d31a7e5d50..87a8c01cf0 100644
--- a/mobile/test/service.mocks.dart
+++ b/mobile/test/service.mocks.dart
@@ -1,5 +1,6 @@
 import 'package:immich_mobile/services/album.service.dart';
 import 'package:immich_mobile/services/api.service.dart';
+import 'package:immich_mobile/services/app_settings.service.dart';
 import 'package:immich_mobile/services/background.service.dart';
 import 'package:immich_mobile/services/backup.service.dart';
 import 'package:immich_mobile/services/entity.service.dart';
@@ -25,4 +26,6 @@ class MockNetworkService extends Mock implements NetworkService {}
 
 class MockSearchApi extends Mock implements SearchApi {}
 
+class MockAppSettingService extends Mock implements AppSettingsService {}
+
 class MockBackgroundService extends Mock implements BackgroundService {}