משלבים את PGS Recall API במשחק

בדף הזה מוסבר איך להטמיע את Recall API במשחק. המאמר מתחיל בהסבר על הגדרת שרת המשחקים והלקוח לתמיכה בממשק ה-API, וממשיך להסבר על אחסון אסימונים ואחזור שלהם.

הגדרת שרת משחקים

מגדירים את שרת המשחקים כך שיבצע קריאות ל-Recall API לשרתים של Google.

1. הגדרת פרויקט Play Games Services

(אם עדיין לא עשיתם את זה) פועלים לפי ההוראות במאמר הגדרת Google Play Games Services.

2. הגדרת חשבון שירות למשחק

פועלים לפי ההוראות ליצירת חשבון שירות. בסיום התהליך אמור להיות לכם קובץ JSON עם פרטי הכניסה של חשבון השירות.

3. הורדת ספריית Java בצד השרת עבור PlayGamesServices

מורידים את הספרייה google-api-services-games ומעלים אותה לשרת.

4. הכנת פרטי כניסה לקריאות ל-Recall API

מידע נוסף זמין במאמר הכנה לביצוע קריאה מורשית ל-API.

import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.services.games.Games;
import com.google.api.services.games.GamesScopes;

// ...

GoogleCredential credential =
  GoogleCredential.fromStream(new FileInputStream("<credentials>.json"))
    .createScoped(Collections.singleton(GamesScopes.ANDROIDPUBLISHER));

Games gamesApi =
    new Games.Builder(httpTransport, JSON_FACTORY, credential).build();

הגדרת לקוח משחק

מגדירים את לקוח המשחק כך שיאחזר את מזהי סשן Recall שמשמשים את השרת לתקשורת עם שרתי Google.

Java SDK

מגדירים את Java SDK בלקוח ומוודאים שכוללים את com.google.android.gms:play-services-games-v2:19.0.0 ואת com.google.android.gms:play-services-tasks:18.0.2 ומעלה בקובץ gradle.

כדי לתקשר עם השרתים של Google עם המידע הנכון, צריך לבקש מ-SDK של הלקוח מזהה של סשן Recall ולשלוח אותו לשרת של המשחק.

Kotlin

PlayGames.getRecallClient(getActivity())
                .requestRecallAccess()
                .addOnSuccessListener { recallAccess -> val recallSessionId: String = recallAccess.getSessionId() }
                // Send the recallSessionId to your game server

Java

PlayGames.getRecallClient(getActivity())
  .requestRecallAccess()
  .addOnSuccessListener(
    recallAccess -> {
      String recallSessionId = recallAccess.getSessionId();
      // Send the recallSessionId to your game server
    });

Unity SDK

אם עדיין לא עשיתם זאת, מגדירים את Unity SDK בלקוח.

כדי לתקשר עם השרתים של Google עם המידע הנכון, צריך לבקש מ-SDK של הלקוח מזהה של סשן Recall ולשלוח אותו לשרת של המשחק.

PlayGamesPlatform.Instance.RequestRecallAccess(
    recallAccess => {
        string recallSessionId = recallAccess.sessionId;
        // Send the recallSessionId to your game server
    });

שימוש ב-Recall API בשרת המשחק

אחרי שמגדירים את השרת והלקוח, אפשר לשלוח את recallSessionID מלקוח המשחק לשרת המשחק ולפעול לפי ההנחיות שבהמשך כדי להתחיל להשתמש ב-Java API לאחסון, לאחזור או למחיקה של אסימוני הזיכרון בצד השרת.

אחסון טוקנים

אפשר לאחסן את הפרסונה של המשתמשים ואת הטוקן של המשחק באמצעות האובייקט LinkPersonaRequest. צריך להשתמש ב-GoogleCredential כדי לשלוח קריאה לממשקי API של Google (פרטים נוספים זמינים במאמר שליחת קריאה לממשקי API של Google). חשוב לזכור שבהתאם למגבלת הקרדינליות 1:1, אפשר לקשר רק פרסונה אחת לפרופיל PGS אחד בכל פעם (ולהיפך).כדאי להגדיר את מדיניות ההחלטה למקרה שפרופיל ה-PGS הזה כבר קושר לפרסונה אחרת.

