How can I auto save a captured image in a UWP app? - image

I have this code:
CameraCaptureUI captureUI = new CameraCaptureUI();
captureUI.PhotoSettings.AllowCropping = false;
StorageFile photo = await captureUI.CaptureFileAsync(CameraCaptureUIMode.Photo);
How can I implement to auto save image option when click on the capture button?

How can I implement to auto save image option when click on the capture button?
The StorageFile containing the captured photo is given a dynamically generated name and saved in our app's local folder if we do not cancel the capture, so if we click on the capture button without clicking the confirm button, the photo will be saved automatically in our app's TempState folder.
For more info, refer Capture photos and video with Windows built-in camera UI.
To better organize your captured photos, you may want to move the file to a different folder. Please refer to the following sample which shows how to copy the latest capture photo from the TempState folder to the LocalFolder.
For example:
CameraCaptureUI captureUI = new CameraCaptureUI();
captureUI.PhotoSettings.AllowCropping = false;
StorageFile photo = await captureUI.CaptureFileAsync(CameraCaptureUIMode.Photo);
Windows.Storage.StorageFolder localFolder = Windows.Storage.ApplicationData.Current.TemporaryFolder;
var allFiles =await localFolder.GetFilesAsync();
foreach (StorageFile item in allFiles.OrderByDescending(a => a.DateCreated))
{
StorageFolder destinationFolder = await ApplicationData.Current.LocalFolder.CreateFolderAsync("ProfilePhotoFolder", CreationCollisionOption.OpenIfExists);
await item.CopyAsync(destinationFolder, DateTimeOffset.Now.ToString("yyyyMMddHHmmssfff") + ".jpg", NameCollisionOption.ReplaceExisting);
await item.DeleteAsync();
return;
}

Related

Adding a MediaPicker image to ListView causes System.ObjectDisposedException

I have a form to fill in with data including an image which then goes into a listview. When I click on a button to get an image it works and it goes into the form, however when I click on another button to add it to the listview, the error [System.ObjectDisposedException: 'Cannot access a disposed object.
Object name: 'Stream has been closed'] appears.
Thanks for your help
When I press the add image button :
var ActionPhoto = await DisplayActionSheet("Ajouter une pièce-jointe depuis:", "Annuler", null, "Galerie", "Caméra");
switch (ActionPhoto)
{
case "Galerie":
var Galerie = await MediaPicker.PickPhotoAsync(new MediaPickerOptions { Title = "Choisir une image" });
if (Galerie != null)
{
var voirImageGalerie = await Galerie.OpenReadAsync();
Image_Photos.Source = ImageSource.FromStream(() => voirImageGalerie);
}
break;
case "Caméra":
var camera = await MediaPicker.CapturePhotoAsync();
if (camera != null)
{
var voirImageCamera = await camera.OpenReadAsync();
Image_Photos.Source = ImageSource.FromStream(() => voirImageCamera);
}
break;
}
When I press the add button of the listView:
App.listePosteNoteFrais.Add(new Data{PostePJ = Image_Photos.Source});
In my Data Class:
public ImageSource PostePJ { get; set; }
What I'm adding to my listview:
<Image x:Name="Image_PostePJ" Source="{Binding PostePJ}" HeightRequest="150" WidthRequest="150" Grid.Row="0" Grid.Column="12"/>
Given code:
ImageSource.FromStream(() => voirImageCamera)
The parameter to FromStream:
() => voirImageCamera
is executed every time the image is needed.
The exception message:
System.ObjectDisposedException: 'Cannot access a disposed object. Object name: 'Stream has been closed.
Is telling you that the stream (voirImageCamera) is no longer useable.
I'm not sure what internal code is disposing that stream. Maybe MediaPicker thinks its no longer needed. Or maybe its due to copying from one image source to another. Or something about how/when ListView accesses the image source.
As seen in doc Xamarin.Essentials: Media Picker / General Usage, a safe way to use a result from MediaPicker's OpenReadAsync, is to save the stream in a local file, then use that file as the image source:
// save the file into local storage
var newFile = Path.Combine(FileSystem.CacheDirectory, photo.FileName);
using (var stream = await photo.OpenReadAsync())
using (var newStream = File.OpenWrite(newFile))
await stream.CopyToAsync(newStream);
Then set the image source to that file:
Image_Photos.Source = ImageSource.FromFile(newFile);
The advantage of FromFile, is that it should be able to open the file at any time it needs - there is no stream being held open.
NOTE: The doc example uses CacheDirectory. Depending on the situation, FileSystem.AppDataDirectory might be more appropriate (files that should be kept indefinitely).

How to use Share in Xamarin.iOS

