Connecting to Google Leaderboards Using Xamarin. [Solution]

shanesepacshanesepac USMember ✭✭
edited June 2015 in CocosSharp

Hi guys,

I've been working on this for a very very long time (40+ hours. yes, that is more than a full work week) and finally got this to work.

The problem was changing the launch mode from Launchmode.SingleInstance to Launchmode.Multiple. I'll try to explain what was happening.

When you try to connect to Google leaderboards, OnConnectionFailed() will be called because you are not signed in. StartResolutionForResult() will then get called which will attempt to sign you in. StartResolutionForResult will call OnActivityResult() when finished; however, since you were in SingleInstance mode, the sign in gets cancelled and an error is returned. This issue directly pertains to all people using CocosSharp, and I am very disappointed at how incredibly difficult it was to find any guidance on how to connect to the leaderboards.

Other problems you could be having:

Follow the guidelines on how to enable the APIs for you app. It is extremely important you're using the correct SHA-1 key. Do so in the android developer consolse under game services, not inside "credentials" in console.developers.google.com.

In the manifest, do not include a numerical value inside your meta tag that references your app id. It is looking for a string, so put the string named app_id inside a strings.xml which contains your app_id provided in the developers console.

Follow the google guides on (1) integrating google sign-in and then (2) implementing google sign-in.

Here is my code for those needing help connecting:

{
[Activity (
Label = "xxxxxxx",
AlwaysRetainTaskState = true,
Icon = "@drawable/icon",
Theme = "@android:style/Theme.NoTitleBar",
ScreenOrientation = ScreenOrientation.Landscape | ScreenOrientation.ReverseLandscape,
LaunchMode = LaunchMode.Multiple,
MainLauncher = true,
ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize | ConfigChanges.Keyboard | ConfigChanges.KeyboardHidden)
]
public class MainActivity : AndroidGameActivity, IGoogleApiClientConnectionCallbacks, IGoogleApiClientOnConnectionFailedListener
{

  public static IGoogleApiClient googleapiclient;
  public static bool connectionBool;
  private static int RC_SIGN_IN = 9001;
  private bool mResolvingConnectionFailure;
  private bool mAutoStartSignInflow;
  public static bool mSignInClicked;

  protected override void OnCreate (Bundle bundle)
  {
      base.OnCreate (bundle);



      mSignInClicked = true;
      mAutoStartSignInflow = true;
      mResolvingConnectionFailure = false;
      googleapiclient = new GoogleApiClientBuilder (this,this,this)
          .AddApi(GamesClass.Api)
          .AddApi(PlusClass.Api)
          .AddScope(PlusClass.ScopePlusLogin)
          .AddScope(PlusClass.ScopePlusProfile)
          .AddScope(GamesClass.ScopeGames)
          .Build ();


      var application = new CCApplication ();
      application.ApplicationDelegate = new GameAppDelegate ();
          
      SignInButton button = new SignInButton(this);
      SetContentView (application.AndroidContentView);
      application.StartGame ();
  }

  override protected void OnStart(){
      base.OnStart ();
  
      googleapiclient.Connect ();
      //helper.onStart (this);

  }
  override protected void OnStop(){
      base.OnStop ();
      googleapiclient.Disconnect ();
      //helper.onStop ();
  }

  public void OnConnected(Bundle connectionHint){
      Log.Info ("NICE!", "Client connected.");
      connectionBool = true;
  } 



  public void OnConnectionSuspended(int i){
      googleapiclient.Connect ();
  }
  public void OnConnectionFailed(ConnectionResult conResult){

      if (mResolvingConnectionFailure) {
          return;
      }
      if (mSignInClicked || mAutoStartSignInflow) {
          mAutoStartSignInflow = false;
          mSignInClicked = false;
          mResolvingConnectionFailure = true;
      }
      if (resolveConnectionFailure (this, googleapiclient, conResult, RC_SIGN_IN,"There was an issue with signin. Please try again later.")) {
          mResolvingConnectionFailure = false;
      }
  }
  public static bool resolveConnectionFailure(Activity activity,
      IGoogleApiClient client, ConnectionResult result, int requestCode,
      String fallbackErrorMessage) {

      if (result.HasResolution) {
          try {
              result.StartResolutionForResult(activity, requestCode);
              return true;
          } catch (IntentSender.SendIntentException e) {
              // The intent was canceled before it was sent.  Return to the default
              // state and attempt to connect to get an updated ConnectionResult.
              e.PrintStackTrace();
              client.Connect();
              return false;
          }
      } else {
          // not resolvable... so show an error message
          int errorCode = result.ErrorCode;
          Dialog dialog = GooglePlayServicesUtil.GetErrorDialog(errorCode,
              activity, requestCode);
          if (dialog != null) {
              dialog.Show();
          } else {
              // no built-in dialog: show the fallback error message
              showAlert(activity, fallbackErrorMessage);
          }
          return false;
      }
  } 
  public static void showAlert(Activity activity, String message) {
      (new AlertDialog.Builder (activity)).SetMessage (message).SetNeutralButton (17039370,(Android.Content.IDialogInterfaceOnClickListener)null).Create ().Show (); //17039370 is android.r.string.ok.
  }                                                                                               //probably not gonna work
  override protected void OnActivityResult(int requestCode, Result resultCode, Intent intent){
      if (requestCode == RC_SIGN_IN) {
          mSignInClicked = false;
          mResolvingConnectionFailure = false;
          if (resultCode == Result.Ok) {
              googleapiclient.Connect ();
          } else {
              Log.Error("Error", "Unable to sign in");
          }
      }
  }

}
}

Posts

  • RamiTabbaraRamiTabbara AUMember, Xamarin Team Xamurai

    Hi Shane,

    Thanks very much for making this solution publicly available. I'm sure many other developers out there will appreciate it.

  • @shanesepac
    Thank you VERY much!
    I've been stuck on this problem for hours now and finally found this solution. This should be pinned somewhere on both Xamarin Forums and Monogame/CocosSharp Forums!

  • Ron999Ron999 USMember ✭✭

    @shanesepac Hey, This is great info. Can this code be used in a Xamarin Forms Portable Class Library? I am new to C# and Xamarin and have been struggling to get my game connected.
    Any advice on where to put this code in my project would be much appreciated. (In the PCL or in the Android code?)
    Thanks very much!
    Ron

Sign In or Register to comment.