אופציונלי: אפשר להגדיר זמן חיים (TTL) לאסימון, כדי להצהיר כמה זמן האסימון תקף באמצעות אובייקט Durations. אפשר להגדיר את זה באמצעות SetTtl() (כמו בדוגמה שלמטה), שקובע את תאריך התפוגה לפי משך הזמן שצוין בשיטה, או באמצעות setExpireTime(), שמאפשר להגדיר שעה מדויקת שבה האסימונים יפוגו.

חובה להצפין את הטוקן של הדמות ואת הטוקן של המשחק, ואסור שהם יכילו פרטים אישיים מזהים. מחרוזות של פרסונות וטוקנים יכולות להכיל עד 256 תווים, ויכולים להיות עד 20 טוקנים או פרסונות שמאוחסנים לכל שחקן לכל משחק.

בכל רגע נתון, אפשר לאחסן רק טוקן אחד לכל דמות ולכל שחקן. ניסיון לאחסן טוקן אחר עם אותה דמות מוחק את הטוקן המקורי.

import com.google.api.services.games.Games.Recall.LinkPersona;
import com.google.api.services.games.model.LinkPersonaRequest;
import com.google.api.services.games.model.LinkPersonaResponse;
import com.google.protobuf.util.Durations;

// ...

Games gamesApi =
    new Games.Builder(httpTransport, JSON_FACTORY, credential).build();

String recallSessionId = ... // recallSessionID from game client
String persona = ... // encrypted opaque string, stable for in-game account
String token = ... // encrypted opaque string encoding the progress line

LinkPersonaRequest linkPersonaRequest =
  LinkPersonaRequest.newBuilder()
    .setSessionId(recallSessionId)
    .setPersona(persona)
    .setToken(token)
    .setCardinalityConstraint(ONE_PERSONA_TO_ONE_PLAYER)
    .setConflictingLinksResolutionPolicy(CREATE_NEW_LINK)
    .setTtl(Durations.fromDays(7)) // Optionally set TTL for token
    .build();

LinkPersonaResponse linkPersonaResponse =
  gamesApi.recall().linkPersona(linkPersonaRequest).execute();

if (linkPersonaResponse.getState() == LINK_CREATED) {
  // success
}

אחזור טוקנים

יש שלוש אפשרויות לאחזור טוקן, בהתאם לצרכים של המשחקים שלכם. אפשר לבקש את הפעולות הבאות:

  • הטוקנים שמשויכים למשחק הנוכחי, כולל טוקנים של שליפת מידע בהיקף המשחק.
  • האסימון האחרון שאוחסן בכל המשחקים שבבעלות חשבון המפתח.
  • בהינתן רשימה של משחקים שנמצאים בבעלות חשבון המפתח, כל אסימוני הביטול שמשויכים לכל משחק.

טוקנים של ריקול בהיקף המשחק

כדי לאחזר את טוקני ההחזרה מהמשחק הנוכחי, צריך לקבל את recallSessionId מהלקוח ולהעביר אותו אל retrieveTokens API:

import com.google.api.services.games.Games;
import com.google.api.services.games.model.RetrievePlayerTokensResponse;
import com.google.api.services.games.model.RecallToken;

// ...

String recallSessionId = ... // recallSessionID from game client

RetrievePlayerTokensResponse retrievePlayerTokensResponse =
  gamesApi.recall().retrieveTokens(recallSessionId).execute();

for (RecallToken recallToken : retrievePlayerTokensResponse.getTokens()) {
  String token recallToken.getToken();
  // Same string as was written in LinkPersona call
  // decrypt and recover in-game account
}

הטוקן האחרון לביטול ההסכמה בכל המשחקים שבבעלות חשבון המפתח

כדי לאחזר את האסימון האחרון שמאוחסן בכל המשחקים שבבעלות חשבון המפתח ב-Google Play Console, צריך לקבל את recallSessionId מהלקוח ולהעביר אותו אל API‏ lastTokenFromAllDeveloperGames, כמו שמוצג בקטע הקוד הבא. כחלק מהתשובה, אפשר לבדוק את מזהה האפליקציה שמשויך לאסימון הזה.

import com.google.api.services.games.Games;
import com.google.api.services.games.model.RetrieveDeveloperGamesLastPlayerTokenResponse;
import com.google.api.services.games.model.GamePlayerToken;
import com.google.api.services.games.model.RecallToken;

// ...

String recallSessionId = ... // recallSessionID from game client

RetrieveDeveloperGamesLastPlayerTokenResponse response =
        gamesApi.recall().lastTokenFromAllDeveloperGames(recallSessionId)
        .execute();

