question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Xamarin all OS: take a photo with CrossMedia.Current.TakePhotoAsync

See original GitHub issue

Bug

I’m creating a project where I have to take a lot of pictures. In my previous project for iOS all are working fine. I’m using the same code for a new project for all platforms (iOS, Android and UWP).

When I take a photo on Android the stream is empty. In UWP when I try to open the page where I can take a photo, the application is blocked: after 3-5 minutes it’s unblocked and I can take a photo.

Version Number of Plugin: 2.3.0 Device Tested On:

  • Nokia Lumia 735 (Windows 10)
  • Cubot Rainbow Sim Free Smartphone Dual Sim 3G Unlocked 5 Inch HD Android 6.0 Quad Core 1.3 GHz 1 GB Ram 16GB Rom Smart Phone 13MP Camera GPS WIFI Hots
  • iPhone 6s

Simulator Tested On:

  • Android 6.0 as Nexus 6P API 23 x86
  • my desktop with Windows 10

Expected Behavior

I can take take a photo to save it on disk

Steps to reproduce the Behavior

        /// <summary>
        /// Gets the camera command.
        /// </summary>
        /// <value>The camera command.</value>
        public ICommand CameraCommand
        {
            get { return _cameraCommand ?? new Command(async () => await ExecuteCameraCommand(), () => CanExecuteCameraCommand()); }
        }

        /// <summary>
        /// Determines whether this instance can execute camera command.
        /// </summary>
        /// <returns><c>true</c> if this instance can execute camera command; otherwise, <c>false</c>.</returns>
        public bool CanExecuteCameraCommand() {
            if (!CrossMedia.Current.IsCameraAvailable || !CrossMedia.Current.IsTakePhotoSupported) {
                return false;
            }
            return true;
        }

        /// <summary>
        /// Executes the camera command.
        /// </summary>
        /// <returns>The camera command.</returns>
        public async Task ExecuteCameraCommand() {
            var file = await CrossMedia.Current.TakePhotoAsync(new Plugin.Media.Abstractions.StoreCameraMediaOptions());

            if (file == null)
                return;

            byte[] imageAsBytes = null;
            using (var memoryStream = new MemoryStream()) {
                file.GetStream().CopyTo(memoryStream);
                file.Dispose();
                imageAsBytes = memoryStream.ToArray();
            }

            if (imageAsBytes.Length > 0) {
                var resizer = DependencyService.Get<IImageResize>();
                imageAsBytes = resizer.ResizeImage(imageAsBytes, 1080, 1080);

                var imageSource = ImageSource.FromStream(() => new MemoryStream(imageAsBytes));
                _images.Add(new GalleryImage { Source = imageSource, OrgImage = imageAsBytes });
            }
        }

Thank you for your job!

Issue Analytics

  • State:closed
  • Created 7 years ago
  • Comments:7 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
jamesmontemagnocommented, Aug 30, 2016

@erportico

You should call the Initialize() before you call the take photo:

 public async Task ExecuteCameraCommand()
        {

            await CrossMedia.Current.Initialize();
            var file = await CrossMedia.Current.TakePhotoAsync(new Plugin.Media.Abstractions.StoreCameraMediaOptions());

of do it in the pages on appearing:

 bool initialized;
        protected override async void OnAppearing()
        {
            base.OnAppearing();
            await CrossMedia.Current.Initialize();
            initialized = true;
            ((Command)CameraCommand).ChangeCanExecute();
        }

For UWP you must call initialize before calling anything else, so update your CanExecute to:

public bool CanExecuteCameraCommand()
        {
            if (!initialized)
                return false;

            if (!CrossMedia.Current.IsCameraAvailable || !CrossMedia.Current.IsTakePhotoSupported)
            {
                return false;
            }
            return true;
        }

Also, make sure in your MainActivity you copied this code in for Android:

public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Permission[] grantResults)
        {
            PermissionsImplementation.Current.OnRequestPermissionsResult(requestCode, permissions, grantResults);
        }

I assume you also set your target to 23: image

I tested the code out that you posed with my modifications on my Nexus 6P running 7.0 stock and it worked perfect. I got a file and got the stream from it.

For UWP I set the Webcam capability in the appxmanifest. In this instance your Command will have an issue because Small optimization: Finally, you should make sure you actually are creating a new command in your getter for the command:

public ICommand CameraCommand
        {
            get { return _cameraCommand ?? (_cameraCommand = new Command(async () => await ExecuteCameraCommand(), () => CanExecuteCameraCommand())); }
        }

Else it will just create a new one every time.

Closing as I tested this on all platforms with production level, and here is a test app that I used:

App36.zip

0reactions
erporticocommented, Sep 9, 2016

My fix at this problem is

[...]
byte[] imageAsBytes = null;
using (var memoryStream = new MemoryStream()) {
   file.GetStream().CopyTo(memoryStream);
   imageAsBytes = memoryStream.ToArray();

   if (imageAsBytes.Length == 0) {
      imageAsBytes = await FileHelper.GetImageAsByte(file.Path);
   }
   file.Dispose();
}
[...]
Read more comments on GitHub >

github_iconTop Results From Across the Web

Xamarin - CrossMedia.Current.TakePhotoAsync saves 2 ...
TakePhotoAsync saves 2 photo's in different locations ... I have created an app that takes pictures using Xamarins CrossMedia.Current.
Read more >
Xamarin.Essentials: Media Picker
The MediaPicker class in Xamarin.Essentials lets a user pick or take a photo or video on the device.
Read more >
Cross Platform Photos with Media Plugin
Here is the easiest example of taking a photo and displaying it in a Xamarin.Forms image. takePhoto.Clicked += async (sender, args) => {...
Read more >
Make an App able to take a Picture using Xamarin
Start by inserting a plugin named Xam.Plugin.Media. Using plugins Does not need to be Xamarin.Forms is an Xamarin.iOS or Xamarin.
Read more >
The step by step set up of Media Plugin for Xamarin.Forms!
Let's properly set up Media Plugin (Xam.Plugin.Media) for Xamarin.Forms, harnessing the full capabilities with an optimized implementation!
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found