JoyfulReaper
JoyfulReaper

Reputation: 11

Blazor Hyrid - Access Device Camera from InputFile

I am attempting to using Blazor Hybrid (on MAUI) to capture an image from the camera (on Android in my case). I have been trying for awhile with no success. This StackOverflow suggests trying the following:

<input type="file" accept="image/*" capture>

However, this and also:

<InputFile OnChange="LoadPhoto" accept="image/*" capture />

does not work for me in Blazor Hybrid (it does work in Blazor Server/WASM). Both result in the file picker widget opening in Android rather than the camera widget. Any suggestions?

Upvotes: 1

Views: 2749

Answers (2)

yushulx
yushulx

Reputation: 12160

You can implement it as follows:

  1. Create a button and an image element in your razor file:
    <button @onclick="CaptureImage">Capture Image</button>
    <img id="image" />
    
  2. Add the CaptureImage function:
    public async Task CaptureImage()
    {
        FileResult photo = null;
        if (DeviceInfo.Current.Platform == DevicePlatform.WinUI || DeviceInfo.Current.Platform == DevicePlatform.MacCatalyst)
        {
            photo = await FilePicker.PickAsync();
        }
        else if (DeviceInfo.Current.Platform == DevicePlatform.Android || DeviceInfo.Current.Platform == DevicePlatform.iOS)
        {
            photo = await MediaPicker.CapturePhotoAsync();
        }
    
        if (photo == null)
        {
            return;
        }
    
        using (var stream = await photo.OpenReadAsync())
        {
            var dotnetImageStream = new DotNetStreamReference(stream);
            await JSRuntime.InvokeAsync<bool>("jsFunctions.captureImage", "image", dotnetImageStream);
        }
    
    }
    
  3. Implement the JavaScript function in your js file:
    window.jsFunctions = {
     captureImage: async function (imageId, imageStream) {
         const arrayBuffer = await imageStream.arrayBuffer();
         const blob = new Blob([arrayBuffer]);
         const url = URL.createObjectURL(blob);
         document.getElementById(imageId).src = url;
         document.getElementById(imageId).style.display = 'block';
         return true;
     },
    }
    

Upvotes: 3

gonzalorf
gonzalorf

Reputation: 311

I'd use native access to the camera. You can communicate MAUI and the Blazor part through a object injected with DI. This way, the blazor code doesn´t know that is running in a MAUI app. This object should have a method like "TakePicture()" that you call in Blazor when clicking a button and rises an event like "OnTakePicture". The MAUI part should attach an event handler to OnTakePicture, so it can take a picture with the camera. When the picture is taken, you do the oposite way to get the picture as a byte[] and show it.

Upvotes: 2

Related Questions