4
votes

I am still getting used to Xamarin.Forms and I am on very basic level. I went through many articles for my issue, but to the end couldn't resolve it. So...

Currently I am trying to add Google authentication inside my Xamarin.Forms application, which use Droid and iOS (no WP). So far I am following guide from here. I am using Xamarin.Auth to authenticate to Google.

Here is some part from my source code.


    private async void GoogleSheetsButton_Tapped()
    {
        string clientId = null;
        string redirectUri = null;

        if (Device.RuntimePlatform == Device.iOS)
        {
            clientId = Constants.iOSClientId;
            redirectUri = Constants.iOSRedirectUrl;
        }
        else if (Device.RuntimePlatform == Device.Android)
        {
            clientId = Constants.AndroidClientId;
            redirectUri = Constants.AndroidRedirectUrl;
        }

        var authenticator = new OAuth2Authenticator(
            clientId,
            null,
            Constants.Scope,
            new Uri(Constants.AuthorizeUrl),
            new Uri(redirectUri),
            new Uri(Constants.AccessTokenUrl),
            null,
            true);

        authenticator.Completed += OnAuthCompleted;
        authenticator.Error += OnAuthError;

        AuthenticationState.Authenticator = authenticator;

        var presenter = new Xamarin.Auth.Presenters.OAuthLoginPresenter();
        presenter.Login(authenticator);
    }

The problem is coming after my method complete it's work. So after my last line:


    presenter.Login(authenticator);

everything looks alright and debugging I am following that compiler goes out of method without any errors, but then I receive exception, which you can see here. It's "No compatible code running".

Here some more information regarding my source code:

  • Source of "Constants" class used for client ids and URLs

    public static class Constants
    {
        public static string AppName = "....";

        // OAuth
        // For Google login, configure at https://console.developers.google.com/
        public static string iOSClientId = "6.....apps.googleusercontent.com";
        public static string AndroidClientId = "6.....apps.googleusercontent.com";

        // These values do not need changing
        public static string Scope = "https://www.googleapis.com/auth/userinfo.email";
        public static string AuthorizeUrl = "https://accounts.google.com/o/oauth2/auth";
        public static string AccessTokenUrl = "https://www.googleapis.com/oauth2/v4/token";
        public static string UserInfoUrl = "https://www.googleapis.com/oauth2/v2/userinfo";

        // Set these to reversed iOS/Android client ids, with :/oauth2redirect appended
        public static string iOSRedirectUrl = "com.googleusercontent.apps.6......h:/oauth2redirect";
        public static string AndroidRedirectUrl = "com.googleusercontent.apps.6......l:/oauth2redirect";
    }

  • Source of implemented methods for on authentication complete/error, which in fact still I cannot hit because of my error
 

    async void OnAuthCompleted(object sender, AuthenticatorCompletedEventArgs e)
    {
        var authenticator = sender as OAuth2Authenticator;
        if (authenticator != null)
        {
            authenticator.Completed -= OnAuthCompleted;
            authenticator.Error -= OnAuthError;
        }

        GoogleLoginUser user = null;
        if (e.IsAuthenticated)
        {
            var request = new OAuth2Request("GET", new Uri(Constants.UserInfoUrl), null, e.Account);
            var response = await request.GetResponseAsync();
            if (response != null)
            {
                string userJson = await response.GetResponseTextAsync();
                user = JsonConvert.DeserializeObject(userJson);
            }

            if (_account != null)
            {
                _store.Delete(_account, Constants.AppName);
            }

            await _store.SaveAsync(_account = e.Account, Constants.AppName);
            await DisplayAlert("Email address", user.Email, "OK");
        }
    }

    void OnAuthError(object sender, AuthenticatorErrorEventArgs e)
    {
        var authenticator = sender as OAuth2Authenticator;
        if (authenticator != null)
        {
            authenticator.Completed -= OnAuthCompleted;
            authenticator.Error -= OnAuthError;
        }

        var message = e.Message;
    }

  • Source of Android MainActivity where I added

    public class MainActivity : FormsAppCompatActivity
    {
        protected override void OnCreate(Bundle bundle)
        {
            TabLayoutResource = Resource.Layout.Tabbar;
            ToolbarResource = Resource.Layout.Toolbar;

            base.OnCreate(bundle);

            Forms.Init(this, bundle);
            global::Xamarin.Auth.Presenters.XamarinAndroid.AuthenticationConfiguration.Init(this, bundle);

            MobileBarcodeScanner.Initialize(Application);

            LoadApplication(new App());
        }
    }

  • Source of UrlSchemeInterceptorActivity

    [Activity(Label = "CustomUrlSchemeInterceptorActivity", NoHistory = true, LaunchMode = LaunchMode.SingleTop)]
    [IntentFilter(new[] { Intent.ActionView }, Categories = new[] { Intent.CategoryDefault, Intent.CategoryBrowsable }, DataSchemes = new[] { "com.googleusercontent.apps.6......l" }, DataPath = "/oauth2redirect")]
    public class CustomUrlSchemeInterceptorActivity : Activity
    {
        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);

            var uri = new Uri(Intent.Data.ToString());

            AuthenticationState.Authenticator.OnPageLoading(uri);

            Finish();
        }
    }

Here are the main articles I went through deeply => Link 1, Link 2 and Link 3, but still couldn't resolve the issue.

I am not sure where the error comes from, or can I can I continue debugging it to resolve issue.

Thanks in advance

Solution

  1. Change android compiler to Android 7.0 inside Android project properties. Screenshot
  2. Make sure that inside Android Manifest your target is SDK Version. Screenshot
  3. Update all "Xamarin.Android.*" nuget packages to minimum version 25.4.0.1. Most probably they're currently to 23.3.0. I found problems with dependencies on updating it, so I make manual upload. I went and download manually each package and move it to packages folder. Then I created my own package source and give for path my folder packages and I used it to install already downloaded NuGet packages. Screenshot
  4. After that my issue was solved.
1
Please do not include source code as an image. Still less a linked image. Source code should be included as text for search- and radability.Paul Kertscher

1 Answers

0
votes

Please update your Android SDK to API 24 or higher and set it as the compile version for your project. And update your referred assemblies for the custom tabs and its dependencies to v25.x.x. Thats it. You should be able to get it working.

Vijay.