我试图扫描我的应用程序中的QR码。它有时起作用,有时不起作用。感觉是当另一个线程上正在加载某些东西时,它不起作用。例如,当附近的商店仍在加载时,如果我按下扫描按钮。如果我等待,通常会奏效。
视频捕获正常,因为我会看到预览。
这是我的代码:
private bool resultFound;
public ScannerView()
{
InitializeComponent();
On<Xamarin.Forms.PlatformConfiguration.iOS>().SetUseSafeArea(false);
view = new UIView();
ScannerArea.Children.Add(view);
}
void HandleAVRequestAccessStatus(bool accessGranted)
{
if (!accessGranted)
{
MainThread.BeginInvokeOnMainThread(async () =>
{
await NavigationHelper.Current.CloseModalAsync();
});
}
metadataOutput = new AVCaptureMetadataOutput();
var metadataDelegate = new MetadataOutputDelegate();
metadataOutput.SetDelegate(metadataDelegate, DispatchQueue.MainQueue);
session = new AVCaptureSession();
camera = AVCaptureDevice.DevicesWithMediaType(AVMediaType.Video).First();
input = AVCaptureDeviceInput.FromDevice(camera);
session.AddInput(input);
session.AddOutput(metadataOutput);
metadataOutput.MetadataObjectTypes = AVMetadataObjectType.QRCode | AVMetadataObjectType.EAN8Code | AVMetadataObjectType.EAN13Code;
metadataDelegate.MetadataFound += MetadataDelegate_MetadataFound;
camera.LockForConfiguration(out var error);
camera.VideoZoomFactor = 2;
camera.UnlockForConfiguration();
layer = new AVCaptureVideoPreviewLayer(session);
layer.VideoGravity = AVLayerVideoGravity.ResizeAspectFill;
layer.MasksToBounds = true;
layer.Frame = UIApplication.SharedApplication.KeyWindow.RootViewController.View.Bounds;
view.Layer.AddSublayer(layer);
session.StartRunning();
}
protected override void OnAppearing()
{
base.OnAppearing();
var status = AVCaptureDevice.GetAuthorizationStatus(AVMediaType.Video);
if (status != AVAuthorizationStatus.Authorized)
{
MainThread.BeginInvokeOnMainThread(() =>
{
AVCaptureDevice.RequestAccessForMediaType(AVMediaType.Video, HandleAVRequestAccessStatus);
});
return;
}
HandleAVRequestAccessStatus(true);
}
protected override void OnDisappearing()
{
base.OnDisappearing();
session.StopRunning();
session.RemoveInput(input);
session = null;
}
void Handle_Clicked(object sender, System.EventArgs e)
{
NavigationHelper.Current.CloseModalAsync();
}
void MetadataDelegate_MetadataFound(object sender, AVMetadataMachineReadableCodeObject e)
{
if (resultFound)
{
return;
}
resultFound = true;
var text = e.StringValue;
Device.BeginInvokeOnMainThread(async () =>
{
Vibration.Vibrate(100);
await NavigationHelper.Current.CloseModalAsync();
TinyPubSub.Publish(NavigationParameter.ToString(), text);
});
}
}
public class MetadataOutputDelegate : AVCaptureMetadataOutputObjectsDelegate
{
public override void DidOutputMetadataObjects(AVCaptureMetadataOutput captureOutput, AVMetadataObject[] metadataObjects, AVCaptureConnection connection)
{
foreach (var m in metadataObjects)
{
if (m is AVMetadataMachineReadableCodeObject)
{
MetadataFound(this, m as AVMetadataMachineReadableCodeObject);
}
}
}
public event EventHandler<AVMetadataMachineReadableCodeObject> MetadataFound = delegate { };
}