Example #1
0
        void SaveToAlbum(string watermarkedPath)
        {
            var lib = PHPhotoLibrary.SharedPhotoLibrary;

            lib.PerformChanges(() =>
            {
                var album             = PHAssetCollection.FetchAssetCollections(new[] { Xamarin.Essentials.Preferences.Get("iOSAlbumIdentifier", string.Empty) }, null)?.firstObject as PHAssetCollection;
                var collectionRequest = PHAssetCollectionChangeRequest.ChangeRequest(album);

                if (UIDevice.CurrentDevice.CheckSystemVersion(9, 0))
                {
                    var options = new PHAssetResourceCreationOptions
                    {
                        ShouldMoveFile = true
                    };
                    var changeRequest = PHAssetCreationRequest.CreationRequestForAsset();
                    changeRequest.AddResource(PHAssetResourceType.Video, NSUrl.FromString(watermarkedPath), options);

                    collectionRequest.AddAssets(new[] { changeRequest.PlaceholderForCreatedAsset });
                }
                else
                {
                    var changeRequest2 = PHAssetChangeRequest.FromVideo(NSUrl.FromString(watermarkedPath));
                    collectionRequest.AddAssets(new[] { changeRequest2.PlaceholderForCreatedAsset });
                }

                RetrieveLastAssetSaved();
            }, (success, err) =>
            {
            });
        }
Example #2
0
        private void SaveVideoToLibrary(NSUrl outputFileUrl)
        {
            var creationRequest      = PHAssetCreationRequest.CreationRequestForAsset();
            var videoResourceOptions = new PHAssetResourceCreationOptions {
                ShouldMoveFile = true
            };

            creationRequest.AddResource(PHAssetResourceType.Video, outputFileUrl,
                                        videoResourceOptions);
        }
        public override void DidFinishCapture(AVCapturePhotoOutput captureOutput, AVCaptureResolvedPhotoSettings resolvedSettings, NSError error)
        {
            if (error != null)
            {
                Console.WriteLine($"Error capturing photo: {error.LocalizedDescription})");
                DidFinish();
                return;
            }

            if (photoData == null)
            {
                Console.WriteLine("No photo data resource");
                DidFinish();
                return;
            }

            PHPhotoLibrary.RequestAuthorization(status =>
            {
                if (status == PHAuthorizationStatus.Authorized)
                {
                    PHPhotoLibrary.SharedPhotoLibrary.PerformChanges(() =>
                    {
                        var options = new PHAssetResourceCreationOptions
                        {
                            UniformTypeIdentifier = RequestedPhotoSettings.ProcessedFileType,
                        };

                        var creationRequest = PHAssetCreationRequest.CreationRequestForAsset();
                        creationRequest.AddResource(PHAssetResourceType.Photo, photoData, options);

                        var url = livePhotoCompanionMovieUrl;
                        if (url != null)
                        {
                            var livePhotoCompanionMovieFileResourceOptions = new PHAssetResourceCreationOptions
                            {
                                ShouldMoveFile = true
                            };
                            creationRequest.AddResource(PHAssetResourceType.PairedVideo, url, livePhotoCompanionMovieFileResourceOptions);
                        }
                    }, (success, err) =>
                    {
                        if (err != null)
                        {
                            Console.WriteLine($"Error occurered while saving photo to photo library: {error.LocalizedDescription}");
                        }
                        DidFinish();
                    });
                }
                else
                {
                    DidFinish();
                }
            });
        }
        // キャプチャー後処理
        public override void DidFinishCapture(AVCapturePhotoOutput captureOutput, AVCaptureResolvedPhotoSettings resolvedSettings, NSError error)
        {
            if (error != null)
            {
                Console.WriteLine($"Error capturing photo: {error.LocalizedDescription})");
                return;
            }

            if (photoData == null)
            {
                Console.WriteLine("No photo data resource");
                return;
            }

            // 撮影したラベル画像をフォトアルバムに保存するか
            // フォトアルバムに保存する必要が出てきた真偽値をTrueにする
            bool IsSaveToPhotoAlbum = false;

            // 画像を保存するかどうかの判定
            if (IsSaveToPhotoAlbum)
            {
                // 撮影した画像を保存する処理
                PHPhotoLibrary.RequestAuthorization(status =>
                {
                    if (status == PHAuthorizationStatus.Authorized)
                    {
                        PHPhotoLibrary.SharedPhotoLibrary.PerformChanges(() =>
                        {
                            var creationRequest = PHAssetCreationRequest.CreationRequestForAsset();
                            creationRequest.AddResource(PHAssetResourceType.Photo, photoData, null);

                            var url = livePhotoCompanionMovieUrl;
                            if (url != null)
                            {
                                var livePhotoCompanionMovieFileResourceOptions = new PHAssetResourceCreationOptions
                                {
                                    ShouldMoveFile = true
                                };
                                creationRequest.AddResource(PHAssetResourceType.PairedVideo, url, livePhotoCompanionMovieFileResourceOptions);
                            }
                        }, (success, err) =>
                        {
                            if (err != null)
                            {
                                Console.WriteLine($"Error occurered while saving photo to photo library: {error.LocalizedDescription}");
                            }
                        });
                    }
                });
            }
        }
