-
-
Save Krumelur/842f7aed2becde403fbb77e80322d265 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using Android.Gms.Common; | |
using Android.Gms.Common.Apis; | |
using Android.Gms.Games.Achievement; | |
using Android.Gms.Games.LeaderBoard; | |
using Android.Gms.Games; | |
using Android.App; | |
using Android.Content; | |
using Android.Views; | |
using Java.Interop; | |
using System.Collections.Generic; | |
namespace GooglePlay.Services.Helpers | |
{ | |
/// <summary> | |
/// Basic wrapper for interfacing with the GooglePlayServices Game API's | |
/// </summary> | |
public class GameHelper: Java.Lang.Object, GoogleApiClient.IConnectionCallbacks, GoogleApiClient.IOnConnectionFailedListener | |
{ | |
GoogleApiClient client; | |
Activity activity; | |
bool signedOut = true; | |
bool signingin = false; | |
bool resolving = false; | |
List<IAchievement> achievments = new List<IAchievement>(); | |
Dictionary<string, List<ILeaderboardScore>> scores = new Dictionary<string, List<ILeaderboardScore>> (); | |
AchievementsCallback achievmentsCallback; | |
LeaderBoardsCallback leaderboardsCallback; | |
const int REQUEST_LEADERBOARD = 9002; | |
const int REQUEST_ALL_LEADERBOARDS = 9003; | |
const int REQUEST_ACHIEVEMENTS = 9004; | |
const int RC_RESOLVE = 9001; | |
/// <summary> | |
/// Gets or sets a value indicating whether the user is signed out or not. | |
/// </summary> | |
/// <value><c>true</c> if signed out; otherwise, <c>false</c>.</value> | |
public bool SignedOut { | |
get { return signedOut; } | |
set { | |
if (signedOut != value) { | |
signedOut = value; | |
// Store if we Signed Out so we don't bug the player next time. | |
using (var settings = this.activity.GetSharedPreferences ("googleplayservicessettings", FileCreationMode.Private)) { | |
using (var e = settings.Edit ()) { | |
e.PutBoolean ("SignedOut", signedOut); | |
e.Commit (); | |
} | |
} | |
} | |
} | |
} | |
/// <summary> | |
/// Gets or sets the gravity for the GooglePlay Popups. | |
/// Defaults to Bottom|Center | |
/// </summary> | |
/// <value>The gravity for popups.</value> | |
public GravityFlags GravityForPopups { get; set; } | |
/// <summary> | |
/// The View on which the Popups should show | |
/// </summary> | |
/// <value>The view for popups.</value> | |
public View ViewForPopups {get;set;} | |
/// <summary> | |
/// This event is fired when a user successfully signs in | |
/// </summary> | |
public event EventHandler OnSignedIn; | |
/// <summary> | |
/// This event is fired when the Sign in fails for any reason | |
/// </summary> | |
public event EventHandler OnSignInFailed; | |
/// <summary> | |
/// This event is fired when the user Signs out | |
/// </summary> | |
public event EventHandler OnSignedOut; | |
/// <summary> | |
/// List of Achievements. Populated by LoadAchievements | |
/// </summary> | |
/// <value>The achievements.</value> | |
public List<IAchievement> Achievements { | |
get { return achievments; } | |
} | |
public GameHelper (Activity activity) | |
{ | |
this.activity = activity; | |
this.GravityForPopups = GravityFlags.Bottom | GravityFlags.Center; | |
achievmentsCallback = new AchievementsCallback (this); | |
leaderboardsCallback = new LeaderBoardsCallback (this); | |
} | |
public void Initialize() { | |
var settings = this.activity.GetSharedPreferences ("googleplayservicessettings", FileCreationMode.Private); | |
signedOut = settings.GetBoolean ("SignedOut", true); | |
if (!signedOut) | |
CreateClient (); | |
} | |
private void CreateClient() { | |
// did we log in with a player id already? If so we don't want to ask which account to use | |
var settings = this.activity.GetSharedPreferences ("googleplayservicessettings", FileCreationMode.Private); | |
var id = settings.GetString ("playerid", String.Empty); | |
var builder = new GoogleApiClient.Builder (activity, this, this); | |
builder.AddApi (Android.Gms.Games.GamesClass.Api); | |
builder.AddScope (Android.Gms.Games.GamesClass.ScopeGames); | |
builder.SetGravityForPopups ((int)GravityForPopups); | |
if (ViewForPopups != null) | |
builder.SetViewForPopups (ViewForPopups); | |
if (!string.IsNullOrEmpty (id)) { | |
builder.SetAccountName (id); | |
} | |
client = builder.Build (); | |
} | |
/// <summary> | |
/// Start the GooglePlayClient. This should be called from your Activity Start | |
/// </summary> | |
public void Start() { | |
if(SignedOut && !signingin) | |
return; | |
if (client != null && !client.IsConnected) { | |
client.Connect (); | |
} | |
} | |
/// <summary> | |
/// Disconnects from the GooglePlayClient. This should be called from your Activity Stop | |
/// </summary> | |
public void Stop() { | |
if (client != null && client.IsConnected) { | |
client.Disconnect (); | |
} | |
} | |
/// <summary> | |
/// Reconnect to google play. | |
/// </summary> | |
public void Reconnect() { | |
if (client != null) | |
client.Reconnect (); | |
} | |
/// <summary> | |
/// Sign out of Google Play and make sure we don't try to auto sign in on the next startup | |
/// </summary> | |
public void SignOut() { | |
SignedOut = true; | |
if (client.IsConnected) { | |
GamesClass.SignOut (client); | |
Stop (); | |
using (var settings = this.activity.GetSharedPreferences ("googleplayservicessettings", FileCreationMode.Private)) { | |
using (var e = settings.Edit ()) { | |
e.PutString ("playerid",String.Empty); | |
e.Commit (); | |
} | |
} | |
client.Dispose (); | |
client = null; | |
if (OnSignedOut != null) | |
OnSignedOut (this, EventArgs.Empty); | |
} | |
} | |
/// <summary> | |
/// Attempt to Sign in to Google Play | |
/// </summary> | |
public void SignIn() { | |
signingin = true; | |
if (client == null) | |
CreateClient (); | |
if (client.IsConnected) | |
return; | |
if (client.IsConnecting) | |
return; | |
var result = GooglePlayServicesUtil.IsGooglePlayServicesAvailable (activity); | |
if (result != ConnectionResult.Success) { | |
return; | |
} | |
Start (); | |
} | |
/// <summary> | |
/// Unlocks the achievement. | |
/// </summary> | |
/// <param name="achievementCode">Achievement code from you applications Google Play Game Services Achievements Page</param> | |
public void UnlockAchievement(string achievementCode) { | |
GamesClass.Achievements.Unlock (client, achievementCode); | |
} | |
public void IncrementAchievement(string achievementCode, int progress) { | |
GamesClass.Achievements.Increment (client, achievementCode, progress); | |
} | |
/// <summary> | |
/// Show the built in google Achievements Activity. This will cause your application to go into a Paused State | |
/// </summary> | |
public void ShowAchievements() { | |
var intent = GamesClass.Achievements.GetAchievementsIntent (client); | |
activity.StartActivityForResult (intent, REQUEST_ACHIEVEMENTS); | |
} | |
/// <summary> | |
/// Submit a score to google play. The score will only be updated if it is greater than the existing score. | |
/// This is not immediate but will occur at the next sync of the google play client. | |
/// </summary> | |
/// <param name="leaderboardCode">Leaderboard code from you applications Google Play Game Services Leaderboards Page</param> | |
/// <param name="value">The value of the score</param> | |
public void SubmitScore(string leaderboardCode, long value) { | |
GamesClass.Leaderboards.SubmitScore (client, leaderboardCode, value); | |
} | |
/// <summary> | |
/// Submit a score to google play. The score will only be updated if it is greater than the existing score. | |
/// This is not immediate but will occur at the next sync of the google play client. | |
/// </summary> | |
/// <param name="leaderboardCode">Leaderboard code from you applications Google Play Game Services Leaderboards Page</param> | |
/// <param name="value">The value of the score</param> | |
/// <param name="value">Additional MetaData to attach. Must be a URI safe string with a max length of 64 characters</param> | |
public void SubmitScore(string leaderboardCode, long value, string metadata) { | |
GamesClass.Leaderboards.SubmitScore (client, leaderboardCode, value, metadata); | |
} | |
/// <summary> | |
/// Show the built in leaderboard activity for the leaderboard code. | |
/// </summary> | |
/// <param name="leaderboardCode">Leaderboard code from you applications Google Play Game Services Leaderboards Page</param> | |
public void ShowLeaderBoardIntentForLeaderboard(string leaderboardCode) { | |
var intent = GamesClass.Leaderboards.GetLeaderboardIntent (client, leaderboardCode); | |
activity.StartActivityForResult (intent, REQUEST_LEADERBOARD); | |
} | |
/// <summary> | |
/// Show the built in leaderboard activity for all the leaderboards setup for your application | |
/// </summary> | |
public void ShowAllLeaderBoardsIntent() { | |
var intent = GamesClass.Leaderboards.GetAllLeaderboardsIntent (client); | |
activity.StartActivityForResult (intent, REQUEST_ALL_LEADERBOARDS); | |
} | |
/// <summary> | |
/// Load the Achievments. This populates the Achievements property | |
/// </summary> | |
public void LoadAchievements() { | |
var pendingResult = GamesClass.Achievements.Load (client, false); | |
pendingResult.SetResultCallback (achievmentsCallback); | |
} | |
public void LoadTopScores(string leaderboardCode) { | |
var pendingResult = GamesClass.Leaderboards.LoadTopScores (client, leaderboardCode, 2, 0, 25); | |
pendingResult.SetResultCallback (leaderboardsCallback); | |
} | |
#region IGoogleApiClientConnectionCallbacks implementation | |
public void OnConnected (Android.OS.Bundle connectionHint) | |
{ | |
resolving = false; | |
SignedOut = false; | |
signingin = false; | |
using (var settings = this.activity.GetSharedPreferences ("googleplayservicessettings", FileCreationMode.Private)) { | |
using (var e = settings.Edit ()) { | |
e.PutString ("playerid",GamesClass.GetCurrentAccountName(client)); | |
e.Commit (); | |
} | |
} | |
if (OnSignedIn != null) | |
OnSignedIn (this, EventArgs.Empty); | |
} | |
public void OnConnectionSuspended (int resultCode) | |
{ | |
resolving = false; | |
SignedOut = false; | |
signingin = false; | |
client.Disconnect (); | |
if (OnSignInFailed != null) | |
OnSignInFailed (this, EventArgs.Empty); | |
} | |
public void OnConnectionFailed (ConnectionResult result) | |
{ | |
if (resolving) | |
return; | |
if (result.HasResolution) { | |
resolving = true; | |
result.StartResolutionForResult (activity, RC_RESOLVE); | |
return; | |
} | |
resolving = false; | |
SignedOut = false; | |
signingin = false; | |
if (OnSignInFailed != null) | |
OnSignInFailed (this, EventArgs.Empty); | |
} | |
#endregion | |
/// <summary> | |
/// Processes the Activity Results from the Signin process. MUST be called from your activity OnActivityResult override. | |
/// </summary> | |
/// <param name="requestCode">Request code.</param> | |
/// <param name="resultCode">Result code.</param> | |
/// <param name="data">Data.</param> | |
public void OnActivityResult (int requestCode, Result resultCode, Intent data) { | |
if (requestCode == RC_RESOLVE) { | |
if (resultCode == Result.Ok) { | |
Start (); | |
} else { | |
if (OnSignInFailed != null) | |
OnSignInFailed (this, EventArgs.Empty); | |
} | |
} | |
} | |
internal class AchievementsCallback : Java.Lang.Object, IResultCallback { | |
GameHelper helper; | |
public AchievementsCallback (GameHelper helper): base() | |
{ | |
this.helper = helper; | |
} | |
#region IResultCallback implementation | |
public void OnResult (Java.Lang.Object result) | |
{ | |
var ar = result.JavaCast<IAchievementsLoadAchievementsResult>(); | |
if (ar != null) { | |
helper.achievments.Clear (); | |
var count = ar.Achievements.Count; | |
for (int i = 0; i < count; i++) { | |
var item = ar.Achievements.Get (i); | |
var a = item.JavaCast<IAchievement> (); | |
helper.achievments.Add (a); | |
} | |
} | |
} | |
#endregion | |
} | |
internal class LeaderBoardsCallback : Java.Lang.Object, IResultCallback { | |
GameHelper helper; | |
public LeaderBoardsCallback (GameHelper helper): base() | |
{ | |
this.helper = helper; | |
} | |
#region IResultCallback implementation | |
public void OnResult (Java.Lang.Object result) | |
{ | |
var ar = result.JavaCast<ILeaderboardsLoadScoresResult>(); | |
if (ar != null) { | |
var id = ar.Leaderboard.LeaderboardId; | |
if (!helper.scores.ContainsKey (id)) { | |
helper.scores.Add (id, new List<ILeaderboardScore> ()); | |
} | |
helper.scores [id].Clear (); | |
var count = ar.Scores.Count; | |
for (int i = 0; i < count; i++) { | |
var score = ar.Scores.Get(i).JavaCast<ILeaderboardScore> (); | |
helper.scores [id].Add (score); | |
} | |
} | |
} | |
#endregion | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using TowerOffense.Resources; | |
#if __IOS__ || __TVOS__ | |
using UIKit; | |
using Foundation; | |
using GameKit; | |
#endif | |
#if __ANDROID__ | |
using TowerOffense.Droid; | |
#endif | |
namespace TowerOffense | |
{ | |
public static class GameServices | |
{ | |
public enum ACHIEVEMENTS | |
{ | |
UnlockDarkKnight, | |
UnlockSkeleton, | |
EpicFail, | |
FiveInARow, | |
TenInARow, | |
BatMan, | |
LifeSaver, | |
SlimeEvader | |
} | |
public static void AuthenticateGameService () | |
{ | |
#if __IOS__ || __TVOS__ | |
var localPlayer = GKLocalPlayer.LocalPlayer; | |
if (localPlayer.Authenticated) | |
{ | |
Util.Log ("Player already authenticated."); | |
return; | |
} | |
// If we have a game center authentication controller, show it. | |
if (localPlayer.AuthenticateHandler != null) | |
{ | |
Util.Log ("GameCenter authentication handler already set."); | |
return; | |
} | |
// Assign an authentication handler. | |
localPlayer.AuthenticateHandler = AppleGameCenterAuthenticationHandler; | |
#elif __FIRETV__ | |
// TODO: FireTV | |
#elif __ANDROID__ | |
try | |
{ | |
MainActivity.Instance.GameHelper.SignIn (); | |
} | |
catch(Exception ex) | |
{ | |
Util.Log("Failed to sign in: {0}", ex); | |
Tracking.Report(ex, true); | |
} | |
#endif | |
} | |
public static void SignOut () | |
{ | |
#if __IOS__ || __TVOS__ | |
// NOP | |
#elif __FIRETV__ | |
// TODO: FireTV | |
#elif __ANDROID__ | |
try | |
{ | |
MainActivity.Instance.GameHelper.SignOut(); | |
} | |
catch(Exception ex) | |
{ | |
Util.Log("Failed to sign out: {0}", ex); | |
Tracking.Report(ex, true); | |
} | |
#endif | |
} | |
#if __IOS__ || __TVOS__ | |
private async static void AppleGameCenterAuthenticationHandler (UIViewController controller, NSError error) | |
{ | |
if (error != null) | |
{ | |
Util.Log ("Error authenticating GameCenter: {0}", error); | |
Tracking.Track ("Error authenticating GameCenter", new Dictionary<string, string> { | |
{ "Error", error.ToString () } | |
}); | |
} | |
if (controller != null) | |
{ | |
Util.Log ("Got game center view controller."); | |
try | |
{ | |
UIApplication.SharedApplication.Windows [0].RootViewController.PresentViewController (controller, true, null); | |
} | |
catch (Exception ex) | |
{ | |
Util.Log ("Presenting GameCenter controller failed: {0}", ex); | |
Tracking.Report (ex, true); | |
} | |
} | |
else | |
{ | |
if (GKLocalPlayer.LocalPlayer.Authenticated) | |
{ | |
Util.Log ("Player is authenticated in Game Center"); | |
try | |
{ | |
await GKLocalPlayer.LocalPlayer.SetDefaultLeaderboardIdentifierAsync ("net.csharx.sirlanceandhop.highscores"); | |
} | |
catch (Exception ex) | |
{ | |
Util.Log ("Setting default leaderbord ID failed: {0}", ex); | |
Tracking.Report (ex, true); | |
} | |
} | |
else | |
{ | |
Util.Log ("Player is not authenticated in Game Center"); | |
} | |
} | |
} | |
#endif | |
public static void ReportAchievement (ACHIEVEMENTS achievement) | |
{ | |
#if __IOS__ || __TVOS__ | |
string achievementId = "net.csharx.sirlanceandhop." + achievement.ToString ().ToLower (); | |
try | |
{ | |
Util.Log ("Reporting achievement {0}", achievementId); | |
var reportAchievement = new GKAchievement (achievementId) { | |
ShowsCompletionBanner = false, | |
PercentComplete = 100f | |
}; | |
GKAchievement.ReportAchievements (new GKAchievement[] { reportAchievement }, error => { | |
if (error != null) | |
{ | |
Util.Log ("Submitting achievement failed with error: {0}", error); | |
Tracking.Track ("Reporting achievement failed", new Dictionary<string, string> () { | |
{ "Error", error.ToString () }, | |
}); | |
} | |
}); | |
} | |
catch (Exception ex) | |
{ | |
Util.Log ("Submitting achievement failed: {0}", ex); | |
Tracking.Report (ex, new Dictionary<string, string> () { | |
{ "Achievement", achievement.ToString () }, | |
{ "ID", achievementId }, | |
}, true); | |
} | |
#elif __FIRETV__ | |
// TODO: FireTV | |
#elif __ANDROID__ | |
int achievementId = -1; | |
string achievementCode = null; | |
switch(achievement) | |
{ | |
case ACHIEVEMENTS.BatMan: | |
achievementId = TowerOffense.Droid.Resource.String.achievement_batman; | |
break; | |
case ACHIEVEMENTS.EpicFail: | |
achievementId = TowerOffense.Droid.Resource.String.achievement_epic_fail; | |
break; | |
case ACHIEVEMENTS.LifeSaver: | |
achievementId = TowerOffense.Droid.Resource.String.achievement_lifesaver; | |
break; | |
case ACHIEVEMENTS.SlimeEvader: | |
achievementId = TowerOffense.Droid.Resource.String.achievement_slime_evader; | |
break; | |
case ACHIEVEMENTS.TenInARow: | |
achievementId = TowerOffense.Droid.Resource.String.achievement_ten_in_a_row; | |
break; | |
case ACHIEVEMENTS.UnlockDarkKnight: | |
achievementId = TowerOffense.Droid.Resource.String.achievement_unlock_first_bonus_character; | |
break; | |
case ACHIEVEMENTS.UnlockSkeleton: | |
achievementId = TowerOffense.Droid.Resource.String.achievement_unlock_second_bonus_character; | |
break; | |
default: | |
Util.Log("Achievement '{0}' not found.", achievement); | |
return; | |
} | |
try | |
{ | |
achievementCode = MainActivity.Instance.GetString(achievementId); | |
MainActivity.Instance.GameHelper.UnlockAchievement(achievementCode); | |
} | |
catch(Exception ex) | |
{ | |
Util.Log("Unlocking achievement '{0}' failed (achievement ID: '{1}'): {2}", achievement, achievementCode, ex); | |
Tracking.Report(ex, new Dictionary<string, string>() { | |
{"Achievement", achievement.ToString()}, | |
{"ID", achievementCode.ToString()} | |
}, true); | |
} | |
#endif | |
} | |
public static void ReportGameServiceScore (int score, int level) | |
{ | |
#if __IOS__ || __TVOS__ | |
var gkScorePoints = new GKScore ("net.csharx.sirlanceandhop.highscores") { | |
Value = score | |
}; | |
var gkScoreLevel = new GKScore ("net.csharx.sirlanceandhop.level") { | |
Value = level | |
}; | |
try | |
{ | |
GKScore.ReportScores (new GKScore[] { gkScorePoints, gkScoreLevel }, error => { | |
if (error != null) | |
{ | |
Util.Log ("Submitting scores failed with error: {0}", error); | |
Tracking.Track ("Reporting score failed", new Dictionary<string, string> () { | |
{ "Error", error.ToString () }, | |
}); | |
} | |
}); | |
} | |
catch (Exception ex) | |
{ | |
Util.Log ("Submitting scores failed: {0}", ex); | |
Tracking.Report (ex, new Dictionary<string, string> () { | |
{ "Score", score.ToString () }, | |
{ "Level", level.ToString () } | |
}, true); | |
} | |
#elif __FIRETV__ | |
// TODO: FireTV | |
#elif __ANDROID__ | |
string scoreCode = MainActivity.Instance.GetString(TowerOffense.Droid.Resource.String.leaderboard_score); | |
try | |
{ | |
MainActivity.Instance.GameHelper.SubmitScore (scoreCode, score); | |
} | |
catch(Exception ex) | |
{ | |
Util.Log("Submitting scores failed: {0}", ex); | |
Tracking.Report(ex, new Dictionary<string, string>() { | |
{"Score", score.ToString()}, | |
{"Level", level.ToString()}, | |
{"ID", scoreCode } | |
}, true); | |
} | |
string levelCode = MainActivity.Instance.GetString(TowerOffense.Droid.Resource.String.leaderboard_level); | |
try | |
{ | |
MainActivity.Instance.GameHelper.SubmitScore (levelCode, level); | |
} | |
catch(Exception ex) | |
{ | |
Util.Log("Submitting level failed: {0}", ex); | |
Tracking.Report(ex, new Dictionary<string, string>() { | |
{"Score", score.ToString()}, | |
{"Level", level.ToString()}, | |
{"ID", levelCode } | |
}, true); | |
} | |
#endif | |
} | |
public static void ShowLeaderboards () | |
{ | |
#if __IOS__ || __TVOS__ | |
// If game center cannot be used, we cannot show records. | |
if (!GKLocalPlayer.LocalPlayer.Authenticated) | |
{ | |
UI.ShowMessageBox (Strings.GameCenterLoginFailed, Strings.OK); | |
return; | |
} | |
var leaderboardController = new GKGameCenterViewController (); | |
// Unavailable on tvOS | |
#if __IOS__ | |
leaderboardController.ViewState = GKGameCenterViewControllerState.Default; | |
leaderboardController.LeaderboardIdentifier = "net.csharx.sirlanceandhop.highscores"; | |
#endif | |
leaderboardController.Finished += (sender, e) => leaderboardController.DismissViewController (true, null); | |
UIApplication.SharedApplication.Windows [0].RootViewController.PresentViewController (leaderboardController, true, null); | |
#elif __FIRETV__ | |
// TODO: FireTV | |
#elif __ANDROID__ | |
try | |
{ | |
if(MainActivity.Instance.GameHelper.SignedOut) | |
{ | |
UI.ShowMessageBox(Strings.GooglePlayGamesRequired, Strings.OK); | |
return; | |
} | |
MainActivity.Instance.GameHelper.ShowAllLeaderBoardsIntent (); | |
} | |
catch(Exception ex) | |
{ | |
Util.Log("Showing leaderboards failed: {0}", ex); | |
Tracking.Report(ex, true); | |
} | |
#endif | |
} | |
public static void ShowAchievements () | |
{ | |
#if __IOS__ || __TVOS__ | |
// Not required on iOS. Achievements can be reached from the records screen. | |
#elif __FIRETV__ | |
// TODO: FireTV | |
#elif __ANDROID__ | |
try | |
{ | |
if(MainActivity.Instance.GameHelper.SignedOut) | |
{ | |
UI.ShowMessageBox(Strings.GooglePlayGamesRequired, Strings.OK); | |
return; | |
} | |
MainActivity.Instance.GameHelper.ShowAchievements(); | |
} | |
catch(Exception ex) | |
{ | |
Util.Log("Showing achievements failed: {0}", ex); | |
Tracking.Report(ex, true); | |
} | |
#endif | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment