כניסה לחשבון במשחקי Android

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

הטמעת כניסה של שחקנים

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

כדי ליצור לקוח כניסה:

  1. יוצרים לקוח כניסה באמצעות האובייקט GoogleSignInOptions, כפי שמתואר בקטע הקוד הבא. כדי להגדיר את הכניסה צריך לציין GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN ב-GoogleSignInOptions.Builder.

    GoogleSignInOptions signInOptions = GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN;
  2. אם רוצים להשתמש ב-SnapshotsClient, צריך להוסיף את .requestScopes(Games.SCOPE_GAMES_SNAPSHOTS) ל-GoogleSignInOptions.Builder, כפי שמתואר בקטע הקוד הבא:

    GoogleSignInOptions  signInOptions =
        new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN)
            .requestScopes(Games.SCOPE_GAMES_SNAPSHOTS)
            .build();
  3. קוראים ל-method‏ GoogleSignIn.getClient() ומעבירים את האפשרויות שהגדרתם בשלבים הקודמים. אם הקריאה תצליח, Google Sign-In API יחזיר מופע של GoogleSignInClient.

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

אפשר לבדוק אם חשבון מסוים כבר מחובר במכשיר הנוכחי באמצעות GoogleSignIn.getLastSignedInAccount(), ואם לחשבון הזה כבר הוקצו ההרשאות הנדרשות באמצעות GoogleSignIn.hasPermissions(). אם שני התנאים מתקיימים – כלומר, getLastSignedInAccount() מחזירה ערך שאינו null ו-hasPermissions() מחזירה את הערך true – אפשר להשתמש בבטחה בחשבון שהתקבל מ-getLastSignedInAccount(), גם אם המכשיר במצב אופליין.

ביצוע כניסה ללא קול

אפשר לבצע קריאה אל silentSignIn() כדי לאחזר את חשבון השחקן שמחובר כרגע, ולנסות להכניס שחקנים בלי להציג ממשק משתמש אם הם נכנסו בהצלחה לאפליקציה במכשיר אחר.

השיטה silentSignIn() מחזירה Task<GoogleSignInAccount>. כשהמשימה תושלם, תוכלו להגדיר את השדה GoogleSignInAccount שהצהרתם עליו קודם לחשבון הכניסה שהמשימה מחזירה, או לערך null, שמציין שאין משתמש מחובר.

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

מכיוון שהמצב של המשתמש שמחובר לחשבון יכול להשתנות כשהפעילות לא בחזית, מומלץ להפעיל את silentSignIn() מהשיטה onResume() של הפעילות.

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

  1. מפעילים את השיטה silentSignIn() ב-GoogleSignInClient כדי להתחיל את תהליך הכניסה השקטה. הקריאה הזו מחזירה אובייקט Task<GoogleSignInAccount> שמכיל GoogleSignInAccount אם הכניסה השקטה בוצעה בהצלחה.
  2. כדי לטפל בהצלחה או בכשלון של הכניסה של הנגן, משנים את הערך של OnCompleteListener.
    • אם משימה הכניסה הושלמה בהצלחה, מקבלים את האובייקט GoogleSignInAccount באמצעות קריאה ל-getResult().
    • אם הכניסה לא בוצעה בהצלחה, אפשר לשלוח כוונה לכניסה כדי להפעיל תהליך כניסה אינטראקטיבי. רשימה של מודעות קריאה חוזרת נוספות שאפשר להשתמש בהן מופיעה במדריך למפתחים של Tasks API ובחומר העזר בנושא API של Task.

קטע הקוד הבא מראה איך האפליקציה יכולה לבצע כניסה שקטה:

private void signInSilently() {
  GoogleSignInOptions signInOptions = GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN;
  GoogleSignInAccount account = GoogleSignIn.getLastSignedInAccount(this);
  if (GoogleSignIn.hasPermissions(account, signInOptions.getScopeArray())) {
    // Already signed in.
    // The signed in account is stored in the 'account' variable.
    GoogleSignInAccount signedInAccount = account;
  } else {
    // Haven't been signed-in before. Try the silent sign-in first.
    GoogleSignInClient signInClient = GoogleSignIn.getClient(this, signInOptions);
    signInClient
        .silentSignIn()
        .addOnCompleteListener(
            this,
            new OnCompleteListener<GoogleSignInAccount>() {
              @Override
              public void onComplete(@NonNull Task<GoogleSignInAccount> task) {
                if (task.isSuccessful()) {
                  // The signed in account is stored in the task's result.
                  GoogleSignInAccount signedInAccount = task.getResult();
                } else {
                  // Player will need to sign-in explicitly using via UI.
                  // See [sign-in best practices](http://developers.google.com/games/services/checklist) for guidance on how and when to implement Interactive Sign-in,
                  // and [Performing Interactive Sign-in](http://developers.google.com/games/services/android/signin#performing_interactive_sign-in) for details on how to implement
                  // Interactive Sign-in.
                }
              }
            });
  }
}

@Override
protected void onResume() {
  super.onResume();
  signInSilently();
}

אם ניסיון הכניסה השקט נכשל, תוכלו להפעיל את הפונקציה getException() כדי לקבל ApiException עם קוד הסטטוס המפורט. קוד סטטוס CommonStatusCodes.SIGN_IN_REQUIRED מציין שהמשתמש צריך לבצע פעולה מפורשת כדי להיכנס לחשבון. במקרה כזה, האפליקציה צריכה להפעיל תהליך כניסה אינטראקטיבי כמו שמתואר בקטע הבא.

