Исключение из сканера штрих-кода с пользовательским предварительным просмотром - PullRequest
0 голосов
/ 06 июня 2019

В настоящее время я использую BarcodeScanner с пользовательским предварительным просмотром, показанным в ContentDialog.

Я действительно использовал код, предоставленный в документации Microsoft, и все работает правильно, но только один раз.

Вот мой целый BarcodeScanner класс обслуживания:

public class BarcodeScannerUtil : IBarcodeScanner
{
    private static Windows.Devices.PointOfService.BarcodeScanner _scanner = null;
    private static ClaimedBarcodeScanner _claimedBarcodeScanner = null;
    private static Action<string> _callback;

    MediaCapture mediaCapture;
    bool isPreviewing;
    DisplayRequest displayRequest = new DisplayRequest();
    CameraPreviewDialog preview = new CameraPreviewDialog();

    public async Task ClaimScannerAsync()
    {
        string selector = Windows.Devices.PointOfService.BarcodeScanner.GetDeviceSelector();
        DeviceInformationCollection deviceCollection = await DeviceInformation.FindAllAsync(selector);

        if (_scanner == null)
            _scanner = await Windows.Devices.PointOfService.BarcodeScanner.FromIdAsync(deviceCollection[0].Id);

        if (_scanner != null)
        {
            if (_claimedBarcodeScanner == null)
                _claimedBarcodeScanner = await _scanner.ClaimScannerAsync();

            if (_claimedBarcodeScanner != null)
            {
                _claimedBarcodeScanner.DataReceived += ClaimedBarcodeScanner_DataReceivedAsync;
                _claimedBarcodeScanner.ReleaseDeviceRequested += ClaimedBarcodeScanner_ReleaseDeviceRequested;
                _claimedBarcodeScanner.IsDecodeDataEnabled = true;
                _claimedBarcodeScanner.IsDisabledOnDataReceived = true;
                await _claimedBarcodeScanner.EnableAsync();
                //await _claimedBarcodeScanner.ShowVideoPreviewAsync();
                await _claimedBarcodeScanner.StartSoftwareTriggerAsync();
                await StartPreviewAsync();

                Debug.WriteLine("Barcode Scanner claimed");
            }
        }
    }

    private MediaCaptureInitializationSettings InitCaptureSettings()
    {
        var _captureInitSettings = new MediaCaptureInitializationSettings();
        _captureInitSettings.VideoDeviceId = _scanner.VideoDeviceId;
        _captureInitSettings.StreamingCaptureMode = StreamingCaptureMode.Video;
        _captureInitSettings.PhotoCaptureSource = PhotoCaptureSource.VideoPreview;

        return _captureInitSettings;
    }

    private async Task StartPreviewAsync()
    {
        try
        {
            mediaCapture = new MediaCapture();
            await mediaCapture.InitializeAsync(InitCaptureSettings());
            displayRequest.RequestActive();
            DisplayInformation.AutoRotationPreferences = DisplayOrientations.Landscape;
        }
        catch (UnauthorizedAccessException)
        {
            await new ErrorDialog("Impossible d'acceder à la caméra, veuillez vérifier les permissions de l'application.").ShowAsync();
        }

        try
        {
            preview.Source = mediaCapture;
            await mediaCapture.StartPreviewAsync();
            isPreviewing = true;
            ContentDialogResult resPreview = await preview.ShowAsync();

            //clic sur le bouton annuler
            if (resPreview == ContentDialogResult.Secondary)
            {
                await CleanupCameraAsync();
                await _claimedBarcodeScanner.StopSoftwareTriggerAsync();
                await _claimedBarcodeScanner.DisableAsync();
            }

        }
        catch (System.IO.FileLoadException)
        {
            mediaCapture.CaptureDeviceExclusiveControlStatusChanged += _mediaCapture_CaptureDeviceExclusiveControlStatusChanged;
        }

    }