Example #5
0
        private void TryToAddPhotoToLibrary()
        {
            var creationRequest = PHAssetCreationRequest.CreationRequestForAsset();

            creationRequest.AddResource(PHAssetResourceType.Photo, PhotoData, null);

            if (_livePhotoCompanionMovieUrl == null)
            {
                return;
            }

            var livePhotoCompanionMovieFileResourceOptions = new PHAssetResourceCreationOptions
            {
                ShouldMoveFile = true
            };

            creationRequest.AddResource(PHAssetResourceType.PairedVideo, _livePhotoCompanionMovieUrl,
                                        livePhotoCompanionMovieFileResourceOptions);
        }
Example #6
0
        public void FinishedRecording(AVCaptureFileOutput captureOutput, NSUrl outputFileUrl, NSObject[] connections, NSError error)
        {
            /*
             *      Note that currentBackgroundRecordingID is used to end the background task
             *      associated with this recording. This allows a new recording to be started,
             *      associated with a new UIBackgroundTaskIdentifier, once the movie file output's
             *      `recording` property is back to NO — which happens sometime after this method
             *      returns.
             *
             *      Note: Since we use a unique file path for each recording, a new recording will
             *      not overwrite a recording currently being saved.
             */
            var currentBackgroundRecordingId = backgroundRecordingId;

            backgroundRecordingId = UIApplication.BackgroundTaskInvalid;

            Action cleanup = () =>
            {
                if (NSFileManager.DefaultManager.FileExists(outputFileUrl.Path))
                {
                    NSError tError;
                    NSFileManager.DefaultManager.Remove(outputFileUrl.Path, out tError);
                }

                if (currentBackgroundRecordingId != UIApplication.BackgroundTaskInvalid)
                {
                    UIApplication.SharedApplication.EndBackgroundTask(currentBackgroundRecordingId);
                }
            };

            var success = true;

            if (error != null)
            {
                Console.WriteLine($"Movie file finishing error: {error}");
                var tmpObj = error.UserInfo[AVErrorKeys.RecordingSuccessfullyFinished];
                if (tmpObj is NSNumber)
                {
                    success = ((NSNumber)tmpObj).BoolValue;
                }
                else if (tmpObj is NSString)
                {
                    success = ((NSString)tmpObj).BoolValue();
                }
            }
            if (success)
            {
                // Check authorization status.
                PHPhotoLibrary.RequestAuthorization((PHAuthorizationStatus status) =>
                {
                    if (status == PHAuthorizationStatus.Authorized)
                    {
                        // Save the movie file to the photo library and cleanup.
                        PHPhotoLibrary.SharedPhotoLibrary.PerformChanges(() =>
                        {
                            var options            = new PHAssetResourceCreationOptions();
                            options.ShouldMoveFile = true;
                            var creationRequest    = PHAssetCreationRequest.CreationRequestForAsset();
                            creationRequest.AddResource(PHAssetResourceType.Video, outputFileUrl, options);
                        }, (cbSuccess, cbError) =>
                        {
                            if (!cbSuccess)
                            {
                                Console.WriteLine($"Could not save movie to photo library: {cbError}");
                            }
                            cleanup();
                        });
                    }
                    else
                    {
                        cleanup();
                    }
                });
            }
            else
            {
                cleanup();
            }

            // Enable the Camera and Record buttons to let the user switch camera and start another recording.
            //DispatchQueue.MainQueue.DispatchAsync(() =>
            //{
            //	// Only enable the ability to change camera if the device has more than one camera.
            //	CameraButton.Enabled = (videoDeviceDiscoverySession.UniqueDevicePositionsCount() > 1);
            //	RecordButton.Enabled = true;
            //	CaptureModeControl.Enabled = true;
            //	RecordButton.SetTitle(NSBundle.MainBundle.LocalizedString(@"Record", @"Recording button record title"), UIControlState.Normal);
            //});
        }
		public void DidFinishCapture (AVCapturePhotoOutput captureOutput, AVCaptureResolvedPhotoSettings resolvedSettings, NSError error)
		{
			if (error != null) {
				Console.WriteLine ($"Error capturing photo: {error.LocalizedDescription})");
				DidFinish ();
				return;
			}

			if (photoData == null) {
				Console.WriteLine ("No photo data resource");
				DidFinish ();
				return;
			}

			PHPhotoLibrary.RequestAuthorization (status => {
				if (status == PHAuthorizationStatus.Authorized) {
					PHPhotoLibrary.SharedPhotoLibrary.PerformChanges (() => {
						var creationRequest = PHAssetCreationRequest.CreationRequestForAsset ();
						creationRequest.AddResource (PHAssetResourceType.Photo, photoData, null);

						var url = livePhotoCompanionMovieUrl;
						if (url != null) {
							var livePhotoCompanionMovieFileResourceOptions = new PHAssetResourceCreationOptions {
								ShouldMoveFile = true
							};
							creationRequest.AddResource (PHAssetResourceType.PairedVideo, url, livePhotoCompanionMovieFileResourceOptions);
						}
					}, (success, err) => {
						if (err != null)
							Console.WriteLine ($"Error occurered while saving photo to photo library: {error.LocalizedDescription}");
						DidFinish ();
					});
				} else {
					DidFinish ();
				}
			});
		}