ביצוע כניסה אינטראקטיבית

כדי להיכנס באמצעות אינטראקציה של השחקן, האפליקציה צריכה להפעיל את כוונת הכניסה. אם ההתחברות תצליח, ממשק המשתמש של Google Sign-In API יציג הודעה שבה השחקן יתבקש להזין את פרטי הכניסה שלו. הגישה הזו מפשטת את פיתוח האפליקציה, כי פעילות הכניסה מטפלת בתרחישים כמו צורך לעדכן את Google Play Services או הצגת בקשות להסכמה, בשם האפליקציה. התוצאה מוחזרת דרך הפונקציה החוזרת (callback)‏ onActivityResult.

כדי לבצע את הכניסה באופן אינטראקטיבי, פועלים לפי השלבים הבאים:

  1. קוראים ל-getSigninIntent() ב-GoogleSignInClient כדי לקבל כוונה לכניסה, ואז קוראים ל-startActivity() ומעבירים את הכוונה הזו. קטע הקוד הבא מראה איך האפליקציה יכולה להפעיל תהליך כניסה אינטראקטיבי:

    private void startSignInIntent() {
      GoogleSignInClient signInClient = GoogleSignIn.getClient(this,
          GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN);
      Intent intent = signInClient.getSignInIntent();
      startActivityForResult(intent, RC_SIGN_IN);
    }
  2. בקריאה החוזרת (callback) של onActivityResult(), מטפלים בתוצאה מהכוונה שהוחזרה.

    • אם תוצאת הכניסה הייתה מוצלחת, מקבלים את האובייקט GoogleSignInAccount מה-GoogleSignInResult.
    • אם תוצאת הכניסה לא הייתה מוצלחת, עליכם לטפל בשגיאת הכניסה (לדוגמה, באמצעות הצגת הודעת שגיאה בהתראה). קטע הקוד הבא מראה איך האפליקציה יכולה לטפל בתוצאות של כניסת השחקן:
    @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()) {
          // The signed in account is stored in the result.
          GoogleSignInAccount signedInAccount = result.getSignInAccount();
        } 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();
        }
      }
    }

אחזור פרטי השחקנים

הקוד GoogleSignInAccount שמוחזר על ידי Google Sign-In API לא מכיל פרטי נגן. אם המשחק שלכם משתמש בפרטי שחקנים, כמו שם התצוגה ומזהה השחקן, תוכלו לפעול לפי השלבים הבאים כדי לאחזר את המידע הזה.

  1. כדי לקבל אובייקט PlayersClient, קוראים לשיטה getPlayersClient() ומעבירים את GoogleSignInAccount כפרמטר.
  2. משתמשים בשיטות PlayersClient כדי לטעון באופן אסינכרוני את האובייקט Player שמכיל את פרטי השחקן. לדוגמה, אפשר להפעיל את הפונקציה getCurrentPlayer() כדי לטעון את הנגן שאליו המשתמש מחובר כרגע. אם המשימה מחזירה את הערך ApiException עם קוד סטטוס SIGN_IN_REQUIRED, סימן שצריך לבצע אימות מחדש של הנגן. כדי לעשות זאת, צריך להפעיל את הפונקציה GoogleSignInClient.getSignInIntent() כדי להיכנס לחשבון בנגן באופן אינטראקטיבי.
  3. אם המשימה מחזירה את האובייקט Player, אפשר להפעיל את השיטות של האובייקט Player כדי לאחזר פרטים ספציפיים של נגן (לדוגמה, getDisplayName() או getPlayerId()).

הוספת לחצן כניסה

כדי להציג במשחק לחצן סטנדרטי לכניסה לחשבון Google, אפשר להשתמש באחת מהגישות הבאות:

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

קטע הקוד הזה מראה איך להוסיף לחצן כניסה לפעילות שלכם בשיטה onCreate().

@Override
protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_sign_in);
  findViewById(R.id.sign_in_button).setOnClickListener(this);
  findViewById(R.id.sign_out_button).setOnClickListener(this);
}

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

@Override
public void onClick(View view) {
  if (view.getId() == R.id.sign_in_button) {
    // start the asynchronous sign in flow
    startSignInIntent();
  } else if (view.getId() == R.id.sign_out_button) {
    // sign out.
    signOut();
    // show sign-in button, hide the sign-out button
    findViewById(R.id.sign_in_button).setVisibility(View.VISIBLE);
    findViewById(R.id.sign_out_button).setVisibility(View.GONE);
  }
}

הצגת חלונות קופצים של משחקים

אפשר להציג תצוגות קופצות במשחק באמצעות הכיתה GamesClient. לדוגמה, יכול להיות שתוצג הודעה קופצת עם הכיתוב 'ברוך הבא' או 'הישגים נפתחים'. כדי לאפשר לשירותי המשחקים של Google Play להציג חלונות קופצים בתצוגות במשחק, צריך להפעיל את השיטה setViewForPopups(). כדי להתאים אישית את המיקום של חלון הקופץ במסך, אפשר להפעיל את הפונקציה setGravityForPopups().

יציאה מהחשבון של הנגן

כדי לצאת מהחשבון, צריך להפעיל את השיטה signOut() ב-GoogleSignInClient.

private void signOut() {
  GoogleSignInClient signInClient = GoogleSignIn.getClient(this,
      GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN);
  signInClient.signOut().addOnCompleteListener(this,
      new OnCompleteListener<Void>() {
        @Override
        public void onComplete(@NonNull Task<Void> task) {
          // at this point, the user is signed out.
        }
      });
}