How to know that camera is currently being used by another application with UWP?

1

I am trying to show error message "Cannot setup camera; currently being using" when there is already a process running the camera. I have the code that starts the preview using the MediaCapture and it works fine when running without another application using camera. I do get the exception

0x40080201: WinRT originate error (parameters: 0xC00D3704, 0x00000049, 0x10EFF1CC)

in my logs but my try catch block doesn't catch the error.

create_task(_mediaCapture->StartPreviewToCustomSinkAsync(encoding_profile, media_sink)).then([this, &hr](task<void>& info) {
    try {
         info.get();
    } catch (Exception^ e) {
        hr = e->HResult;
    }
}).wait();
windows
camera
uwp
c++-cx
asked on Stack Overflow Jun 10, 2017 by surajp • edited Jun 14, 2017 by Jay Zuo

1 Answer

1

StartPreviewAsync method will throw a FileLoadException if another app has exclusive control of the capture device. We can catch this error to alert the user that the camera is currently being used by another application. A simple sample can be found at Use MediaCapture to start the preview stream.

However, this is a C# sample and FileLoadException is what used in .Net. For C++/CX, we can check the HRESULT value which should be 0x80070020. Following is the simple sample in C++/CX version.

MainPage.xaml

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <CaptureElement Name="PreviewControl" Stretch="Uniform"/>
    <Button Click="Button_Click">Click</Button>
</Grid>

MainPage.xaml.h

public ref class MainPage sealed
{
public:
    MainPage();

private:
    // Prevent the screen from sleeping while the camera is running
    Windows::System::Display::DisplayRequest^ _displayRequest;

    // MediaCapture
    Platform::Agile<Windows::Media::Capture::MediaCapture^> _mediaCapture;

    void Button_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
};

MainPage.xaml.cpp

MainPage::MainPage()
    : _mediaCapture(nullptr)
    , _displayRequest(ref new Windows::System::Display::DisplayRequest())
{
    InitializeComponent();
}


void MainPage::Button_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
{
    _mediaCapture = ref new Windows::Media::Capture::MediaCapture();
    create_task(_mediaCapture->InitializeAsync())
        .then([this](task<void> previousTask) {
        try
        {
            previousTask.get();
            _displayRequest->RequestActive();
            Windows::Graphics::Display::DisplayInformation::AutoRotationPreferences = Windows::Graphics::Display::DisplayOrientations::Landscape;
            PreviewControl->Source = _mediaCapture.Get();
            create_task(_mediaCapture->StartPreviewAsync())
                .then([this](task<void>& previousTask)
            {
                try
                {
                    previousTask.get();
                }
                catch (Exception^ exception)
                {
                    if (exception->HResult == 0x80070020)
                    {
                        auto messageDialog = ref new Windows::UI::Popups::MessageDialog("Cannot setup camera; currently being using.");
                        create_task(messageDialog->ShowAsync());
                    }
                }
            });
        }
        catch (AccessDeniedException^)
        {
            auto messageDialog = ref new Windows::UI::Popups::MessageDialog("The app was denied access to the camera.");
            create_task(messageDialog->ShowAsync());
        }
    });
}

StartPreviewToCustomSinkAsync method is similar to StartPreviewAsync method and can also throw a FileLoadException. You should be able to handle it using the same way. For more info, please also see Handle changes in exclusive control.

answered on Stack Overflow Jun 14, 2017 by Jay Zuo

User contributions licensed under CC BY-SA 3.0