Example #8
0
        public void FinishedRecording(AVCaptureFileOutput captureOutput, NSUrl outputFileUrl, NSObject[] connections, NSError error)
        {
            // Note that currentBackgroundRecordingID is used to end the background task associated with this recording.
            // This allows a new recording to be started, associated with a new UIBackgroundTaskIdentifier, once the movie file output's isRecording property
            // is back to false — which happens sometime after this method returns.
            // Note: Since we use a unique file path for each recording, a new recording will not overwrite a recording currently being saved.

            Action cleanup = () => {
                var path = outputFileUrl.Path;
                if (NSFileManager.DefaultManager.FileExists(path))
                {
                    NSError err;
                    if (!NSFileManager.DefaultManager.Remove(path, out err))
                    {
                        Console.WriteLine($"Could not remove file at url: {outputFileUrl}");
                    }
                }
                var currentBackgroundRecordingID = backgroundRecordingID;
                if (currentBackgroundRecordingID != -1)
                {
                    backgroundRecordingID = -1;
                    UIApplication.SharedApplication.EndBackgroundTask(currentBackgroundRecordingID);
                }
            };

            bool success = true;

            if (error != null)
            {
                Console.WriteLine($"Movie file finishing error: {error.LocalizedDescription}");
                success = ((NSNumber)error.UserInfo[AVErrorKeys.RecordingSuccessfullyFinished]).BoolValue;
            }

            if (success)
            {
                // Check authorization status.
                PHPhotoLibrary.RequestAuthorization(status => {
                    if (status == PHAuthorizationStatus.Authorized)
                    {
                        // Save the movie file to the photo library and cleanup.
                        PHPhotoLibrary.SharedPhotoLibrary.PerformChanges(() => {
                            var options = new PHAssetResourceCreationOptions
                            {
                                ShouldMoveFile = true
                            };
                            var creationRequest = PHAssetCreationRequest.CreationRequestForAsset();
                            creationRequest.AddResource(PHAssetResourceType.Video, outputFileUrl, options);
                        }, (success2, error2) => {
                            if (!success2)
                            {
                                Console.WriteLine($"Could not save movie to photo library: {error2}");
                            }
                            cleanup();
                        });
                    }
                    else
                    {
                        cleanup();
                    }
                });
            }
            else
            {
                cleanup();
            }

            // Enable the Camera and Record buttons to let the user switch camera and start another recording.
            DispatchQueue.MainQueue.DispatchAsync(() => {
                // Only enable the ability to change camera if the device has more than one camera.
                CameraButton.Enabled       = UniqueDevicePositionsCount(videoDeviceDiscoverySession) > 1;
                RecordButton.Enabled       = true;
                CaptureModeControl.Enabled = true;
                RecordButton.SetTitle("Record", UIControlState.Normal);
            });
        }
		public void FinishedRecording (AVCaptureFileOutput captureOutput, NSUrl outputFileUrl, NSObject [] connections, NSError error)
		{
			// Note that currentBackgroundRecordingID is used to end the background task associated with this recording.
			// This allows a new recording to be started, associated with a new UIBackgroundTaskIdentifier, once the movie file output's isRecording property
			// is back to false — which happens sometime after this method returns.
			// Note: Since we use a unique file path for each recording, a new recording will not overwrite a recording currently being saved.

			Action cleanup = () => {
				var path = outputFileUrl.Path;
				if (NSFileManager.DefaultManager.FileExists (path)) {
					NSError err;
					if (!NSFileManager.DefaultManager.Remove (path, out err))
						Console.WriteLine ($"Could not remove file at url: {outputFileUrl}");

				}
				var currentBackgroundRecordingID = backgroundRecordingID;
				if (currentBackgroundRecordingID != -1) {
					backgroundRecordingID = -1;
					UIApplication.SharedApplication.EndBackgroundTask (currentBackgroundRecordingID);
				}
			};

			bool success = true;
			if (error != null) {
				Console.WriteLine ($"Movie file finishing error: {error.LocalizedDescription}");
				success = ((NSNumber)error.UserInfo [AVErrorKeys.RecordingSuccessfullyFinished]).BoolValue;
			}

			if (success) {
				// Check authorization status.
				PHPhotoLibrary.RequestAuthorization (status => {
					if (status == PHAuthorizationStatus.Authorized) {
						// Save the movie file to the photo library and cleanup.
						PHPhotoLibrary.SharedPhotoLibrary.PerformChanges (() => {
							var options = new PHAssetResourceCreationOptions {
								ShouldMoveFile = true
							};
							var creationRequest = PHAssetCreationRequest.CreationRequestForAsset ();
							creationRequest.AddResource (PHAssetResourceType.Video, outputFileUrl, options);
						}, (success2, error2) => {
							if (!success2)
								Console.WriteLine ($"Could not save movie to photo library: {error2}");
							cleanup ();
						});
					} else {
						cleanup ();
					}
				});
			} else {
				cleanup ();
			}

			// Enable the Camera and Record buttons to let the user switch camera and start another recording.
			DispatchQueue.MainQueue.DispatchAsync (() => {
				// Only enable the ability to change camera if the device has more than one camera.
				CameraButton.Enabled = UniqueDevicePositionsCount (videoDeviceDiscoverySession) > 1;
				RecordButton.Enabled = true;
				CaptureModeControl.Enabled = true;
				RecordButton.SetTitle ("Record", UIControlState.Normal);
			});
		}
        public static void RestoreFromArchive(string filePath, Action onSuccess = null, Action <NSError> onFailure = null)
        {
            if (PHPhotoLibrary.AuthorizationStatus != PHAuthorizationStatus.Authorized)
            {
                onFailure?.Invoke(null);
                return;
            }

            var resources = new List <string>();

            var rootPath = Path.Combine(Paths.Temporary, Path.GetFileNameWithoutExtension(filePath));

            Directory.CreateDirectory(rootPath);
            using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
                using (var archive = new ZipArchive(stream, ZipArchiveMode.Read))
                {
                    foreach (var entry in archive.Entries)
                    {
                        if (entry.Name == "@")
                        {
                            continue;
                        }
                        var entryPath = Path.Combine(rootPath, entry.Name);
                        using (var fileStream = new FileStream(entryPath, FileMode.Create, FileAccess.ReadWrite, FileShare.None))
                        { entry.Open().CopyTo(fileStream); }
                        if (entry.Name.Contains("(Photo)", StringComparison.InvariantCulture) || entry.Name.Contains("(Video)", StringComparison.InvariantCulture))
                        {
                            resources.Insert(0, entryPath);
                        }
                        else
                        {
                            resources.Add(entryPath);
                        }
                    }
                }

            PHPhotoLibrary.SharedPhotoLibrary.PerformChanges(() =>
            {
                var request = PHAssetCreationRequest.CreationRequestForAsset();
                var options = new PHAssetResourceCreationOptions {
                    ShouldMoveFile = true
                };
                foreach (var path in resources)
                {
                    var fileName = Path.GetFileName(path);
                    if (fileName.IndexOf('(') != -1)
                    {
                        var indexLeft    = fileName.IndexOf('(') + 1;
                        var resourceType = fileName.Substring(indexLeft, fileName.IndexOf(')') - indexLeft);
                        var type         = (PHAssetResourceType)Enum.Parse(typeof(PHAssetResourceType), resourceType);
                        request.AddResource(type, NSUrl.FromFilename(path), options);
                    }
                }
            }, (isSuccess, error) =>
            {
                try { Directory.Delete(rootPath, true); }
                catch { }

                if (isSuccess)
                {
                    onSuccess?.Invoke();
                }
                else
                {
                    onFailure?.Invoke(error);
                }
            });
        }
		public void FinishedRecording (AVCaptureFileOutput captureOutput, NSUrl outputFileUrl, NSObject [] connections, NSError error)
		{
			// Note that currentBackgroundRecordingID is used to end the background task associated with this recording.
			// This allows a new recording to be started, associated with a new UIBackgroundTaskIdentifier, once the movie file output's Recording property
			// is back to false — which happens sometime after this method returns.
			// Note: Since we use a unique file path for each recording, a new recording will not overwrite a recording currently being saved.
			var currentBackgroundRecordingID = backgroundRecordingID;
			backgroundRecordingID = -1;

			Action cleanup = () => {
				NSError err;
				if (NSFileManager.DefaultManager.FileExists (outputFileUrl.Path))
					NSFileManager.DefaultManager.Remove (outputFileUrl, out err);

				if (currentBackgroundRecordingID != -1)
					UIApplication.SharedApplication.EndBackgroundTask (currentBackgroundRecordingID);
			};

			var success = true;

			if (error != null) {
				Console.WriteLine ($"Error occurred while capturing movie: {error}");
				success = error.UserInfo [AVErrorKeys.RecordingSuccessfullyFinished].AsBool ();
			}
			if (success) {
				PHPhotoLibrary.RequestAuthorization (status => {
					if (status == PHAuthorizationStatus.Authorized) {
						// Save the movie file to the photo library and cleanup
						PHPhotoLibrary.SharedPhotoLibrary.PerformChanges (() => {
							// In iOS 9 and later, it's possible to move the file into the photo library without duplicating the file data.
							// This avoids using double the disk space during save, which can make a difference on devices with limited free disk space.
							var options = new PHAssetResourceCreationOptions { ShouldMoveFile = true };
							PHAssetCreationRequest changeRequest = PHAssetCreationRequest.CreationRequestForAsset ();
							changeRequest.AddResource (PHAssetResourceType.Video, outputFileUrl, options);
						}, (result, err) => {
							if (!result)
								Console.WriteLine ($"Could not save movie to photo library: {err}");
							cleanup ();
						});
					} else {
						cleanup ();
					}
				});
			} else {
				cleanup ();
			}

			// Enable the Camera and Record buttons to let the user switch camera and start another recording
			DispatchQueue.MainQueue.DispatchAsync (() => {
				// Only enable the ability to change camera if the device has more than one camera
				CameraButton.Enabled = (AVCaptureDevice.DevicesWithMediaType (AVMediaType.Video).Length > 1);
				RecordButton.Enabled = CaptureModeControl.SelectedSegment == (int)CaptureMode.Movie;
				RecordButton.SetTitle ("Record", UIControlState.Normal);
				CaptureModeControl.Enabled = true;
			});
		}
		void DidFinishProcessingRawPhoto (AVCapturePhotoOutput captureOutput,
										  CMSampleBuffer rawSampleBuffer, CMSampleBuffer previewPhotoSampleBuffer,
										  AVCaptureResolvedPhotoSettings resolvedSettings, AVCaptureBracketedStillImageSettings bracketSettings,
										  NSError error)
		{
			if (rawSampleBuffer == null) {
				Console.WriteLine ($"Error occurred while capturing photo: {error}");
				return;
			}

			var filePath = Path.Combine (Path.GetTempPath (), $"{resolvedSettings.UniqueID}.dng");
			NSData imageData = AVCapturePhotoOutput.GetDngPhotoDataRepresentation (rawSampleBuffer, previewPhotoSampleBuffer);
			imageData.Save (filePath, true);

			PHPhotoLibrary.RequestAuthorization (status => {
				if (status == PHAuthorizationStatus.Authorized) {
					PHPhotoLibrary.SharedPhotoLibrary.PerformChanges (() => {
						// In iOS 9 and later, it's possible to move the file into the photo library without duplicating the file data.
						// This avoids using double the disk space during save, which can make a difference on devices with limited free disk space.
						var options = new PHAssetResourceCreationOptions ();
						options.ShouldMoveFile = true;
						PHAssetCreationRequest.CreationRequestForAsset ().AddResource (PHAssetResourceType.Photo, filePath, options); // Add move (not copy) option
					}, (success, err) => {
						if (!success)
							Console.WriteLine ($"Error occurred while saving raw photo to photo library: {err}");
						else
							Console.WriteLine ("Raw photo was saved to photo library");

						NSError rErr;
						if (NSFileManager.DefaultManager.FileExists (filePath))
							NSFileManager.DefaultManager.Remove (filePath, out rErr);
					});
				} else {
					Console.WriteLine ("Not authorized to save photo");
				}
			});
		}
		public void FinishedRecording (AVCaptureFileOutput captureOutput, NSUrl outputFileUrl, NSObject[] connections, NSError error)
		{
			// Note that currentBackgroundRecordingID is used to end the background task associated with this recording.
			// This allows a new recording to be started, associated with a new UIBackgroundTaskIdentifier, once the movie file output's isRecording property
			// is back to NO — which happens sometime after this method returns.
			// Note: Since we use a unique file path for each recording, a new recording will not overwrite a recording currently being saved.

			var currentBackgroundRecordingID = backgroundRecordingID;
			backgroundRecordingID = -1;
			Action cleanup = () => {
				NSError err;
				NSFileManager.DefaultManager.Remove (outputFileUrl, out err);
				if (currentBackgroundRecordingID != -1)
					UIApplication.SharedApplication.EndBackgroundTask (currentBackgroundRecordingID);
			};

			bool success = true;
			if (error != null) {
				Console.WriteLine ("Movie file finishing error: {0}", error);
				success = ((NSNumber)error.UserInfo [AVErrorKeys.RecordingSuccessfullyFinished]).BoolValue;
			}

			if (!success) {
				cleanup ();
				return;
			}
			// Check authorization status.
			PHPhotoLibrary.RequestAuthorization (status => {
				if (status == PHAuthorizationStatus.Authorized) {
					// Save the movie file to the photo library and cleanup.
					PHPhotoLibrary.SharedPhotoLibrary.PerformChanges (() => {
						// In iOS 9 and later, it's possible to move the file into the photo library without duplicating the file data.
						// This avoids using double the disk space during save, which can make a difference on devices with limited free disk space.
						if (UIDevice.CurrentDevice.CheckSystemVersion (9, 0)) {
							var options = new PHAssetResourceCreationOptions {
								ShouldMoveFile = true
							};
							var changeRequest = PHAssetCreationRequest.CreationRequestForAsset ();
							changeRequest.AddResource (PHAssetResourceType.Video, outputFileUrl, options);
						} else {
							PHAssetChangeRequest.FromVideo (outputFileUrl);
						}
					}, (success2, error2) => {
						if (!success2)
							Console.WriteLine ("Could not save movie to photo library: {0}", error2);
						cleanup ();
					});
				} else {
					cleanup ();
				}
			});
		}
