void FinishCapture(object sender, Tuple <NSObject, NSError> e)
        {
            if (Element == null || Control == null)
            {
                return;
            }

            if (e.Item2 != null)
            {
                Element.RaiseMediaCaptureFailed(e.Item2.LocalizedDescription);
                return;
            }

            var photoData = e.Item1 as NSData;

            if (!Element.SavePhotoToFile && photoData != null)
            {
                var data = UIImage.LoadFromData(photoData).AsJPEG().ToArray();
                Device.BeginInvokeOnMainThread(() =>
                {
                    Element.RaiseMediaCaptured(new MediaCapturedEventArgs(imageData: data));
                });
                return;
            }

            PHObjectPlaceholder placeholder = null;

            PHPhotoLibrary.RequestAuthorization(status =>
            {
                if (status != PHAuthorizationStatus.Authorized)
                {
                    return;
                }

                // Save the captured file to the photo library.
                PHPhotoLibrary.SharedPhotoLibrary.PerformChanges(() =>
                {
                    var creationRequest = PHAssetCreationRequest.CreationRequestForAsset();
                    if (photoData != null)
                    {
                        creationRequest.AddResource(PHAssetResourceType.Photo, photoData, null);
                        placeholder = creationRequest.PlaceholderForCreatedAsset;
                    }
                    else if (e.Item1 is NSUrl outputFileUrl)
                    {
                        creationRequest.AddResource(
                            PHAssetResourceType.Video,
                            outputFileUrl,
                            new PHAssetResourceCreationOptions
                        {
                            ShouldMoveFile = true
                        });
                        placeholder = creationRequest.PlaceholderForCreatedAsset;
                    }
                }, (success2, error2) =>
                {
                    if (!success2)
                    {
                        Debug.WriteLine($"Could not save media to photo library: {error2}");
                        if (error2 != null)
                        {
                            Element.RaiseMediaCaptureFailed(error2.LocalizedDescription);
                            return;
                        }
                        Element.RaiseMediaCaptureFailed($"Could not save media to photo library");
                        return;
                    }

                    if (!(PHAsset.FetchAssetsUsingLocalIdentifiers(new[] { placeholder.LocalIdentifier }, null).firstObject is PHAsset asset))
                    {
                        Element.RaiseMediaCaptureFailed($"Could not save media to photo library");
                        return;
                    }
                    if (asset.MediaType == PHAssetMediaType.Image)
                    {
                        asset.RequestContentEditingInput(new PHContentEditingInputRequestOptions
                        {
                            CanHandleAdjustmentData = p => true
                        }, (input, info) =>
                        {
                            Device.BeginInvokeOnMainThread(() =>
                            {
                                Element.RaiseMediaCaptured(new MediaCapturedEventArgs(input.FullSizeImageUrl.Path));
                            });
                        });
                    }
                    else if (asset.MediaType == PHAssetMediaType.Video)
                    {
                        PHImageManager.DefaultManager.RequestAvAsset(asset, new PHVideoRequestOptions
                        {
                            Version = PHVideoRequestOptionsVersion.Original
                        }, (avAsset, mix, info) =>
                        {
                            if (!(avAsset is AVUrlAsset urlAsset))
                            {
                                Element.RaiseMediaCaptureFailed($"Could not save media to photo library");
                                return;
                            }
                            Device.BeginInvokeOnMainThread(() =>
                            {
                                Element.RaiseMediaCaptured(new MediaCapturedEventArgs(urlAsset.Url.Path));
                            });
                        });
                    }
                });
예제 #2
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);
            //});
        }
예제 #3
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 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);
                }
            });
        }
예제 #5
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();
                }
            });
        }
