带有自定义预览的条形码扫描仪异常
Exception from barcode scanner with custom preview
我目前正在使用 BarcodeScanner
并在 ContentDialog
中显示自定义预览。
我确实使用了 Microsoft 文档中提供的代码,并且一切正常,但只有一次。
这是我的全部 BarcodeScanner
服务 class:
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'
at await mediaCapture.StopPreviewAsync();
CleanupCameraAsync()
这真的很奇怪,因为当我点击显示预览的 ContentDialog
的取消按钮时,它做的事情完全一样,之后就没有问题了。
我已经搜索了一个小时,但不知道它的来源。
终于自己找到了答案:
我将 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
在我每次调用它时都具有默认行为。
如果您有更好的解决方案,请告诉我。
我目前正在使用 BarcodeScanner
并在 ContentDialog
中显示自定义预览。
我确实使用了 Microsoft 文档中提供的代码,并且一切正常,但只有一次。
这是我的全部 BarcodeScanner
服务 class:
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'
at await mediaCapture.StopPreviewAsync();
CleanupCameraAsync()
这真的很奇怪,因为当我点击显示预览的 ContentDialog
的取消按钮时,它做的事情完全一样,之后就没有问题了。
我已经搜索了一个小时,但不知道它的来源。
终于自己找到了答案:
我将 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
在我每次调用它时都具有默认行为。
如果您有更好的解决方案,请告诉我。