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) => { }); }
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}"); } }); } }); } }
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); }
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 (); } }); }
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 (); } }); }
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(); } }); }