MediaLibrary.SavePicture method results in a System.UnauthorizedAccessException - windows-phone-7

I've got the following code which handles downloading and saving an Image to the phone's media library. It fails with a System.UnauthorizedAccessException as if there was some cross-thread access. To my understading all code below an await statement runs on the UI thread so this should not be an issue. In addition I've tried wrapping the code below var stream = await client.OpenReadTaskAsync(this.Url); with Deployment.Current.Dispatcher.BeginInvoke but it did not help. :(
I am running this on WP8 with the intention to port the code later to WP7.
private async void OnSaveImageCommand()
{
RunProgressIndicator(true, "Downloading image...");
var client = new WebClient();
try
{
var stream = await client.OpenReadTaskAsync(this.Url);
var bitmap = new BitmapImage();
bitmap.SetSource(stream);
using (var memoryStream = new MemoryStream())
{
var writeableBitmap = new WriteableBitmap(bitmap);
writeableBitmap.SaveJpeg(memoryStream, writeableBitmap.PixelWidth, writeableBitmap.PixelHeight, 0,
100);
memoryStream.SetLength(memoryStream.Position);
memoryStream.Seek(0, SeekOrigin.Begin);
var mediaLibrary = new MediaLibrary();
mediaLibrary.SavePicture("image.jpg", memoryStream);
MessageBox.Show("Image has been saved to the phone's photo album");
}
}
catch
{
MessageBox.Show("Failed to download image");
}
finally
{
RunProgressIndicator(false);
}
}

Did you add an ID_CAP_MEDIALIB_PHOTO capability to your app's manifest?
UnauthorizedAccessException is 99% of the time a missing capability.

Related

How to load/draw an image using NGraphics?

In my Xamarin Forms app, I have an image under androidProject/Resources/drawable/myImage.png. To load these from Xamarin, you can simply do
Image myImage = new Image() { Source = ImageSource.FromFile("myImage.png") };
However, there is no way to draw an Image using NGraphics. Instead, NGraphics DrawImage(IImage) requires an IImage. As far as I can tell, there's no way to turn a Xamarin.Forms.Image into an NGraphics.IImage. In fact, the only way I could find to load IImage is
IImage myImage = Platform.LoadImage("myImage.png");
However, this doesn't work because under the hood this uses BitmapFactory.decodeFile(), which requires the absolute file path. And I couldn't find any way to get the absolute file path of a resource (if it even exists?)
So, how do I actually load and display an image using NGraphics?
NGraphics does not provide any helpers to load images from your Platforms Resource files.
You could do something as follows. However, it will add some overhead converting back and forth between bitmap -> stream -> bitmap.
Android:
Stream GetDrawableStream(Context context, int resourceId)
{
var drawable = ResourcesCompat.GetDrawable(context.Resources, resourceId, context.Theme);
if (drawable is BitmapDrawable bitmapDrawable)
{
var stream = new MemoryStream();
var bitmap = bitmapDrawable.Bitmap;
bitmap.Compress(Bitmap.CompressFormat.Png, 80, stream);
bitmap.Recycle();
return stream;
}
return null;
}
iOS:
Stream GetImageStream(string fileName)
{
using (var image = UIImage.FromFile(fileName))
using (var imageData = image.AsPNG())
{
var byteArray = new byte[imageData.Length];
System.Runtime.InteropServices.Marshal.Copy(imageData.Bytes, byteArray, 0, Convert.ToInt32(imageData.Length));
var stream = new MemoryStream(byteArray);
return stream;
}
return null;
}
However, you could go directly from Bitmap to BitmapImage on Android instead like:
BitmapImage GetBitmapFromDrawable(Context context, int resourceId)
{
var drawable = ResourcesCompat.GetDrawable(context.Resources, resourceId, context.Theme);
if (drawable is BitmapDrawable bitmapDrawable)
{
var bitmap = bitmapDrawable.Bitmap;
return new BitmapImage(bitmap);
}
return null;
}
And on iOS:
CGImageImage GetImageStream(string fileName)
{
var iOSimage = UIImage.FromFile(fileName);
var cgImage = new CGImageImage(iOSImage.CGImage, iOSImage.Scale);
return cgImage;
}
BitmapImage and CGImageImage implement IImage in NGraphics.

UWP FileOpenPicker locks\freezes app in debug

