Open Sompatbu opened 6 years ago
I am also facing the same issue. This functionality is working fine in iOS. In Android, it is saved to the App Memory (/storage/emulated/0/Android/data/com.companyname.AppName/files/Movies/) but While we try to Pick the same Video, we are unable to find this.
there are news for this problem?
^ nope they didn't give this issue any attention for now. No feedback from them.
I am seeing the same issue on iOS, except that there is an exception:
unable to save to album:System.NullReferenceException: Object reference not set to an instance of an object at Plugin.Media.MediaPickerDelegate+
d__28.MoveNext () [0x00166] in :0
Here is the code to create the options:
var file = await CrossMedia.Current.TakeVideoAsync(new Plugin.Media.Abstractions.StoreVideoOptions {
Name = fileName,
Directory = directoryName,
DesiredLength = new TimeSpan(0, 0, seconds),
CompressionQuality = 50,
Quality = Plugin.Media.Abstractions.VideoQuality.Medium,
SaveToAlbum = true,
DefaultCamera = Plugin.Media.Abstractions.CameraDevice.Rear,
});
Also, here are my plist entries:
<key>NSCameraUsageDescription</key>
<string>This app needs access to the camera to take photos.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>This app needs access to photos.</string>
<key>NSMicrophoneUsageDescription</key>
<string>This app needs access to microphone.</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>This app needs access to the photo gallery.</string>
Hi, any news about this? After recording video is not saved to gallery, that's really important issue to fix... :/
The issue is simple: StoreVideoOptions
is not respected in TakeMediaAsync()
. Only TakePhotoAsync()
respects the options and uses the MediaScanner
intent to save the file into the gallery. See here for details.
Either one would extend this library or you would have to implement it yourself in your app ...
Hi there, Has anyone had any success remedying this? I notice that the file.AlbumPath is different from taking a photo from when recording video.
@jamesmontemagno I notice that in the file src/Android/MediaImplementation.cs - line 202 (TakePhotoAsync) the option SaveToAlbum is checked and the proceeding code (to line 247) presumably saves to the device album.
However looking at TakeVideoAsync (line 308) there is no check on the SaveToAlbum property.
Will it be as simple as adding line 202 to 247 from TakePhotoAsync to TakeVideoAsync???
FYI I've added the code from line 202 to 247 of MediaImplementation as a dependency service and it seems to work for saving the Video to Gallery. Only tested on a Samsung S8 though.
Please send a PR
I am having the issue of Taken Videos not saving to the device on both Android and IOS.
The change that @ledragon101 made does seem to solve the problem for Android.
Wondering if anyone is still not able to save their Taken Videos on IOS also?
@Sinkanakagug Using the latest 5.0.0-beta, the SaveToAlbum=true
property does seem to store recorded videos to the gallery on iOS (tested on an iPhone XS running iOS 13.3.1). However on a Sony Xperia with Android 8.0.0, this option does not have any effect.
Just pulled the latest code, but on Android (tested on Samsung S8+ phone and tab S4) still doesn't work, can't save the video from TakeVideoAsync to gallery, it only works in memory, and the videos don't get saved in either Album or internal storage. I could not rebuild the package from source using VS 2019 for Mac like @ledragon101 did, get the UAP 10.0...missing error. Any pointers will be much appreciated
@xiufengpeng I didn;t rebuild the package. I just took the code from line 202 to 247 of MediaImplementation and created a separate DependencyService then passed the result of TakeVideoAsync to it.
Rebuilding packages a bit beyond me
@markelliottopoc Thanks for the info. I tried to use your method to save, but got the "part of the path" not found error on Android (Samsung S4 tab, Android 9), can you share your code ? @jamesmontemagno, any plan to fix this? Thanks a lot.
Interface
namespace xxx.xxx.xxx.xxx
{
public interface IGalleryService
{
void SaveToDevice(MediaFile media, StoreVideoOptions options);
}
}
Dependency Service:
[assembly: Dependency(typeof(GalleryService))]
namespace xxx.xxx.xxx.xxx
{
public class GalleryService : IGalleryService
{
//private Activity _activity;
/// <summary>
///
/// </summary>
public GalleryService()
{
//_activity = CrossCurrentActivity.Current.Activity;
}
public void SaveToDevice(MediaFile media, StoreVideoOptions options)
{
if (options.SaveToAlbum)
{
try
{
//var context = _activity.ApplicationContext;
var context = Xamarin.Essentials.Platform.AppContext;
// Current Activity or null if not initialized or not started.
//var activity = Xamarin.Essentials.Platform.CurrentActivity;
var fileName = Path.GetFileName(media.Path);
var publicUri = MediaPickerActivity.GetOutputMediaFile(context, options.Directory ?? "temp", fileName, true, true);
using (Stream input = File.OpenRead(media.Path))
using (Stream output = File.Create(publicUri.Path))
input.CopyTo(output);
media.AlbumPath = publicUri.Path;
var f = new Java.IO.File(publicUri.Path);
//MediaStore.Images.Media.InsertImage(context.ContentResolver, f.AbsolutePath, f.Name, null);
try
{
Android.Media.MediaScannerConnection.ScanFile(context, new[] { f.AbsolutePath }, null, context as MediaPickerActivity);
ContentValues values = new ContentValues();
values.Put(MediaStore.Images.Media.InterfaceConsts.Title, Path.GetFileNameWithoutExtension(f.AbsolutePath));
values.Put(MediaStore.Images.Media.InterfaceConsts.Description, string.Empty);
values.Put(MediaStore.Images.Media.InterfaceConsts.DateTaken, Java.Lang.JavaSystem.CurrentTimeMillis());
values.Put(MediaStore.Images.ImageColumns.BucketId, f.ToString().ToLowerInvariant().GetHashCode());
values.Put(MediaStore.Images.ImageColumns.BucketDisplayName, f.Name.ToLowerInvariant());
values.Put("_data", f.AbsolutePath);
var cr = context.ContentResolver;
cr.Insert(MediaStore.Images.Media.ExternalContentUri, values);
}
catch (Exception ex1)
{
Console.WriteLine("Unable to save to scan file: " + ex1);
}
var contentUri = Android.Net.Uri.FromFile(f);
var mediaScanIntent = new Intent(Intent.ActionMediaScannerScanFile, contentUri);
context.SendBroadcast(mediaScanIntent);
}
catch (Exception ex2)
{
Console.WriteLine("Unable to save to gallery: " + ex2);
}
}
}
}
}
Above in use in Viewmodel:
await CrossMedia.Current.Initialize().ConfigureAwait(false);
var isCameraAvailable = CrossMedia.Current.IsCameraAvailable;
var isTakePhotoSupported = CrossMedia.Current.IsTakePhotoSupported;
if (!isCameraAvailable || !isTakePhotoSupported) return;
var videoOptions = new StoreVideoOptions
{
DefaultCamera = CameraDevice.Rear,
SaveToAlbum = true,
CompressionQuality = 100,
Quality = (VideoQuality)Enum.Parse(typeof(VideoQuality), Settings.VideoSetting, true)
};
//TODO: Try Catch
using (var file = await CrossMedia.Current.TakeVideoAsync(videoOptions).ConfigureAwait(false))
{
if (file == null) return;
//Check Video Size
var contentLength = new FileInfo(file.Path).Length;
var contentLengthString = contentLength.ToString();
if (contentLength >= (1 << 30)) contentLengthString = $"{contentLength >> 30}Gb";
else if (contentLength >= (1 << 20)) contentLengthString = $"{contentLength >> 20}Mb";
else if (contentLength >= (1 << 10)) contentLengthString = $"{contentLength >> 10}Kb";
var confirm = await _userDialog.ConfirmAsync($"Upload this {contentLengthString} video? Duration will depend on your connection speed. You can amend video quality in Settings to reduce file size", "Confirm", "OK").ConfigureAwait(false);
//Save To Gallery code for Android Video bug
if (videoOptions.SaveToAlbum && Device.RuntimePlatform == Device.Android)
{
var galleryService = DependencyService.Get<IGalleryService>();
galleryService.SaveToDevice(file, videoOptions);
}
if (confirm) await AddImageOrVideoToRfi(rfiDto, file).ConfigureAwait(false);
}
I use Prism and it's not advisable to use XF Dependency Service:
https://prismlibrary.com/docs/xamarin-forms/Dependency-Service.html#use-the-service
I'll get round to fixing but works for now.
Thanks @ledragon101 I was able to re-build the package from James Git code by adding the codes to Android platform, but then ran into a runtime error "This functionality is not implemented in the portable version of this assembly. You should reference the NuGet package from your main application project in order to reference the platform-specific implementation.", tried to set the Android and iOS target versions but no luck, maybe James can shed some light on this issue. Regardless, your code works well on Android (Samsung tab s4, android 9).
Hi, Could someone please send me a link to a simple sample example? I don't understand these line insertions. Android app should be able to just make a video and put it in my video folder, which I can easily achieve. Thanks in advance if anyone bothers to help me.
Feri
I've tried recording video on Xamarin Forms Application and found the problem when I try to picking up the video I've recorded. The video that is just recorded doesn't show in video picker. But if I switch to taking picture and pick it the picture up there's no problem
Bug Information
Version Number of Plugin: 3.1.3 Device Tested On: - Simulator Tested On: Android Emulator run on Oreo Version of VS: Visual Studio for Mac(Community) 7.3.3 Version of Xamarin: 2.5.0.280555 Versions of other things you are using: -
Steps to reproduce the Behavior
Expected Behavior
Application will show the video that's recorded
Actual Behavior
Nothing show on the pick video page
Code snippet
`async void OnCaremaIconClicked(object sender, EventArgs e) { await CrossMedia.Current.Initialize();
Screenshots
This screenshots show the AlbumPath of the file. First picture is the AlbumPath of video. Second is the AlbumPath of picture. Both have SaveToAlbum = true; in the StoreVideoOptions/StoreCameraMediaOptions https://imgur.com/a/aAN4U