예제 #6
0
        void SnapStillImage(CameraViewController sender)
        {
            SessionQueue.DispatchAsync(async() => {
                AVCaptureConnection connection = StillImageOutput.ConnectionFromMediaType(AVMediaType.Video);
                var previewLayer = (AVCaptureVideoPreviewLayer)PreviewView.Layer;

                // Update the orientation on the still image output video connection before capturing.
                connection.VideoOrientation = previewLayer.Connection.VideoOrientation;

                // Flash set to Auto for Still Capture.
                SetFlashModeForDevice(AVCaptureFlashMode.Auto, VideoDeviceInput.Device);

                // Capture a still image.
                try {
                    var imageDataSampleBuffer = await StillImageOutput.CaptureStillImageTaskAsync(connection);

                    // The sample buffer is not retained. Create image data before saving the still image to the photo library asynchronously.
                    NSData imageData = AVCaptureStillImageOutput.JpegStillToNSData(imageDataSampleBuffer);

                    PHPhotoLibrary.RequestAuthorization(status => {
                        if (status == PHAuthorizationStatus.Authorized)
                        {
                            // To preserve the metadata, we create an asset from the JPEG NSData representation.
                            // Note that creating an asset from a UIImage discards the metadata.

                            // In iOS 9, we can use AddResource method on PHAssetCreationRequest class.
                            // In iOS 8, we save the image to a temporary file and use +[PHAssetChangeRequest creationRequestForAssetFromImageAtFileURL:].

                            if (UIDevice.CurrentDevice.CheckSystemVersion(9, 0))
                            {
                                PHPhotoLibrary.SharedPhotoLibrary.PerformChanges(() => {
                                    var request = PHAssetCreationRequest.CreationRequestForAsset();
                                    request.AddResource(PHAssetResourceType.Photo, imageData, null);
                                }, (success, err) => {
                                    if (!success)
                                    {
                                        Console.WriteLine("Error occurred while saving image to photo library: {0}", err);
                                    }
                                });
                            }
                            else
                            {
                                var temporaryFileUrl = new NSUrl(GetTmpFilePath("jpg"), false);
                                PHPhotoLibrary.SharedPhotoLibrary.PerformChanges(() => {
                                    NSError error = null;
                                    if (imageData.Save(temporaryFileUrl, NSDataWritingOptions.Atomic, out error))
                                    {
                                        PHAssetChangeRequest.FromImage(temporaryFileUrl);
                                    }
                                    else
                                    {
                                        Console.WriteLine("Error occured while writing image data to a temporary file: {0}", error);
                                    }
                                }, (success, error) => {
                                    if (!success)
                                    {
                                        Console.WriteLine("Error occurred while saving image to photo library: {0}", error);
                                    }

                                    // Delete the temporary file.
                                    NSError deleteError;
                                    NSFileManager.DefaultManager.Remove(temporaryFileUrl, out deleteError);
                                });
                            }
                        }
                    });
                } catch (NSErrorException ex) {
                    Console.WriteLine("Could not capture still image: {0}", ex.Error);
                }
            });
        }
        private async void SnapStillImage()
        {
            //
            if ((m_videoDevice != null) && (m_stillImageOutput != null))
            {
                if (m_videoDevice.HasFlash && m_videoDevice.IsFlashModeSupported(AVCaptureFlashMode.Auto))
                {
                    NSError error;
                    if (m_videoDevice.LockForConfiguration(out error))
                    {
                        m_videoDevice.FlashMode = AVCaptureFlashMode.Auto;
                        m_videoDevice.UnlockForConfiguration();
                    }
                }

                AVCaptureConnection connection = m_stillImageOutput.ConnectionFromMediaType(AVMediaType.Video);
                var imageDataSampleBuffer      = await m_stillImageOutput.CaptureStillImageTaskAsync(connection);   //获得当前帧的压缩图像

                var imageData = AVCaptureStillImageOutput.JpegStillToNSData(imageDataSampleBuffer);                 //得到当前帧压缩图像的图像数据...

                //RequestAuthorization(handler), handler是用户与权限对话框交互后,执行的动作。
                PHPhotoLibrary.RequestAuthorization(status => {
                    if (status == PHAuthorizationStatus.Authorized)
                    {   // 若用户授权了
                        // To preserve the metadata, we create an asset from the JPEG NSData representation.
                        // Note that creating an asset from a UIImage discards the metadata.

                        // In iOS 9, we can use AddResource method on PHAssetCreationRequest class.
                        // In iOS 8, we save the image to a temporary file and use +[PHAssetChangeRequest creationRequestForAssetFromImageAtFileURL:].

                        if (UIDevice.CurrentDevice.CheckSystemVersion(9, 0))
                        {
                            //PHPhotoLibrary.SharedPhotoLibrary 返回的是一个(共享)图片库对象
                            //PerformChanges (changeHandler, completionHandler) changeHandler 以及 completionHandler 是一个lambda
                            PHPhotoLibrary.SharedPhotoLibrary.PerformChanges(() => {
                                var request = PHAssetCreationRequest.CreationRequestForAsset();
                                request.AddResource(PHAssetResourceType.Photo, imageData, null);        //保存当前照片
                            }, (success, err) => {
                                if (!success)
                                {
                                    Console.WriteLine("Error occurred while saving image to photo library: {0}", err);
                                }
                            });
                        }
                        else
                        {   //用户没有授权
                            string outputFileName  = NSProcessInfo.ProcessInfo.GloballyUniqueString;
                            string tmpDir          = Path.GetTempPath();
                            string outputFilePath  = Path.Combine(tmpDir, outputFileName);
                            string outputFilePath2 = Path.ChangeExtension(outputFilePath, "jpg");
                            NSUrl temporaryFileUrl = new NSUrl(outputFilePath2, false);

                            PHPhotoLibrary.SharedPhotoLibrary.PerformChanges(() => {
                                NSError error = null;
                                if (imageData.Save(temporaryFileUrl, NSDataWritingOptions.Atomic, out error))
                                {
                                    PHAssetChangeRequest.FromImage(temporaryFileUrl);
                                }
                                else
                                {
                                    Console.WriteLine("Error occured while writing image data to a temporary file: {0}", error);
                                }
                            }, (success, error) => {
                                if (!success)
                                {
                                    Console.WriteLine("Error occurred while saving image to photo library: {0}", error);
                                }

                                // Delete the temporary file.
                                NSError deleteError;
                                NSFileManager.DefaultManager.Remove(temporaryFileUrl, out deleteError);
                            });
                        }
                    }
                });
            }
        }