I just developed sample UWP app to capture images from web cam. this is working smoothly
this is the code I have used
public class CameraCaptureService : ICaptureService
{
public async Task<StorageFile> CapturePhotoAsync()
{
var dialog = new CameraCaptureUI();
dialog.PhotoSettings.MaxResolution = CameraCaptureUIMaxPhotoResolution.HighestAvailable;
dialog.PhotoSettings.Format = CameraCaptureUIPhotoFormat.JpegXR;
dialog.PhotoSettings.AllowCropping = true;
var file = await dialog.CaptureFileAsync(CameraCaptureUIMode.Photo);
...
return (file == null) ? null : file;
}
}
but once after I click Image Capture button
this is awaiting until I confirm If I want to proceed this picture or discard the process and restart (with right sign and incorrect sign)
I'm trying to skip that stage and directly save this to local storage
Is this possible to do, using CameraCaptureUI class PhotoSettings ?
NB : dialog.CaptureFileAsync(CameraCaptureUIMode.Photo); is async method
Related
In Xamarin.Forms prerelease they have released a media picker: https://learn.microsoft.com/en-us/xamarin/essentials/media-picker?tabs=android
This is obviously a great addition and the fact that you don't have to use any 3rd party-library is great!
I'm creating an event management app - in the app the user can select an image for the event and be able to see it.
Here is my code:
public async void OnSelectPhotoCommand()
{
var photo = await MediaPicker.PickPhotoAsync();
await LoadPhotoAsync(photo);
}
async Task LoadPhotoAsync(FileResult photo)
{
var newFile = Path.Combine(FileSystem.CacheDirectory, photo.FileName);
using (var stream = await photo.OpenReadAsync())
using (var newStream = File.OpenWrite(newFile)) { await stream.CopyToAsync(newStream); }
ImagePath = newFile;
}
The problem is the image is not showing or appearing whatsoever - I've tried to modify my code and debug it but I am unable to locate the source of the problem.
I want the user to be actually able to see the image - but I am unsure on how to do that using the MediaPicker without putting it in the Android Resources folder?
Thank you,
tommy
From the xamarin essentials documentation be sure to be running it from the UI Thread.
InvokeOnMainThread ( () => {
OnSelectPhotoCommand();
});
I'm trying to capture a video of my application using UWP APIs, specifically the Windows.Media.AppRecording namespace. When I try to execute the code I get a CanRecord flag as false, and the reason given by the Details property is that "something" is disabled by the user.
How can I enable the screen capture? Do I need a specific configuration file, or manifest?
My application is as simple as it get: Just a WPF in .NET 4.7.2, consisting in a button to start recording and a button to stop recording.
Here is the method:
public async Task StartRecordingAsync(string fileName)
{
AppRecordingManager manager = AppRecordingManager.GetDefault();
var status = manager.GetStatus();
if (status.CanRecord || status.CanRecordTimeSpan)
{
var myVideo = await StorageLibrary.GetLibraryAsync(KnownLibraryId.Videos);
StorageFolder projectFolder = await myVideo.SaveFolder.CreateFolderAsync("DataFolder", CreationCollisionOption.OpenIfExists);
var audio = await projectFolder.CreateFileAsync(fileName, CreationCollisionOption.GenerateUniqueName);
var result = await manager.StartRecordingToFileAsync(audio).AsTask<AppRecordingResult>(CTS.Token);
if (result.Succeeded)
{
IsRecording = true;
}
else
{
IsRecording = false;
}
}
}
And here are the Details given by the status variable:
status.Details
The IsDisbaledByUser property of the AppRecordingStatusDetails is false when the user does not allow apps to record.
True if app recording has been disabled by the user; otherwise, false.
To allow apps to record, you need to enable Game Bar from Windows Settings:
Settings -> Gaming -> Record game clips, screenshots, and broadcast using Game bar
I have a UWP application which perform to capture and process images from a camera. This project leverage Microsoft Cognitive Services Face Recognition API and I'm exploring the application's existing functionality for awhile now. My goal is that when the image of a person is identified by the camera (through Face Recognition API service), I want to show the associated image of that person.
With that, the images are captured and stored in a local directory of my machine. I want to retrieve the image file and render it on the screen once the person is identified.
The code below shows the async Task method ProcessCameraCapture
private async Task ProcessCameraCapture(ImageAnalyzer e)
{
if (e == null)
{
this.UpdateUIForNoFacesDetected();
this.isProcessingPhoto = false;
return;
}
DateTime start = DateTime.Now;
await e.DetectFacesAsync();
if (e.DetectedFaces.Any())
{
string names;
await e.IdentifyFacesAsync();
this.greetingTextBlock.Text = this.GetGreettingFromFaces(e, out names);
if (e.IdentifiedPersons.Any())
{
this.greetingTextBlock.Foreground = new SolidColorBrush(Windows.UI.Colors.GreenYellow);
this.greetingSymbol.Foreground = new SolidColorBrush(Windows.UI.Colors.GreenYellow);
this.greetingSymbol.Symbol = Symbol.Comment;
GetSavedFilePhoto(names);
}
else
{
this.greetingTextBlock.Foreground = new SolidColorBrush(Windows.UI.Colors.Yellow);
this.greetingSymbol.Foreground = new SolidColorBrush(Windows.UI.Colors.Yellow);
this.greetingSymbol.Symbol = Symbol.View;
}
}
else
{
this.UpdateUIForNoFacesDetected();
}
TimeSpan latency = DateTime.Now - start;
this.faceLantencyDebugText.Text = string.Format("Face API latency: {0}ms", (int)latency.TotalMilliseconds);
this.isProcessingPhoto = false;
}
In GetSavedFilePhoto, I passed the string names argument once the person is identified.
Code below for the GetSavedFilePhoto method
private void GetSavedFilePhoto(string personName)
{
if (string.IsNullOrWhiteSpace(personName)) return;
var directoryPath = #"D:\PersonImages";
var directories = Directory.GetDirectories(directoryPath);
var filePaths = Directory.GetFiles(directoryPath, "*.jpg", SearchOption.AllDirectories);
}
However, in GetSavedFilePhoto method the variable directories returned an empty string of array when using directoryPath string variable. Directory "D:\PersonImages" is a valid and existing folder in my machine and, it contains subfolders with images inside. I also tried Directory.GetFiles to retrieve the jpg images but still returned an empty string.
I think it should work because I have used Directory class several times but not inside an asyncTask method. Does using async caused the files not returned when using I/O operation?
Sorry for this stupid question, but I really don't understand.
Any help is greatly appreciated.
Using Directory.GetFiles or Directory.GetDirectories method can get the folder/file in the local folder of the Application by the following code. But it could not open D:\.
var directories = Directory.GetDirectories(ApplicationData.Current.LocalFolder.Path);
In UWP app you can only access two locations at default (local folder and install folder), others need capabilities setting or file open picker.Details please reference file access permission.
If you need access to all files in D:\, the user must manually pick the D:\ drive using the FolderPicker, then you have permissions to access to files in this drive.
var picker = new Windows.Storage.Pickers.FileOpenPicker();
picker.ViewMode = Windows.Storage.Pickers.PickerViewMode.Thumbnail;
picker.SuggestedStartLocation =
Windows.Storage.Pickers.PickerLocationId.ComputerFolder;
picker.FileTypeFilter.Add(".jpg");
picker.FileTypeFilter.Add(".jpeg");
picker.FileTypeFilter.Add(".png");
Windows.Storage.StorageFile file = await picker.PickSingleFileAsync();
if (file != null)
{
// Application now has read/write access to the picked file
}
else
{
//do some stuff
}
I am developing a voice recorder app for Windows Phone 8.1 that stores the recordings on the local storage and a cloud storage service.
Everything's almost done except the fact that being able to pause an ongoing recording is a strong requirement for this app and I have to get it done.
Now, since PauseRecordAsync() and ResumeRecordAsync() are not available for Windows Phone 8.1 in the MediaCapture class but they will be available in Windows 10, I had to make a workaround: Every time the pause button is pressed, an audio chunk is saved in the temp folder and that file is stored in an array. When the stop button is pressed, the last chunk is stored in the array and the following Concatenation function is called and a final audio temp file is created:
public async Task<IStorageFile> ConcatenateAudio([ReadOnlyArray]IStorageFile[] audioFiles, IStorageFolder outputFolder, string outputfileName)
{
IStorageFile _OutputFile = await outputFolder.CreateFileAsync(outputfileName, CreationCollisionOption.ReplaceExisting);
MediaComposition _MediaComposition = new MediaComposition();
MediaEncodingProfile _MediaEncodingProfile = MediaEncodingProfile.CreateM4a(AudioEncodingQuality.High);
foreach (IStorageFile _AudioFile in audioFiles)
{
if(_AudioFile != null)
{
BackgroundAudioTrack _BackgroundAudioTrack = await BackgroundAudioTrack.CreateFromFileAsync(_AudioFile);
MediaClip _MediaClip = MediaClip.CreateFromColor(Windows.UI.Colors.Black, _BackgroundAudioTrack.TrimmedDuration); // A dummy black video is created witn the size of the current audio chunk.
// Without this, the duration of the MediaComposition object is always 0.
// It's a messy workaround but it gets the job done.
// Windows 10 will dirrectly support PauseRecordAsync() and ResumeRecordAsync() for MediaCapture tho'. Yay! :D
_MediaClip.Volume = 0;
_BackgroundAudioTrack.Volume = 1;
_MediaComposition.Clips.Add(_MediaClip);
_MediaComposition.BackgroundAudioTracks.Add(_BackgroundAudioTrack);
}
}
TranscodeFailureReason _TranscodeFailureReason = await _MediaComposition.RenderToFileAsync(_OutputFile, MediaTrimmingPreference.Fast, _MediaEncodingProfile);
if (_TranscodeFailureReason != TranscodeFailureReason.None)
{
throw new Exception("Audio Concatenation Failed: " + _TranscodeFailureReason.ToString());
}
return _OutputFile;
}
The problem is that when I play the file, all the audio chunks are played from the beginning of the final audio file at the same time instead of playing the second one right after the first one ended and so on. They are all playing one over the other. The length of the file on the other hand is correct and after all audio files finished playing, it's total silence.
I figured it out. I had to manually set the delay for BackgroundAudioTrack.
Here is the working code:
public async Task<IStorageFile> ConcatenateAudio([ReadOnlyArray]IStorageFile[] audioFiles, IStorageFolder outputFolder, string outputfileName)
{
IStorageFile _OutputFile = await outputFolder.CreateFileAsync(outputfileName, CreationCollisionOption.ReplaceExisting);
MediaComposition _MediaComposition = new MediaComposition();
MediaEncodingProfile _MediaEncodingProfile = MediaEncodingProfile.CreateM4a(AudioEncodingQuality.High);
TimeSpan totalDelay = TimeSpan.Zero;
foreach (IStorageFile _AudioFile in audioFiles)
{
if (_AudioFile != null)
{
BackgroundAudioTrack _BackgroundAudioTrack = await BackgroundAudioTrack.CreateFromFileAsync(_AudioFile);
MediaClip _MediaClip = MediaClip.CreateFromColor(Windows.UI.Colors.Black, _BackgroundAudioTrack.TrimmedDuration); // A dummy black video is created witn the size of the current audio chunk.
// Without this, the duration of the MediaComposition object is always 0.
// It's a messy workaround but it gets the job done.
// Windows 10 will dirrectly support PauseRecordAsync() and ResumeRecordAsync() for MediaCapture tho'. Yay! :D
_MediaClip.Volume = 0;
_BackgroundAudioTrack.Volume = 1;
_MediaComposition.Clips.Add(_MediaClip);
_MediaComposition.BackgroundAudioTracks.Add(_BackgroundAudioTrack);
_BackgroundAudioTrack.Delay = totalDelay;
totalDelay += _BackgroundAudioTrack.TrimmedDuration;
}
}
TranscodeFailureReason _TranscodeFailureReason = await _MediaComposition.RenderToFileAsync(_OutputFile, MediaTrimmingPreference.Fast, _MediaEncodingProfile);
if (_TranscodeFailureReason != TranscodeFailureReason.None)
{
throw new Exception("Audio Concatenation Failed: " + _TranscodeFailureReason.ToString());
}
return _OutputFile;
}
I am making an application that can potentially be used on multiple computers by the same user. I currently have implemented backup and restore functionality to keep the SQLite database synchronized. However, when I install a new copy of the application, I would like to prompt the user to select a backup file (if applicable).
Initially, I thought that I would just put the logic in MainPageViewModel.xaml in the OnNavigatedTo method. The problem with that is that it would run through that logic every time navigating back to MainView. So, I thought that it would make sense to put it in OnApplicationLaunchAsync to only run once when the application is launched.
Here is my code currently:
private async Task<StorageFile> SelectFileAsync()
{
StorageFile pickedFile = null;
var settings = Container.Resolve<ISettings>();
var picker = new FileOpenPicker();
picker.FileTypeFilter.Add(".sqlite");
picker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary;
var file = await picker.PickSingleFileAsync();
if (file != null)
{
var pickedFileToken = StorageApplicationPermissions.FutureAccessList.Add(file);
settings.BackupFileToken = pickedFileToken;
pickedFile = file;
}
return pickedFile;
}
protected async override Task OnLaunchApplicationAsync(LaunchActivatedEventArgs args)
{
var navigationService = Container.Resolve<INavigationService>();
var dialogService = Container.Resolve<IDialogService>();
var settings = Container.Resolve<ISettings>();
if (!string.IsNullOrEmpty(settings.BackupFileToken))
{
var backupFile =
await StorageApplicationPermissions.FutureAccessList.GetFileAsync(settings.BackupFileToken);
var properties = await backupFile.GetBasicPropertiesAsync();
dialogService.Show(string.Format("Backup file found: {0}\r\n" +
"Modified date: {1}", backupFile.Path, properties.DateModified), "");
navigationService.Navigate(Experiences.Main);
}
else
{
navigationService.Navigate(Experiences.Blank);
//dialogService.Show("No backup file specified. Please choose a backup file location.", "");
// TODO: load blank page, then select backup file location, then navigate to main page
await SelectFileAsync();
}
// do not need to return Task.FromResult when OnLaunchApplicationAsync() is async
//return Task.FromResult<object>(null);
}
As you can see, if the BackupFileToken exists, it will check the properties of the file and display a dialog with the file path and last modified date. My problem lies in the situation where it is a new installation/the backup token doesn't exist.
If I try to display a dialog before the FileOpenPicker then the application crashes. I thought perhaps adding a blank view to navigate to, then display the dialog and FileOpenPicker. It just seems like there should be a simpler way to accomplish this (without the need for extra views).
Can someone recommend a way to prompt the user to select a file when the application launches, but let them know the purpose of the FileOpenPicker?
I am aware that my await SelectFileAsync() is losing its return value, this is a temporary situation for testing purposes. I will be sure to assign the return value to the relevant variable once I have found a solution.
Maybe you can use the override
protected override void OnWindowCreated(WindowCreatedEventArgs args) in App.xaml.cs
which is also called once for the creation of the main window.