if (response.hasGamePlayerToken()) {
    GamePlayerToken gamePlayerToken = response.getGamePlayerToken();

    // The ID of the application that the token is associated with.
    String applicationId = gamePlayerToken.getApplicationId();

    // Same string as was written in LinkPersona call.
    RecallToken recallToken = gamePlayerToken.getRecallToken();

    // Decrypt and recover in-game account.
}

כל אסימוני הביטול ברשימה נתונה של משחקים שבבעלות חשבון המפתח

כדי לאחזר את כל האסימונים שמשויכים לרשימת משחקים שנמצאים בבעלות חשבון הפיתוח שלכם ב-Google Play Console, צריך לקבל את recallSessionId מהלקוח ולהעביר אותו אל API‏ gamesPlayerTokens. צריך לספק רשימה של מזהי אפליקציות.

import com.google.api.services.games.Games;
import com.google.api.services.games.model.RetrieveGamesPlayerTokensResponse;
import com.google.api.services.games.model.GamePlayerToken;
import com.google.api.services.games.model.RecallToken;

// ...

String recallSessionId = ... // recallSessionID from game client

// Application IDs for which you would like to retrieve the recall tokens.
List<String> applicationIds = ...

RetrieveGamesPlayerTokensResponse response =
gamesApiClient
        .recall()
        .gamesPlayerTokens(recallSessionId)
        .setApplicationIds(applicationIds)
        .execute();

for (GamePlayerToken gamePlayerToken : response.getGamePlayerTokens()) {
    // The ID of the application that the token is associated with.
    String applicationId  = gamePlayerToken.getApplicationId();


    // Same string as was written in LinkPersona call.
    RecallToken recallToken = gamePlayerToken.getRecallToken();

    // Decrypt and recover in-game account.
}

מחיקת טוקן הגישה

במקרה הצורך, אפשר גם למחוק את אסימון הביטול באמצעות הקריאה הבאה:

import com.google.api.services.games.Games;
import com.google.api.services.games.model.UnlinkPersonaRequest;
import com.google.api.services.games.model.UnlinkPersonaResponse;

// ...

String recallSessionId = ...
String persona = ...
String token = ...

Games gamesApi =
    new Games.Builder(httpTransport, JSON_FACTORY, credential).build();

UnlinkPersonaRequest unlinkPersonaRequest =
  UnlinkPersonaRequest.newBuilder()
    .setSessionId(recallSessionId)
    .setPersona(persona)
    // .setToken(token) - alternatively set token, but not both
    .build();

UnlinkPersonaResponse unlinkPersonaResponse =
  gamesApi.recall().unlinkPersona(unlinkPersonaRequest).execute();

boolean unlinked = unlinkPersonaResponse.isUnlinked();

הפעלת מצב ללא פרופיל

כדי להפעיל פונקציונליות מוגבלת של Recall API למשתמשים שאין להם פרופילים ב-PGS, פועלים לפי השלבים הבאים:

  1. מפעילים את התכונה 'ריקול ללא פרופיל' בפרויקט המשחק של PGS ב-Play Console. בוחרים באפשרות &#39;הפעלת האחסון&#39;.
  2. בהמשך הקטע הזה מפורטים תנאים נוספים.
  3. מוסיפים את תג המטא-נתונים הבא למניפסט של האפליקציה:
<meta-data
  android:name="com.google.android.gms.games.PROFILELESS_RECALL_ENABLED"
  android:value="true" />

תנאים נוספים

בנוסף לכך שאתם כפופים לתנאים ולהגבלות של Play Games Services, אתם מסכימים שאם אתם משתמשים ב-Recall API עבור משתמשים ללא פרופיל PGS, שמאפשר שיתוף נתונים של משתמשי קצה עם Google בלי שהם יצטרכו פרופיל Play Games Services, אתם חייבים, לפני שאתם משתפים את הנתונים האלה עם Google, לספק למשתמשי הקצה הודעה מתאימה שמתארת את הדברים הבאים:

  1. השיתוף של הנתונים עם Google כדי להפעיל את התכונה של קישור חשבון Play Games.
  2. הזמינות של הגדרות לניהול השיתוף, כמו הגדרות של Play Games.
  3. העיבוד של הנתונים האלה מתבצע בהתאם למדיניות הפרטיות של Google, וצריך לקבל הסכמה מתאימה ממשתמשי הקצה לשיתוף כזה, בהתאם לכל הדרישות המשפטיות הרלוונטיות.