I have an app for barcode scanning. It scans successfully for a long time. It scans 100 times with success, then suddenly it crashes.
The exception is AndroidRuntimeException: Only the original thread that created a view hierarchy can touch its views.
Then I don't understand much of the exception. Link to full exception: https://hastebin.com/owerixihag.log
I have made sure to use Device.BeginInvokeOnMainThread()
for UI operations.
ScannerPage.xaml
<zxing:ZXingScannerView x:Name="ScannerView"
Result="{Binding ScanResult, Mode=OneWayToSource}"
ScanResultCommand="{Binding ScanResultCommand}"
IsScanning="{Binding IsScanning}"
IsAnalyzing="{Binding IsAnalyzing}" />
<zxing:ZXingDefaultOverlay x:Name="ScannerOverlay"
BottomText="Scanning will happen automatically"
ShowFlashButton="False"/>
ScannerPageViewModel.cs (stripped of irrelevant parts)
[PropertyChanged.AddINotifyPropertyChangedInterface]
internal class ScannerPageViewModel : INavigatedAware
{
public ScannerPageViewModel(IScannerService scannerService, IUserDialogs dialogs, IPopupNavigation popups, IScreenService screen)
{
ScanResultCommand = new Command(ProcessBarcode);
}
public ICommand ScanResultCommand { get; }
/// <summary>
/// Show info dialog box with ticket info.
/// </summary>
private async Task ShowInfoScanResult(string message)
{
var popup = new PopupViews.InfoScanResult(Popups, message);
popup.Disappearing += (se, ev) => IsAnalyzing = true;
await Popups.PushAsync(popup);
}
private void ProcessBarcode()
{
Device.BeginInvokeOnMainThread(async () =>
{
if (ScanResult != null && !string.IsNullOrEmpty(ScanResult.Text))
{
// Disable the scanner after one barcode is found.
IsAnalyzing = false;
var source = new CancellationTokenSource();
// Show loading animation if scanning takes >1 second.
var t = Task.Run(async () =>
{
await Task.Delay(1000, source.Token);
Device.BeginInvokeOnMainThread(ShowLoading);
});
// Call the web service to process the barcode.
var scanResponse = await ScannerService.ScanBarcode(ScanResult.Text, ScanningSession, SelectedScanAction);
if (scanResponse.IsSuccessful)
{
var scanResult = scanResponse.Data;
if (scanResult.Success)
{
var json = scanResult.BarcodeInfo;
var message = ParseJsonBarcodeInfo(json);
if (SelectedScanAction == ScanAction.Information)
await ShowInfoScanResult(message);
else
await ShowOkScanResult(message);
}
else
{
await ShowErrorScanResult(scanResult.FaultDescription);
}
}
else
{
ShowScanRequestError(scanResponse.ErrorMessage);
}
source.Cancel(); // Cancel loading animation timer.
HideLoading();
Screen.SetFullscreen();
source.Dispose();
}
});
}