If the debugger is attached, calling this function causes the app to hang. If I run without a debugger, there is no hang, and file pickers work perfectly.
private async void OnClick(object sender, RoutedEventArgs e)
{
FileOpenPicker openPicker = new FileOpenPicker();
}
I'm certain this is something super simple, but I just don't know.
Edit:
Here's how I'm using it. Keep in mind, that the simpler function creates the hang issue without all my extra code after it. I've stuffed up the image saving, but that's a separate issue I want to debug when I solve what this post is about.
.
public async Task ImportHeader()
{
FileOpenPicker openPicker = new FileOpenPicker();
openPicker.ViewMode = PickerViewMode.Thumbnail;
openPicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
openPicker.FileTypeFilter.Add(".jpg");
openPicker.FileTypeFilter.Add(".png");
// For multiple image selection
var files = await openPicker.PickMultipleFilesAsync();
foreach (StorageFile singleImage in files)
{
IRandomAccessStream stream = await singleImage.OpenAsync(Windows.Storage.FileAccessMode.Read);
var image = new BitmapImage();
image.SetSource(stream);
HeaderImage.Source = image;
//We also save this to disk for later
Windows.Storage.StorageFolder storageFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
Windows.Storage.StorageFile file = await storageFolder.CreateFileAsync("header.jpg", Windows.Storage.CreationCollisionOption.ReplaceExisting);
stream.Seek(0);
using (StreamWriter bw = new StreamWriter(file.OpenStreamForWriteAsync().Result))
{
var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, stream);
var renderTargetBitmap = new RenderTargetBitmap();
await renderTargetBitmap.RenderAsync(HeaderImage, (int)HeaderImage.Width, (int)HeaderImage.Height);
var pixels = await renderTargetBitmap.GetPixelsAsync();
byte[] bytes = pixels.ToArray();
bw.Write(stream);
}
}
}
This has happened to me as well on some of the recent Windows 10 Insider Preview builds, while the process works flawlessly on stable builds of Windows 10. I think you can assume the cause is there instead of your code.

Load CCSprite Image from URL - CocosSharp + Xamarin.forms

I am working on Xamarin.Forms + CocosSharp Application. Here I want to load an image from an URL in cocoassharp using CCSprite. How can I achieve this? Normal CCSprite image is created like: var sprite = new CCSprite("image.png");
It is better to use async for stream and Read. I just did testing in place where that was not convenient but you should use async versions.
var webClient = new HttpClient();
var imageStream = webClient.GetStreamAsync(new Uri("https://xamarin.com/content/images/pages/forms/example-app.png")).Result;
byte[] imageBytes = new byte[imageStream.Length];
int read=0;
do
{
read += imageStream.Read(imageBytes, read, imageBytes.Length- read);
} while (read< imageBytes.Length);
CCTexture2D texture = new CCTexture2D(imageBytes);
var sprite = new CCSprite(texture);

Xamarin.forms i want to upload image on same page

i am uploading my image by using plugins.media but the problem is it redirect to another photoimage page and upload it there.
var profiletap = new TapGestureRecognizer();
profiletap.Tapped += async (s, e) =>
{
var file = await CrossMedia.Current.PickPhotoAsync();
if (file == null)
return;
await DisplayAlert("File Location", file.Path, "OK");
ImageSource im = ImageSource.FromStream(() =>
{
var stream = file.GetStream();
file.Dispose();
return stream;
});
await Navigation.PushModalAsync(new PhotoPage(im));
};
profile.GestureRecognizers.Add(profiletap);
ant here is photopage content
public class PhotoPage : demopage
{
public PhotoPage(ImageSource img)
{
Content = new Image
{
VerticalOptions =LayoutOptions.Start,
HorizontalOptions = LayoutOptions.Start,
Source =img
};
}
}
Instead of doing
await Navigation.PushModalAsync(new PhotoPage(im));
you can do something like
var img = new Image
{
Source =im
};
then add the new img control to the same container as where the "profile" control has already been added (probably some Stacklayout or Grid or some other layout control like that)
Be aware that you are struggling with the most basic concept of building out your app UI, which is a strong indicator you should read some getting started tutorials for xamarin.forms and really understand how the UI is built.

Unable to rotate image in windows store app

I'm attempting to take a photo with my device camera, but images taken with the device held in "portrait" mode come out sideways. I'd like to rotate them before saving them, but the solution that I keep coming across isn't working for me.
Windows.Storage.Streams.InMemoryRandomAccessStream stream = new Windows.Storage.Streams.InMemoryRandomAccessStream();
imagePreview.Source = null;
await stream.WriteAsync(currentImage.AsBuffer());
stream.Seek(0);
BitmapDecoder decoder = await BitmapDecoder.CreateAsync(stream);
BitmapEncoder encoder = await BitmapEncoder.CreateForTranscodingAsync(stream, decoder);
encoder.BitmapTransform.Rotation = BitmapRotation.Clockwise90Degrees;
encoder.IsThumbnailGenerated = false;
await encoder.FlushAsync();
//save the image
StorageFolder folder = KnownFolders.SavedPictures;
StorageFile capturefile = await folder.CreateFileAsync("photo_" + DateTime.Now.Ticks.ToString() + ".bmp", CreationCollisionOption.ReplaceExisting);
string captureFileName = capturefile.Name;
//store stream in file
using (var fileStream = await capturefile.OpenStreamForWriteAsync())
{
try
{
//because of using statement stream will be closed automatically after copying finished
await Windows.Storage.Streams.RandomAccessStream.CopyAsync(stream, fileStream.AsOutputStream());
}
catch
{
}
}
this produces the original image with no rotation applied to it. I've looked at a lot of samples, and can't figure out what I'm doing wrong.

Resources