Example #14
0
        public void FinishedRecording(AVCaptureFileOutput captureOutput, NSUrl outputFileUrl, NSObject[] connections, NSError error)
        {
            // Note that currentBackgroundRecordingID is used to end the background task associated with this recording.
            // This allows a new recording to be started, associated with a new UIBackgroundTaskIdentifier, once the movie file output's isRecording property
            // is back to NO — which happens sometime after this method returns.
            // Note: Since we use a unique file path for each recording, a new recording will not overwrite a recording currently being saved.

            var currentBackgroundRecordingID = backgroundRecordingID;

            backgroundRecordingID = -1;
            Action cleanup = () => {
                NSError err;
                NSFileManager.DefaultManager.Remove(outputFileUrl, out err);
                if (currentBackgroundRecordingID != -1)
                {
                    UIApplication.SharedApplication.EndBackgroundTask(currentBackgroundRecordingID);
                }
            };

            bool success = true;

            if (error != null)
            {
                Console.WriteLine("Movie file finishing error: {0}", error);
                success = ((NSNumber)error.UserInfo [AVErrorKeys.RecordingSuccessfullyFinished]).BoolValue;
            }

            if (!success)
            {
                cleanup();
                return;
            }
            // Check authorization status.
            PHPhotoLibrary.RequestAuthorization(status => {
                if (status == PHAuthorizationStatus.Authorized)
                {
                    // Save the movie file to the photo library and cleanup.
                    PHPhotoLibrary.SharedPhotoLibrary.PerformChanges(() => {
                        // In iOS 9 and later, it's possible to move the file into the photo library without duplicating the file data.
                        // This avoids using double the disk space during save, which can make a difference on devices with limited free disk space.
                        if (UIDevice.CurrentDevice.CheckSystemVersion(9, 0))
                        {
                            var options = new PHAssetResourceCreationOptions {
                                ShouldMoveFile = true
                            };
                            var changeRequest = PHAssetCreationRequest.CreationRequestForAsset();
                            changeRequest.AddResource(PHAssetResourceType.Video, outputFileUrl, options);
                        }
                        else
                        {
                            PHAssetChangeRequest.FromVideo(outputFileUrl);
                        }
                    }, (success2, error2) => {
                        if (!success2)
                        {
                            Console.WriteLine("Could not save movie to photo library: {0}", error2);
                        }
                        cleanup();
                    });
                }
                else
                {
                    cleanup();
                }
            });
        }