¿Cómo conseguir vídeos con PHVideo de iCloud en Xamarin iOS?

He implementado el picker multimedia (para imágenes y videos) con DependencyService en Xamarin. Aplicación de formularios. Tengo un problema en videos de iCloud. Cuando elijo el video que está en icloud, no puedo conseguirlo.

Mi aplicación es:

async void FinishedPickingAssets(object sender, MultiAssetEventArgs args)
         {
             IList results = new List();
             TaskCompletionSource> tcs = new TaskCompletionSource>();
    
             try 
             { 
                 var options = new PHImageRequestOptions()
                 {
                     NetworkAccessAllowed = true
                 };
    
                 options.Synchronous = false;
                 options.ResizeMode = PHImageRequestOptionsResizeMode.Fast;
                 options.DeliveryMode = PHImageRequestOptionsDeliveryMode.HighQualityFormat;
                 bool completed = false;
                 for (var i = 0; i < args.Assets.Length; i++)
                 {
                     var asset = args.Assets[i];
    
                     string fileName = string.Empty;
                     if (UIDevice.CurrentDevice.CheckSystemVersion(9, 0))
                     {
                         fileName = PHAssetResource.GetAssetResources(asset).FirstOrDefault().OriginalFilename;
                         fileName = Path.GetFileNameWithoutExtension(fileName) + "(" + i.ToString() + ")" + Path.GetExtension(fileName);
                     }
    
                     switch (asset.MediaType)
                     {
                         case PHAssetMediaType.Video:
                         {
                                 var vOptions = new PHVideoRequestOptions();
                                 vOptions.NetworkAccessAllowed = true;
                                 vOptions.Version = PHVideoRequestOptionsVersion.Original;
                                 vOptions.DeliveryMode = PHVideoRequestOptionsDeliveryMode.Automatic;
                                 string videoUrl = "";
    
                                 PHImageManager.DefaultManager.RequestAvAsset(asset, vOptions, (avAsset, audioMix, vInfo) => 
                                 {
                                     DispatchQueue.MainQueue.DispatchAsync(() => {
    
                                         var error = vInfo.ObjectForKey(PHImageKeys.Error);
                                            
                                         if (avAsset != null)
                                         {
                                             videoUrl = ((AVFoundation.AVUrlAsset)avAsset).Url.Path;
                                         }
                                         var meFile = new MediaFile()
                                         {
                                             FileName = fileName,
                                             FilePath = videoUrl
                                         };
    
                                         using (Stream source = File.OpenRead(videoUrl))
                                         {
                                             meFile.FileSize = source.Length;
                                         }
                                         results.Add(meFile);
                                         OnMediaPicked?.Invoke(this, meFile);
    
                                         if (args.Assets.Length == results.Count && !completed)
                                         {
                                             completed = true;
                                             tcs.TrySetResult(results);
                                         }
                                     });
                                 });
                         }
                         break;
                     default:
                         PHImageManager.DefaultManager.RequestImageData(asset, options, (data, dataUti, orientation, info) =>
                         {
    
                             string path = FileHelper.GetOutputPath(MediaFileType.Image, TemporalDirectoryName, fileName);
    
                             if (!File.Exists(path))
                             {
                                 Debug.WriteLine(dataUti);
                                 var imageData = data;
                                 imageData?.Save(path, true);
                             }
    
                             var meFile = new MediaFile()
                             {
                                 FileName = fileName,
                                 FilePath = path,
                                 FileSize = File.ReadAllBytes(path).Length
                             };
    
                             results.Add(meFile);
                             OnMediaPicked?.Invoke(this, meFile);
                             if (args.Assets.Length == results.Count && !completed)
                             {
                                 completed = true;
                                 tcs.TrySetResult(results);
                             }
    
                         });
                         break;
                     }
                 }
             }
             catch
             {
                 tcs.TrySetResult(results);
    
                 string automationId = "UnexpectedSituationMessage";
                 GeneralOperations.OpenToastMessage("Unexpected Situation", automationId);
             }
    
             mediaPickTcs?.TrySetResult(await tcs.Task);
         }

Cuando intento seleccionar el objeto iCloud, obtengo el siguiente error: enter image description here

¿Cómo puedo tomar vídeos con selección múltiple de icloud?

Gracias por adelantado.

Pregunta hecha hace 3 años, 5 meses, 0 días - Por markupmaestro


