jamesmontemagno / MediaPlugin

Take & Pick Photos and Video Plugin for Xamarin and Windows
MIT License
711 stars 360 forks source link

Store Recorded Video Into Device #940

Open CodeToKillBug opened 2 years ago

CodeToKillBug commented 2 years ago

Is There Any Way To Store Recorded Video Into Device As We Do Normally In Device Default Camera.....? I want To Do The Same Thing But Using Xamarin Form Mobile App. Is There Any Way By Which you Can Help Me With.

boris-df commented 2 years ago

I'm just testing this library ...

Storing recorded video on Device -> Works on iOS set the StoreVideoOptions like var mediaOptions = new Plugin.Media.Abstractions.StoreVideoOptions { Directory = "this-is-not-used-videos-are-stored-in-main-album-on-ios", Name = "test.mov", SaveToAlbum = true // set this to true to store on device's gallery };

BUT: On Android it doesn't work

Not sure yet why the recorded video is not stored on Android :( (and i'm a bit frustrated as i found this (rather old) library after days of searching, trying out Xamarin.Essentials and other code i found on the internet ... just to find out, that even THIS one doesn't work flawlessly out of the box - so sad)

boris-df commented 2 years ago

well... in MediaImplementation.cs take a look at TakePhotoAsync(...) Here you can see, that after the call to "await TakeMediaAsync(...)", SaveToAlbum is checked and then some code is run to save the actual image

In TakeVideoAsync(...) i cannot see anything like that.

Here is a quick solution to save the recorded video in the public gallery.

`public string SaveVideoToGallery(byte[] imgBytes, string album, string filename, string description) { var activity = CrossCurrentActivity.Current.Activity; if (activity == null) return string.Empty; if (imgBytes == null) return string.Empty; if (imgBytes.Length == 0) return string.Empty;

        var cr = activity.ContentResolver;

        try
        {
            var ext = System.IO.Path.GetExtension(filename);
            filename = System.IO.Path.GetFileNameWithoutExtension(filename);
            filename = filename.Replace("\\", "_").Replace(".", "_").Replace("/", "_");
            filename = filename + ext;

            string sDirectory = "";
            using (Java.IO.File directory = new Java.IO.File(Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryMovies) + Java.IO.File.Separator + album))
            {
                if (!directory.Exists())
                {
                    directory.Mkdirs();
                }
                sDirectory = directory.Path;
            }

            long fileTime = DateTime.Now.ToFileTime();

            var sFilePath = System.IO.Path.Combine(sDirectory, filename);

            ContentValues values = new ContentValues();

            values.Put(MediaStore.Video.Media.InterfaceConsts.Title, filename);
            values.Put(MediaStore.Video.Media.InterfaceConsts.DisplayName, filename);
            values.Put(MediaStore.Video.Media.InterfaceConsts.Description, description);
            values.Put(MediaStore.Video.Media.InterfaceConsts.MimeType, "video/mp4");
            values.Put(MediaStore.Video.Media.InterfaceConsts.Data, sFilePath);

            values.Put(MediaStore.Video.Media.InterfaceConsts.DateAdded, fileTime);
            values.Put(MediaStore.Video.Media.InterfaceConsts.DateModified, fileTime);
            values.Put(MediaStore.Video.Media.InterfaceConsts.DateTaken, fileTime);

            using (var url = cr.Insert(MediaStore.Video.Media.ExternalContentUri, values))
            {
                using (System.IO.Stream videoOut = cr.OpenOutputStream(url))
                {
                    videoOut.Write(imgBytes, 0, imgBytes.Length);
                    videoOut.Close();

                }
                return url.ToString();
            }

        }
        catch (Exception ex)
        {
            ex.Trace();
        }

        return "";

    }`

to call it, you can either put it into the MediaImplementation itself (then you don't need the Bytes[] array as parameter, use whatever is suitable - look at the TakePhotoAsync ... Or you build your own library with DependencyService or something like that... anyway ... with that code i was able to save the video in the gallery (inside the Movie-Album an own sub-album is created if needed)