אם המשחק משתמש בשרת עורפי, מומלץ להשתמש בכניסה באמצעות חשבון Google כדי לאמת את השחקנים ולהעביר את זהותו באופן מאובטח לשרת הקצה העורפי. כך המשחק יכול לאחזר באופן מאובטח את הזהות של השחקן ונתונים אחרים, בלי להיות חשוף לזיופים פוטנציאליים במהלך המעבר במכשיר.
בתרחיש הזה, המשחק יעודד את השחקן להיכנס לשירותי Google Play Games כרגיל. כשהנגן נכנס בהצלחה, האובייקט GoogleSignInAccount
מכיל קוד מיוחד לשימוש חד-פעמי (שנקרא קוד ההרשאה של השרת) שהלקוח מעביר לשרת. לאחר מכן, בשרת, מחליפים את קוד האימות של השרת באסימון OAuth 2.0, שבו השרת יכול להשתמש כדי לבצע קריאות ל-Google Play Games Services API.
לקבלת הנחיות נוספות על הוספת כניסה למשחקים, קראו את המאמר כניסה למשחקים ל-Android.
כדי לראות דוגמת קוד מפורטת שמראה איך להשתמש ב'כניסה באמצעות חשבון Google' כדי לאמת נגנים, ראו דוגמה של clientserverskeleton
ב-GitHub.
כדי לגשת לנתונים במצב אופליין, צריך לבצע את השלבים הבאים:
- ב-Google Play Console: יוצרים פרטי כניסה לשרת המשחק. הסוג של פרטי הכניסה בצד הלקוח ב-OAuth יהיה 'web'.
- באפליקציה ל-Android: כחלק מהכניסה, מבקשים קוד אימות לשרת עבור פרטי הכניסה של השרת ומעבירים אותו לשרת.
- בשרת המשחק: מחליפים את קוד האימות של השרת באסימון גישה ל-OAuth באמצעות שירותי האימות של Google, ולאחר מכן משתמשים בו כדי לבצע קריאה לממשקי ה-API ל-REST של Play Games Services.
לפני שמתחילים
לפני שתוכלו לשלב את הכניסה באמצעות חשבון Google במשחק, תחילה תצטרכו להוסיף את המשחק ל-Google Play Console, כפי שמתואר במאמר הגדרת שירותי Google Play Games.
יצירת אפליקציית אינטרנט משויכת בצד השרת למשחק
שירותי Google Play Games לא מספקים תמיכה לקצה העורפי של משחקים באינטרנט. עם זאת, הוא מספק תמיכה בשרתים לקצה העורפי של השרת של המשחק ל-Android.
כדי להשתמש ב-API בארכיטקטורת REST לשירותי Google Play Games באפליקציה בצד השרת:
- אפשר ליצור אפליקציית אינטרנט משויכת למשחק בקטע אפליקציות מקושרות ב-Google Play Console. הערה: השדה
launch_url
לא משמש בתהליך הזה וניתן להשאיר אותו ריק. - כדי לקבל את פרטי הכניסה של האפליקציה:
- במשחק ב-Google Play Console, לוחצים על פרטי המשחק.
- גוללים למטה לקטע API Console Project ולוחצים על הקישור לפרויקט במסוף ה-API.
- מהמסך APIs & Services > Credentials ב-Google API Console, מורידים את הקובץ
client_secret.json
של אפליקציית האינטרנט ושומרים אותו במיקום שלשרת יש גישה אליו. שומרים את מזהה הלקוח של פרטי הכניסה לשימוש מאוחר יותר.
- מפעילים מחדש את האפליקציה בצד השרת כדי שהיא תהיה מוכנה לקבל בקשות מאפליקציית הלקוח של המשחק.
ביצוע כניסה לחשבון בצד הלקוח
הכיתה GoogleSignInClient
היא נקודת הכניסה הראשית לאחזור החשבון של המשתמש שמחובר כרגע, ולהתחברות של המשתמש אם הוא לא עשה זאת בעבר באפליקציה במכשיר.
כדי ליצור לקוח כניסה:
- יוצרים לקוח לכניסה באמצעות האובייקט
GoogleSignInOptions
. כדי להגדיר את הכניסה, צריך לציין את הערךGoogleSignInOptions.DEFAULT_GAMES_SIGN_IN
ב-GoogleSignInOptions.Builder
. - צריך גם לציין שהמשחק דורש קוד אימות לשרת הקצה העורפי. לשם כך, צריך להפעיל את השיטה
GoogleSignInOptions.Builder.requestServerAuthCode()
עם מזהה הלקוח של השרת כפרמטר. אחזור קוד האימות יתבצע מאוחר יותר, לצורך אסימוני גישה בשרת הקצה העורפי, כפי שמתואר בקטע קבלת קוד האימות של השרת. - קוראים ל-method
GoogleSignIn.getClient()
ומעבירים את האפשרויות שהגדרתם קודם. אם הקריאה תצליח, Google Sign-In API יחזיר מופע שלGoogleSignInClient
. - אחרי שמקבלים את המופע של
GoogleSignInClient
, צריך להמשיך להיכנס לחשבון של הנגן בשקט באמצעותonResume()
של הפעילות, כפי שמתואר בקטע ביצוע כניסה שקטה.
הנה דוגמה:
private static final int RC_SIGN_IN = 9001; private GoogleSignInClient mGoogleSignInClient; private void startSignInForAuthCode() { // Client ID for your backend server. String webClientId = getString(R.string.webclient_id); GoogleSignInOptions signInOption = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN) .requestServerAuthCode(webClientId) .build(); GoogleSignInClient signInClient = GoogleSignIn.getClient(this, signInOption); Intent intent = signInClient.getSignInIntent(); startActivityForResult(intent, RC_SIGN_IN); }
קבלת קוד האימות של השרת
כדי לאחזר קוד אימות שרת שאפשר להשתמש בו במשחק לטוקני גישה בשרת הקצה העורפי, צריך להפעיל את השיטה getServerAuthCode()
באובייקט GoogleSignInAccount
שמוחזר על ידי Google Sign-In לאחר כניסה מוצלחת של משתמש.
הנה דוגמה:
// Auth code to send to backend server. private String mServerAuthCode; @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == RC_SIGN_IN) { GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data); if (result.isSuccess()) { mServerAuthCode = result.getSignInAccount().getServerAuthCode(); } else { String message = result.getStatus().getStatusMessage(); if (message == null || message.isEmpty()) { message = getString(R.string.signin_other_error); } new AlertDialog.Builder(this).setMessage(message) .setNeutralButton(android.R.string.ok, null).show(); } } }
החלפת קוד האימות של השרת באסימון גישה בשרת
שולחים את קוד האימות של השרת לשרת הקצה העורפי כדי להמיר אותו לאסימוני גישה ואסימוני רענון. משתמשים באסימון הגישה כדי לבצע קריאה ל-Google Play Games Services API מטעם השחקן, ואפשר גם לאחסן את אסימון הרענון כדי לקבל אסימון גישה חדש כשפג התוקף של אסימון הגישה.
קטע הקוד הבא מראה איך אפשר ליישם את הקוד בצד השרת בשפת התכנות Java כדי להחליף את קוד האימות של השרת באסימוני גישה. היא משתמשת באפליקציית הדוגמה clientserverskeleton:
/**
* Exchanges the authcode for an access token credential. The credential
* is the associated with the given player.
*
* @param authCode - the non-null authcode passed from the client.
* @param player - the player object which the given authcode is
* associated with.
* @return the HTTP response code indicating the outcome of the exchange.
*/
private int exchangeAuthCode(String authCode, Player player) {
try {
// The client_secret.json file is downloaded from the Google API
// console. This is used to identify your web application. The
// contents of this file should not be shared.
//
File secretFile = new File("client_secret.json");
// If we don't have the file, we can't access any APIs, so return
// an error.
if (!secretFile.exists()) {
log("Secret file : " + secretFile
.getAbsolutePath() + " does not exist!");
return HttpServletResponse.SC_FORBIDDEN;
}
GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(
JacksonFactory.getDefaultInstance(), new
FileReader(secretFile));
// Extract the application id of the game from the client id.
String applicationId = extractApplicationId(clientSecrets
.getDetails().getClientId());
GoogleTokenResponse tokenResponse =
new GoogleAuthorizationCodeTokenRequest(
HTTPTransport,
JacksonFactory.getDefaultInstance(),
"https://oauth2.googleapis.com/token",
clientSecrets.getDetails().getClientId(),
clientSecrets.getDetails().getClientSecret(),
authCode,
"")
.execute();
log("hasRefresh == " + (tokenResponse.getRefreshToken() != null));
log("Exchanging authCode: " + authCode + " for token");
Credential credential = new Credential
.Builder(BearerToken.authorizationHeaderAccessMethod())
.setJsonFactory(JacksonFactory.getDefaultInstance())
.setTransport(HTTPTransport)
.setTokenServerEncodedUrl("https://www.googleapis.com/oauth2/v4/token")
.setClientAuthentication(new HttpExecuteInterceptor() {
@Override
public void intercept(HttpRequest request)
throws IOException {
}
})
.build()
.setFromTokenResponse(tokenResponse);
player.setCredential(credential);
// Now that we have a credential, we can access the Games API.
PlayGamesAPI api = new PlayGamesAPI(player, applicationId,
HTTPTransport, JacksonFactory.getDefaultInstance());
// Call the verify method, which checks that the access token has
// access to the Games API, and that the player id used by the
// client matches the playerId associated with the accessToken.
boolean ok = api.verifyPlayer();
// Call a Games API on the server.
if (ok) {
ok = api.updatePlayerInfo();
if (ok) {
// persist the player.
savePlayer(api.getPlayer());
}
}
return ok ? HttpServletResponse.SC_OK :
HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
} catch (IOException e) {
e.printStackTrace();
}
return HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
}
מידע נוסף על גישה ל-Google APIs משרת לקצה העורפי מטעם שחקן שמחובר לחשבון זמין במאמר הפעלת גישה בצד השרת.
טיפול ביציאה של שחקנים
כדי לנתק את השחקנים מהמשחק, יש להפעיל את השיטה signOut()
ב-GoogleSignInClient
. קטע קוד לדוגמה זמין במאמר יציאה מהחשבון בנגן.
קריאה לממשקי API ל-REST מהשרת
ממשקי API ל-REST לשירותי Google Play Games – תיאור מלא של קריאות ה-API הזמינות.
ריכזנו כאן דוגמאות לקריאות API ל-REST שיכולות להועיל:
שחקן
- רוצים לקבל את המזהה ואת נתוני הפרופיל של השחקן שנכנס לחשבון? קוראים לפונקציה Players.get עם המזהה
'me'
.
חברים
הקפידו לקרוא את המדריך חברים, שכולל הסבר מפורט על 'חברים'.
- רוצים לאחזר את רשימת החברים של השחקן? קוראים לפונקציה Players.list עם הערך
'friends_all'
כ-collection
. - בודקים אם יש לכם גישה לרשימת החברים. קוראים ל-Players.get עבור
me
, ומעיינים בשדהprofileSettings.friendsListVisibility
בתגובה.
הישגים
חשוב לקרוא את המדריך הישגים, שכולל הסבר מפורט על ההישגים.
- רוצה לקבל רשימה של ההישגים הנוכחיים? אפשר לבצע קריאה אל AchievementDefinitions.list.
- אפשר לשלב זאת עם קריאה אל Achievements.list כדי לברר אילו מהשחקנים ביטלו את הנעילה שלהם.
- האם השחקן השיג הישג? אפשר ללחוץ על Achievements.unlock.
- האם השחקן עשה התקדמות לקראת השלמת מטרה חלקית? משתמשים ב-Achievements.increment כדי לדווח על התקדמות (ולגלות אם השחקן ביטל את הנעילה שלו).
- האם אתם מנסים לנפות באגים במשחק שעדיין לא עבר לסביבת הייצור? אפשר לנסות להפעיל את Achievements.reset או את Achievements.resetAll מ-Management APIs כדי לאפס את ההישגים למצב המקורי שלהם.
לוחות לידרבורד
מומלץ לעיין במדריך בנושא לוחות לידרבורד, שבו מוסבר בהרחבה על לוחות לידרבורד.
- רוצים לקבל רשימה של כל לוחות התוצאות במשחק? מריצים את הפונקציה Leaderboards.list.
- האם השחקן סיים משחק? אפשר לשלוח את התוצאה שלהם אל Scores.submit ולבדוק אם זו תוצאה גבוהה חדשה.
- רוצים להציג לידרבורד? מקבלים את הנתונים מ-Scores.list ומציגים אותם למשתמש.
- אפשר להשתמש ב-Scores.listWindow כדי למצוא מבחר של ציונים שקרובים לציון הגבוה של המשתמש.
- כדי לקבל מידע נוסף על הציון של השחקן בלוח מודעות מסוים (לדוגמה, אם השחקן נמצא ב-12% העליונים של כל השחקנים), צריך להפעיל את Scores.get.
- האם אתם מנקים באגים במשחק? אפשר לנסות להפעיל את Scores.reset מ-Management API כדי לאפס את כל הנקודות של השחקן הזה מ-Leaderboard מסוים.