3 Respuestas:

  • Primero asegúrate de que hayas encendido iCloud Photos .

    
     1. Go to Settings > [your name] > iCloud.
     2. Tap Photos.
     3. If you need to, tap to turn on iCloud Photos.
    
    

    enter image description here

    A continuación, compruebe si el vídeo y la pantalla de fotos en Photo App en su dispositivo .

    Para la selección múltiple y varias personalizaciones usted podría instalar el plugin GMImagePicker.Xamarin de nuget .

    Respondida el Dec 17, 2020 a las 07:40 - por devdynamox

    Votos positivos: 0 | Votos negativos: 0

  • El error que estás experimentando se debe a que estás intentando acceder a un archivo de video de iCloud directamente desde su URL local, pero eso no es posible debido a que los archivos de iCloud no están descargados localmente en el dispositivo. Para poder obtener los videos de iCloud, necesitas descargarlos primero.

    Aquí te dejo una sugerencia de cómo podrías modificar tu código para descargar los videos de iCloud antes de intentar acceder a ellos:

    • Asegúrate de tener una conexión a internet activa.
    • Agrega una función async para descargar los videos de iCloud antes de intentar acceder a ellos:
    csharp
    private async Task DownloadVideoFromICloudAsync(PHAsset asset)
    {
        var vOptions = new PHVideoRequestOptions();
        vOptions.NetworkAccessAllowed = true;
        vOptions.Version = PHVideoRequestOptionsVersion.Original;
        vOptions.DeliveryMode = PHVideoRequestOptionsDeliveryMode.Automatic;
    
        var tcs = new TaskCompletionSource();
    
        PHImageManager.DefaultManager.RequestAvAsset(asset, vOptions, (avAsset, audioMix, vInfo) =>
        {
            DispatchQueue.MainQueue.DispatchAsync(() =>
            {
                if (avAsset != null)
                {
                    var tempFileName = "tempVideo.mp4"; // Nombre temporal para el video descargado
                    string videoUrl = Path.Combine(Path.GetTempPath(), tempFileName);
    
                    var exportSession = new AVFoundation.AVAssetExportSession(avAsset, AVFoundation.AVAssetExportSessionPreset.MediumQuality);
                    exportSession.OutputUrl = NSUrl.FromFilename(videoUrl);
                    exportSession.OutputFileType = AVFileType.Mpeg4;
                    exportSession.ExportAsynchronously(() =>
                    {
                        if (exportSession.Error != null)
                        {
                            Console.WriteLine(exportSession.Error.LocalizedDescription);
                            tcs.SetResult(null);
                        }
                        else
                        {
                            tcs.SetResult(videoUrl);
                        }
                    });
                }
                else
                {
                    tcs.SetResult(null);
                }
            });
        });
    
        return await tcs.Task;
    }
    
    • Luego, en tu método `FinishedPickingAssets`, usa esta función para descargar los videos de iCloud antes de acceder a ellos:
    csharp
    for (var i = 0; i < args.Assets.Length; i++)
    {
        var asset = args.Assets[i];
    
        switch (asset.MediaType)
        {
            case PHAssetMediaType.Video:
                {
                    var videoUrl = await DownloadVideoFromICloudAsync(asset);
    
                    if (videoUrl != null)
                    {
                        var meFile = new MediaFile()
                        {
                            FileName = fileName,
                            FilePath = videoUrl
                        };
    
                        using (Stream source = File.OpenRead(videoUrl))
                        {
                            meFile.FileSize = source.Length;
                        }
    
                        results.Add(meFile);
                        OnMediaPicked?.Invoke(this, meFile);
                    }
                }
                break;
            // Resto de tu código para los casos de imágenes u otros tipos de archivos
        }
    }
    

    Con estos cambios, los videos de iCloud serán descargados localmente antes de acceder a ellos, lo que debería ayudarte a evitar el error que estás experimentando. ¡Espero que esta solución te sea de ayuda!

    Respondida el Dec 18, 2020 a las 07:39 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • Para recuperar videos de iCloud con PHVideo en Xamarin iOS, debes seguir estos pasos:

    • Asegúrate de que tu aplicación tiene el permiso `NSPhotoLibraryAddUsageDescription` en `Info.plist` para acceder a la biblioteca de fotos.
    • Utiliza `PHVideoRequestOptions` para especificar las opciones de solicitud de video:
    csharp
    var vOptions = new PHVideoRequestOptions();
    vOptions.NetworkAccessAllowed = true;
    vOptions.Version = PHVideoRequestOptionsVersion.Original;
    vOptions.DeliveryMode = PHVideoRequestOptionsDeliveryMode.Automatic;
    
    • Solicita un objeto `AVAsset` para el video usando `RequestAvAsset`:
    csharp
    PHImageManager.DefaultManager.RequestAvAsset(asset, vOptions, (avAsset, audioMix, vInfo) =>
    {
        DispatchQueue.MainQueue.DispatchAsync(() =>
        {
            var error = vInfo.ObjectForKey(PHImageKeys.Error);
    
            if (avAsset != null)
            {
                videoUrl = ((AVFoundation.AVUrlAsset)avAsset).Url.Path;
            }
            // ...
        });
    });
    
    • Utiliza `AVUrlAsset` para obtener la ruta del archivo de video:
    csharp
    if (avAsset != null)
    {
        videoUrl = ((AVFoundation.AVUrlAsset)avAsset).Url.Path;
    }
    
    • Crea un objeto `MediaFile` con la ruta del archivo de video:
    csharp
    var meFile = new MediaFile()
    {
        FileName = fileName,
        FilePath = videoUrl
    };
    

    Aquí tienes una versión modificada de tu código que implementa estos pasos para recuperar videos de iCloud:

    csharp
    async void FinishedPickingAssets(object sender, MultiAssetEventArgs args)
    {
        IList results = new List();
        TaskCompletionSource> tcs = new TaskCompletionSource>();
    
        try 
        { 
            var options = new PHImageRequestOptions()
            {
                NetworkAccessAllowed = true
            };
    
            options.Synchronous = false;
            options.ResizeMode = PHImageRequestOptionsResizeMode.Fast;
            options.DeliveryMode = PHImageRequestOptionsDeliveryMode.HighQualityFormat;
            bool completed = false;
            for (var i = 0; i < args.Assets.Length; i++)
            {
                var asset = args.Assets[i];
    
                string fileName = string.Empty;
                if (UIDevice.CurrentDevice.CheckSystemVersion(9, 0))
                {
                    fileName = PHAssetResource.GetAssetResources(asset).FirstOrDefault().OriginalFilename;
                    fileName = Path.GetFileNameWithoutExtension(fileName) + "(" + i.ToString() + ")" + Path.GetExtension(fileName);
                }
    
                switch (asset.MediaType)
                {
                    case PHAssetMediaType.Video:
                    {
                        var vOptions = new PHVideoRequestOptions();
                        vOptions.NetworkAccessAllowed = true;
                        vOptions.Version = PHVideoRequestOptionsVersion.Original;
                        vOptions.DeliveryMode = PHVideoRequestOptionsDeliveryMode.Automatic;
                        string videoUrl = "";
    
                        PHImageManager.DefaultManager.RequestAvAsset(asset, vOptions, (avAsset, audioMix, vInfo) => 
                        {
                            DispatchQueue.MainQueue.DispatchAsync(() => {
    
                                var error = vInfo.ObjectForKey(PHImageKeys.Error);
    
                                if (avAsset != null)
                                {
                                    videoUrl = ((AVFoundation.AVUrlAsset)avAsset).Url.Path;
                                }
                                var meFile = new MediaFile()
                                {
                                    FileName = fileName,
                                    FilePath = videoUrl
                                };
    
                                using (Stream source = File.OpenRead(videoUrl))
                                {
                                    meFile.FileSize = source.Length;
                                }
                                results.Add(meFile);
                                OnMediaPicked?.Invoke(this, meFile);
    
                                if (args.Assets.Length == results.Count && !completed)
                                {
                                    completed = true;
                                    tcs.TrySetResult(results);
                                }
                            });
                        });
                    }
                    break;
                    default:
                        PHImageManager.DefaultManager.RequestImageData(asset, options, (data, dataUti, orientation, info) =>
                        {
    
                            string path = FileHelper.GetOutputPath(MediaFileType.Image, TemporalDirectoryName, fileName);
    
                            if (!File.Exists(path))
                            {
                                Debug.WriteLine(dataUti);
                                var imageData = data;
                                imageData?.Save(path, true);
                            }
    
                            var meFile = new MediaFile()
                            {
                                FileName = fileName,
                                FilePath = path,
                                FileSize = File.ReadAllBytes(path).Length
                            };
    
                            results.Add(meFile);
                            OnMediaPicked?.Invoke(this, meFile);
                            if (args.Assets.Length == results.Count && !completed)
                            {
                                completed = true;
                                tcs.TrySetResult(results);
                            }
    
                        });
                        break;
                }
            }
        }
        catch
        {
            tcs.TrySetResult(results);
    
            string automationId = "UnexpectedSituationMessage";
            GeneralOperations.OpenToastMessage("Unexpected Situation", automationId);
        }
    
        mediaPickTcs?.TrySetResult(await tcs.Task);
    }
    

    Nota: Asegúrate de que tu dispositivo está conectado a Internet cuando intentes recuperar videos de iCloud.

    Respondida el Dec 18, 2020 a las 07:44 - por Gemini

    Votos positivos: 0 | Votos negativos: 0