    private async Task CleanupCameraAsync()
    {
        if (mediaCapture != null)
        {
            if (isPreviewing)
            {
                await mediaCapture.StopPreviewAsync();
            }

            await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
            {
                preview.Source = null;
                if (displayRequest != null)
                {
                    displayRequest.RequestRelease();
                }

                mediaCapture.Dispose();
                mediaCapture = null;
            });
        }

    }

    public void Subscribe(Action<string> callback)
    {
        // it makes sense to have only one foreground barcode reader client at a time
        _callback = callback;
    }

    /// <summary>
    /// Retire une action callback du BarcodeScanner
    /// </summary>
    public void Unsubscribe()
    {
        _callback = null;
    }

    private async void ClaimedBarcodeScanner_DataReceivedAsync(ClaimedBarcodeScanner sender, BarcodeScannerDataReceivedEventArgs args)
    {
        await CleanupCameraAsync();
        await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
        {
            preview.Hide();
        });

        if (_callback == null)
            return;

        var barcode = CryptographicBuffer.ConvertBinaryToString(BinaryStringEncoding.Utf8, args.Report.ScanDataLabel);
        _callback(barcode);
    }

    private void ClaimedBarcodeScanner_ReleaseDeviceRequested(object sender, ClaimedBarcodeScanner e)
    {
        // always retain the device
        e.RetainDevice();
    }

    private async void _mediaCapture_CaptureDeviceExclusiveControlStatusChanged(MediaCapture sender, MediaCaptureDeviceExclusiveControlStatusChangedEventArgs args)
    {
        if (args.Status == MediaCaptureDeviceExclusiveControlStatus.SharedReadOnlyAvailable)
        {
            await new ErrorDialog("Impossible d'acceder à la caméra car elle est utilisée par une autre application.").ShowAsync();
        }
        else if (args.Status == MediaCaptureDeviceExclusiveControlStatus.ExclusiveControlAvailable && !isPreviewing)
        {
            await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
            {
                await StartPreviewAsync();
            });
        }
    }
}

Когда я показываю свой предварительный просмотр, я использую IsDisabledOnDataReceived = true;, но когда я снова открываю свой сканер штрих-кода, я получаю исключение, говорящее System.Exception : 'The request is invalid in the current state. Started' в await mediaCapture.StopPreviewAsync(); в CleanupCameraAsync()

Это действительно странно, потому что, когда я нажимаю кнопку «Отмена» на ContentDialog, показывающей предварительный просмотр, это делает точно то же самое, и после этого никаких проблем не возникает.

Я искал час, и понятия не имею, откуда это может быть.

1 Ответ

0 голосов
/ 14 июня 2019

Наконец-то нашёл ответ сам:

Я переместил CleanupCameraAsync() из моего события OnReceived в результаты моего диалогового окна содержимого

ContentDialogResult resPreview = await preview.ShowAsync();

//clic sur le bouton annuler
if (resPreview == ContentDialogResult.Secondary)
{
    await _claimedBarcodeScanner.StopSoftwareTriggerAsync();
    await _claimedBarcodeScanner.DisableAsync();
    await CleanupCameraAsync();
}
else
{
    await CleanupCameraAsync();
}

Поэтому, когда я закрываю диалог кнопкой, он работает, и если он закрывается каким-либо другим способом, CleanupCameraAsync() все равно будет срабатывать.

Плюс, я добавил несколько строк в CleanupCameraAsync() для сброса всех компонентов моего BarcodeScanner

private async Task CleanupCameraAsync()
{
    if (mediaCapture != null)
    {
        if (isPreviewing)
        {
            await mediaCapture.StopPreviewAsync();
        }

        await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
        {
            preview.Source = null;
            if (displayRequest != null)
            {
                displayRequest.RequestRelease();
            }

            mediaCapture.Dispose();
            mediaCapture = null;

            /*******added these lines*********/
            displayRequest = new DisplayRequest();
            preview = new CameraPreviewDialog();
            _scanner = null;
            _claimedBarcodeScanner = null;
        });
    }
}

Это не совсем чисто, но вынуждает BarcodeScanner вести себя по умолчанию при каждом вызове.

Если у вас есть лучшее решение, дайте мне знать, пожалуйста.

...