I am following the documentation here:
https://learn.microsoft.com/en-us/xamarin/essentials/share?tabs=android
To implement the share functionality in my Xamarin.iOS app. My code:
byte[] pdf = await DownloadPdfFile();
var fn = "myfile.pdf";
var file = Path.Combine(FileSystem.CacheDirectory, fn);
await File.WriteAllBytesAsync(file, pdf);
await Share.RequestAsync(new ShareFileRequest
{
Title = ViewModel.Parameter.Title,
File = new ShareFile(file)
});
Nothing happens when I run this code.
My guess is you need to add some permissions in your info.plist
<key>NSPhotoLibraryAddUsageDescription</key>
<string>This app needs access to the photo gallery for saving photos and videos.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>This app needs access to photos gallery for saving photos and videos.</string>
Let me know in case you have queries
I solved it. There is a bug when running on iPad as mentioned here and you can fix this by specifying the PresentationSourceBounds:
await Share.RequestAsync(new ShareFileRequest
{
Title = "My title",
File = new ShareFile(file),
PresentationSourceBounds = new System.Drawing.Rectangle((int)View.Frame.Width, 0, (int)(View.Frame.Width), (int)(View.Frame.Height))
});

Open PDF file with page number/index in UWP apps

Is there any option to Open a PDF file that is available in local state folder (inside app installation directory) with the page number. There is one method (launchFileAsync) to open such files but I don't find any option to pass page number/index to open specific page.
Thank you! Any help is appreciated.
UWP provides the PdfDocument class for parsing PDF files, and this class provides the GetPage method for obtaining the object of the corresponding page (PdfPage) through the index.
This is simple code:
PdfDocument pdfDocument;
StorageFile file = await ApplicationData.Current.LocalFolder.GetFileAsync("xxx.pdf");
pdfDocument = await PdfDocument.LoadFromFileAsync(file);
using (var firstPage = pdfDocument.GetPage(0))
{
var stream = new InMemoryRandomAccessStream();
await firstPage.RenderToStreamAsync(stream);
// do something...
}
Here is the complete code example:
PDF document sample

Google Drive Picker - select folders to upload

I have my picker code as follows:
var mimetypes = "application/vnd.ms-excel," +
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet," +
"application/vnd.google-apps.spreadsheet," +
"application/vnd.ms-powerpoint," +
"application/vnd.openxmlformats-officedocument.presentationml.presentation," +
"application/vnd.google-apps.presentation," +
"application/vnd.openxmlformats-officedocument.wordprocessingml.document," +
"application/msword," +
"application/vnd.google-apps.document," +
"application/pdf,"+
"application/vnd.google-apps.folder";
var view = new google.picker.View(google.picker.ViewId.DOCS);
view.setMimeTypes(mimetypes);
var docsView = new google.picker.DocsView()
.setIncludeFolders(true)
.setMimeTypes('application/vnd.google-apps.folder')
.setSelectFolderEnabled(true);
var folderView = new google.picker.View(google.picker.ViewId.FODLERS);
folderView.setMimeTypes("application/vnd.google-apps.folder");
var picker = new google.picker.PickerBuilder()
.enableFeature(google.picker.Feature.MINE_ONLY)
.enableFeature(google.picker.Feature.NAV_HIDDEN)
.setAppId(appId)
.setOAuthToken(oauthToken)
.addView(view)
.addView(docsView)
.addView(folderView)
.addView(new google.picker.DocsUploadView())
.setSelectableMimeTypes(mimetypes)
.setDeveloperKey(developerKey)
.setCallback(pickerCallback)
.build();
picker.setVisible(true);
I have added the view to enable "setSelectFolderEnabled" but still after selecting the folder form Picker View, the "Select" button in the bottom remains disabled. I need the folder Id in callback for further processing. But I am unable to figure out how to enable the button even if a folder is selected.
Does Google Picker API only allow to select files saved in Google Drive ??
Just changed my code to this and it works :
var docsView = new google.picker.DocsView().
setIncludeFolders(true).
setSelectFolderEnabled(true);
var picker = new google.picker.PickerBuilder()
.enableFeature(google.picker.Feature.MINE_ONLY)
.enableFeature(google.picker.Feature.NAV_HIDDEN)
.setAppId(appId)
.setOAuthToken(oauthToken)
.setDeveloperKey(developerKey)
.addView(docsView)
.setCallback(pickerCallback)
.build();
picker.setVisible(true);
Try to add the google.picker.​ViewId.FOLDERS viewId in the addView. I think you can't select folders due to it not being set in the PickerView.Builder. More information about the View Descriptions can be found on the Showing Different Views of the Picker API documentation.
After that, determine if you have write scopes for you to upload files to Drive.

Save Image from My Pictures Folder to Local App Folder in Windows 8 Metro App

I'm using a button to select an image from the Pictures folder, what I want is to save that selected image to the app's Local Storage in order to be able to show that image using binding in a GridView. Is this posible? How could I do it? Thanks
You would do it something like this:
FileOpenPicker openPicker = new FileOpenPicker();
openPicker.ViewMode = PickerViewMode.Thumbnail;
openPicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
openPicker.FileTypeFilter.Add(".jpg");
openPicker.FileTypeFilter.Add(".jpeg");
openPicker.FileTypeFilter.Add(".png");
StorageFile file = await openPicker.PickSingleFileAsync();
if (file != null)
{
await file.CopyAsync(Windows.Storage.ApplicationData.Current.LocalFolder);
}

Resources