0

I am attempting to read a QRCode in Xamarin.Forms. I have a shared project in XF. I have added the nuget packages for ZXing.Net. Everything works in the iOS project. I am getting an error in the Android project. The errors that I get via Android SDK Monitor, it indicates that there is a problem with the scanner being null and not being accessible. I am guessing that there is something that I have not set up correct on the Android side. Does anyone see anything improper in my code? Thanks for your time.

ScanPage class:
public class ScanPage : ContentPage
{
    ZXing.Net.Mobile.Forms.ZXingScannerView zxing;
    ZXingDefaultOverlay overlay;
    bool isConnected = false;
    string basicUrl = "golfeventscores.azurewebsites.net";
    public ScanPage ()
    {

        zxing = new ZXing.Net.Mobile.Forms.ZXingScannerView
        {
            HorizontalOptions = LayoutOptions.FillAndExpand,
            VerticalOptions = LayoutOptions.FillAndExpand,
            AutomationId = "zxingScannerView",
        };
        zxing.OnScanResult += async (ZXing.Result result) => {
            zxing.IsAnalyzing = false;
            zxing.IsScanning = false;
            var teamToken = result.Text;
            //MessagingCenter.Send<string>(teamToken, "SelectTeamMembers");
            isConnected = await Plugin.Connectivity.CrossConnectivity.Current.IsRemoteReachable(basicUrl);
            if (isConnected)
            {
                await GetTeamData(teamToken);
            }
            else
            {
                await DisplayAlert("Connectivity", "There is a problem with internet connectivity. Please try and reload this screen.", "Ok");
            }
        };

        overlay = new ZXingDefaultOverlay
        {
            TopText = "Hold your phone up to the barcode",
            BottomText = "Scanning will happen automatically",
            ShowFlashButton = zxing.HasTorch,
            AutomationId = "zxingDefaultOverlay",
        };
        overlay.FlashButtonClicked += (sender, e) => {
            zxing.IsTorchOn = !zxing.IsTorchOn;
        };
        var grid = new Grid
        {
            VerticalOptions = LayoutOptions.FillAndExpand,
            HorizontalOptions = LayoutOptions.FillAndExpand,
        };
        grid.Children.Add(zxing);
        grid.Children.Add(overlay);

        // The root page of your application
        Content = grid;
    }

    protected override void OnAppearing()
    {
        base.OnAppearing();
        zxing.IsScanning = true;
    }

    protected override void OnDisappearing()
    {
        zxing.IsScanning = false;
        base.OnDisappearing();
    }
    async System.Threading.Tasks.Task GetTeamData(string Token)
    {
        try
        {
            var scanResult = await WebServices.ws.TokenLookup(Token);
            if (scanResult.Result == true)
            {
                if (scanResult.IsScoreBoard == true)
                {
                    var uri = new System.Uri(scanResult.ScoreboardUrl);
                    Device.BeginInvokeOnMainThread(() =>
                    {
                        Device.OpenUri(uri);
                        Navigation.PopToRootAsync();
                    });
                }
                if (scanResult.IsCharity == true)
                {
                    if (scanResult.TeamPlayers.Count > 0)
                    {
                        var player = scanResult.TeamPlayers.First();
                        var playerId = player.PlayerTeamId;
                        var urlResult = await WebServices.ws.ServerUrl(Token, playerId);

                        if (urlResult.ValidRequest && (!String.IsNullOrEmpty(urlResult.Url)))
                        {
                            var uri = new System.Uri(urlResult.Url);
                            Device.OpenUri(uri);
                            await Navigation.PopToRootAsync();
                        }
                    }
                    else{
                        await DisplayAlert("Scanning", "There was a problem downloading the Charity Team Info.", "OK");
                    }
                }
                else
                {
                    if (scanResult.IsLargeGame != true)
                    {
                        var select = new Pages.SelectTeamMembers(Token);
                        await Navigation.PushAsync(select);
                    }
                    else
                    {
                        await DisplayAlert("Large Game", "Don't have the large team game setup with scanning.", "Ok");
                    }
                }
            }
            else
            {
                await DisplayAlert("Server Problem", "There was some type of server error. Please try again or call Wally.", "Ok");
            }
        }
        catch(System.Exception sysExc)
        {
            //nothing seems to be caught
        }
    }
}

MainActivity.cs contents:
[Activity (Label = "TD Scan", Icon = "@drawable/icon", Theme="@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
    protected override void OnCreate (Bundle bundle)
    {
        TabLayoutResource = Resource.Layout.Tabbar;
        ToolbarResource = Resource.Layout.Toolbar; 

        base.OnCreate (bundle);
        global::Xamarin.Forms.Forms.Init (this, bundle);
        ZXing.Net.Mobile.Forms.Android.Platform.Init();
        LoadApplication (new GolfGameScanApp.App ());
    }

    public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Permission[] grantResults)
    {
        ZXing.Net.Mobile.Android.PermissionsHandler.OnRequestPermissionsResult(requestCode, permissions, grantResults);
    }
}
Rob
  • 14,746
  • 28
  • 47
  • 65
Wallace B. McClure
  • 1,165
  • 1
  • 15
  • 31

1 Answers1

0

Have you defined all in Android Project?

Xamarin Forms

For Xamarin Forms there is a bit more setup needed. You will need to initialize the library on each platform in your platform specific app project.

Android

On Android, in your main Activity's OnCreate (..) implementation, call:

ZXing.Net.Mobile.Forms.Android.Platform.Init();

ZXing.Net.Mobile for Xamarin.Forms also handles the new Android permission request model for you, but you will need to add the following override implementation to your main Activity as well:

public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Permission[] grantResults)
{
    global::ZXing.Net.Mobile.Forms.Android.PermissionsHandler.OnRequestPermissionsResult (requestCode, permissions, grantResults);           
}

The Camera permission should be automatically included for you in the AndroidManifest.xml however if you would like to use the Torch API's you will still need to add the Flashlight permission yourself. You can do this by using the following assembly level attribute:

[assembly: UsesPermission (Android.Manifest.Permission.Flashlight)]
Alessandro Caliaro
  • 5,623
  • 7
  • 27
  • 52
  • Thanks. Yes, all of that has been done. I placed it in the sample code above that I pasted out of my project. :-) Please keep the possible issues coming! It also feels like there might be something I am doing on the wrong thread, but can't quite find it. I've previously had a bunch of Device.BeginInvokeOnMainThread calls everywhere, but it did nothing for me. – Wallace B. McClure Oct 07 '17 at 14:05
  • So, I went back and worked on this. It APPEARS that if you try to do some processing work in this OnScanResult method, hit the UI, whatever, something happens on Android that causes the component to crash. I went back and implemented some messaging via MessageCenter to start processing and that seems to cause things to work as intended. I talked a little to Redth yesterday on IM, but he is on vacay. I'll see if he knows anything when he gets back. Until then, I seem to be working now. – Wallace B. McClure Oct 07 '17 at 15:02
  • Thanks for your thoughts @Alessandro. They really do help. :-) – Wallace B. McClure Oct 07 '17 at 15:02