あなたの Androidゲームにゲームギフトを追加する



  • この記事は、Google Playゲームサービスに関する記事を和訳したものです。
  • 原文: Adding Game Gifts to Your Android Game
  • 元記事のライセンスは CC-BYで、この和訳記事のライセンスは CC-BYです。
  • 自己責任でご利用ください。
  • 和訳した時期は 2019年7月ころです。

ゲームプレイをより協調的にし、ソーシャルなエンゲージメントを改善するために、あなたのゲームは、ゲームギフト APIを使用することによって、プレイヤーにゲーム内のリソースあるいはアイテムのギフトを送信しリクエストできるようにすることができます。 あなたのゲームは Google Playゲームサービスによって提供されたビルトインのユーザインタフェース(UI)を表示することができ、それは、プレイヤーが、ゲーム内のアイテムやリソースのためのギフトを友人に送信しリクエストすることを簡単にします。 リクエストの受信者は、受信者がログインしているすべての端末(ただし通知が無効になっている場合を除く)上で通知を受信します。

さらには、Google Playゲームサービスのゲームギフト APIは十分に柔軟なので、あなたのゲームはプレイヤーが互いにアイテムを交渉し、取引できるようにするために使用することができます。

始める前に

ゲームギフト APIを使用し始める前に:

ひとたびプレイヤーがサインインし、GoogleApiClientが接続されれば、あなたのゲームはゲームギフト APIを使用し始めることができます。

ゲームギフトの基本

プレイヤーが Google Playゲームサービスにてゲームギフトの機能を使用して送信することができるリクエストには、2つのタイプがあります:

  • ウィッシュリクエストは、彼らの友人からゲーム内のアイテムあるいは幾つかの他の有形の援助の形式を要求します。
  • ギフトリクエストは、彼らの友人へゲーム内のアイテムあるいは幾つかの他の有形の援助の形式を送信します; 例えば、プレイヤーはゲームプレイを延長するために、お互いに "lives" をギフトすることができます。

プレイヤーはデフォルトのリクエスト送信 UIから、1人以上のターゲットのリクエストの受信者を指定することができます。 ギフトあるいはウィッシュは、受信者によって消費される(つまり、受信者によって受け入れられる)か、却下されます。 それぞれのリクエストは一度だけ消費されることができます。 もしそれらが消費されなければ、一定期間後に失効します。

リクエストは次の重要なプロパティを持っています:

名前 説明 ノート
Type リクエストが、ギフトかウィッシュかを示します。
  • ギフト。 もし、他のプレイヤーにゲーム内のアイテムあるいはその他の有形の援助の形式を送信するならば、このリクエストタイプを使用します。
  • ウィッシュ。 もし、他のプレイヤーにゲーム内のアイテムあるいはその他の有形の援助の形式を要求するならば、このリクエストタイプを使用します。
開発者によって定義されます。
Payload リクエストと共に送信するデータを格納するバイト配列。 getMaxPayloadSize()を呼び出すことによって、ペイロードのために利用できる最大のサイズを見つけることができます。 開発者によって定義されます。
Request lifetime 受信者が何もしない場合にリクエストが持続する期間(日数)を示します。 この値は、1~14日(両端を含む)の範囲でなければなりません。 この時間が経過した後、リクエストはいつでも Google Playゲームサービスによって削除されるかもしれません。 開発者によって定義されます。
Icon リクエストアイコンとして表示されるビットマップ。 開発者によって定義されます。
Description リクエストのための追加のコンテキストを提供するために、リクエスト送信 UIにて表示される文字列。 開発者によって定義されます。
ID リクエスト用のユニークな ID。 Google Playゲームサービスによってセットされます。
Sender リクエストを送信したユーザについての情報。 Google Playゲームサービスによってセットされます。
Creation timestamp リクエストが生成されたときのサーバのタイムスタンプ。 Google Playゲームサービスによってセットされます。
Expiration timestamp リクエストが Google Playゲームサービスによって削除される対象になるまでのサーバのタイムスタンプ。 Google Playゲームサービスによってセットされます。
Recipient status リクエストが受け入れられたか保留中であるかを示します。 もしリクエストが受信者によって却下されたならば、送信者のみが受信者の状態を RECIPIENT_STATUS_PENDINGとして表示されることに注意してください。 Google Playゲームサービスによってセットされます。

リクエストを送信する

ギフトあるいはウィッシュのリクエストを送信するには、次の手順を実行します:

  1. プレイヤーがリクエストの受信者を選択することを可能にするには、デフォルトのリクエスト送信 UIを提示するために getSendIntent()を呼び出します。 呼び出しでは、リクエストタイプ(TYPE_GIFTあるいは TYPE_WISH)を指定しなければなりません。 ゲーム特有のアイテムが要求された、あるいは送信されたことを示すためのバイト配列形式の追加のデータを提供するために、payload入力パラメータを使用することができます。 以下のスニペットに示すように、ペイロードは空にすることができます。

    Intent intent = Games.Requests.getSendIntent(client, type,
                "".getBytes(), DEFAULT_LIFETIME, icon, description);
    
  2. 次に、startActivityForResult()を呼び出し、getSendIntent()によって返された Intentを、開発者によって定義されたリクエストコードと一緒に渡します。 もし呼び出しが成功したならば、ユーザーにはデフォルトのリクエスト送信 UIが表示されます。

    startActivityForResult(intent, SEND_GIFT_CODE);
    
  3. ユーザが UIから 1人以上のリクエストの受信者を選択した後、リクエストはゲームギフト APIによって Google Playゲームサービスに送信されます。 Google Playゲームサービスは、それから、リクエストを表現するための GameRequestオブジェクトを作成し、このリクエストオブジェクトをターゲットの受信者にルーティングします。 あなたのゲームが受信したリクエストを受け入れる方法については、リクエストを処理するを参照してください。 あなたのゲーム内で、リクエストの送信中にエラーが発生したかどうかをチェックするために、onActivityResult()をオーバーライドすることができます。

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
            case SEND_REQUEST_CODE:
                if (resultCode == GamesActivityResultCodes.RESULT_SEND_REQUEST_FAILED) {
                   Toast.makeText(this, "FAILED TO SEND REQUEST!", Toast.LENGTH_LONG).show();
                }
                break;
            case SEND_GIFT_CODE:
                if (resultCode == GamesActivityResultCodes.RESULT_SEND_REQUEST_FAILED) {
                   Toast.makeText(this, "FAILED TO SEND GIFT!", Toast.LENGTH_LONG).show();
                }
                break;
        }
        super.onActivityResult(requestCode, resultCode, data);
    }
    

リクエスト通知からあなたのゲームを起動する

デフォルトでは、リクエストの受信者には、彼らが友人からリクエストを受信したとき、彼らの端末上に通知が表示されるでしょう。 もし受信者の端末上にすでにあなたのゲームがインストールされているならば、受信者は単純にリクエストを受け入れるかどうかを選択するための UIを起動するために通知を展開し、クリックすることができます。 受信者がこの選択をした後、システムは自動的にあなたのゲームを起動します。

次に、あなたのゲームは受信者が選択したリクエストのリストを取得する必要があります。 このリストは、あなたのゲームがonConnected()コールバックから受信した接続バンドルから connectionHintに格納された GameRequestオブジェクトとして表現されます。

ArrayList <GameRequest> mRequests
        = Games.Requests.getGameRequestsFromBundle(connectionHint);

あなたのゲームは connectionHintで返されるリクエストをプログラム的に受け入れる必要があります。 自動的にリクエストを受け入れる方法については、リクエストをプログラム的に処理するのステップ 2を参照してください。

リクエストを処理する

もし、着信リクエストが到着したときにあなたのゲームアクティビティが通知されたければ、あなたのゲームに OnRequestReceivedListenerを登録することができます。 もし、あなたのゲームが OnRequestReceivedListenerを使用するならば、ユーザは彼らの端末上で標準的なリクエスト通知を受信しないでしょう。 代わりに、あなたのゲームはユーザのために彼らが受信したリクエストを表示し、リクエストを受け入れるかどうかを選択するための受信トレイ UIを起動するオプションを提供することができます。 さらには、あなたのゲームが着信リクエストをプログラム的に処理するようにすることができます。

OnRequestReceivedListenerを登録するには、registerRequestListener()を呼び出し、あなたのゲームの GoogleApiClientとリクエストリスナーのインスタンスを渡します。

private OnRequestReceivedListener mRequestListener
        = new OnRequestReceivedListener() {
    @Override
    public void onRequestReceived(GameRequest request) {
        int requestStringResource;
        switch (request.getType()) {
            case GameRequest.TYPE_GIFT:
                requestStringResource = R.string.new_gift_received;
                break;
            case GameRequest.TYPE_WISH:
                requestStringResource = R.string.new_request_received;
                break;
            default:
                return;
        }
        Toast.makeText(MainActivity.this, requestStringResource,
                Toast.LENGTH_LONG).show();
        updateRequestCounts();
    }

    @Override
    public void onRequestRemoved(String requestId) {
        // Handle removal of incoming request; for example, if the sending
        // user cancelled the request.
    }
};

@Override
public void onConnected(Bundle connectionHint) {
    // Sign-in worked!
    // Show sign-out button or other UI

    // This is *NOT* required; if you do not register a handler for
    // request events, you will get standard notifications instead.
    Games.Requests.registerRequestListener(mGoogleApiClient,
            mRequestListener);

    // Our sample displays the request counts.
    updateRequestCounts();
}

デフォルトの受信トレイ UIを使用してリクエストを処理する

あなたのゲームは、リクエストの受信者に、受け入れられることを待っているすべての着信リクエストのリストを表示させるために、SDKによって提供されたデフォルトの受信トレイ UIを起動することができます。 受信者は、それから、リクエストを受け入れるかどうかを選択することができます。 受信トレイ UIを表示するには、受信トレイ UIを起動するための Intentを取得するために getInboxIntent()を呼び出し、それから startActivityForResult()を呼び出し、その Intentを渡します。

startActivityForResult(Games.Requests.getInboxIntent(mGoogleApiClient), SHOW_INBOX);

もし呼び出しが成功したならば、ゲームはデフォルトの受信トレイ UIを表示し、受信者に、彼らが受け入れたい着信リクエストを選択するよう促します。 受信者の選択は、それから、あなたのゲームが onActivityResult()コールバックから取得することができる Intentとして返されます。

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch (requestCode) {
        case SHOW_INBOX:
            if (resultCode == Activity.RESULT_OK && data != null) {
                handleInboxResult(Games.Requests
                        .getGameRequestsFromInboxResponse(data));
            } else {
                // handle failure to process inbox result
                ...
            }
            break;
    }
    super.onActivityResult(requestCode, resultCode, data);
}

リクエストをプログラム的に処理する

あなたのゲームはリクエストをプログラム的に受け入れることもできます。 例えば、ユーザがサインインした後、あなたのゲームにカスタムのリクエスト UIを表示するために、この方法を使用するかもしれません。 もしあなたのゲームがカスタム UIを使用するならば、それが、ユーザにリクエストを受け入れるオプションと、リクエストを却下する別個のオプションを提示していることを確認してください。

リクエストをプログラム的に受け入れるには、次の手順を実行します:

  1. onConnected()コールバックにて、Bundle引数から保留中のリクエストのリストを取得します:

    @Override
    public void onConnected(Bundle connectionHint) {
        // ...
    
        ArrayList <GameRequest> mRequests
                = Games.Requests.getGameRequestsFromBundle(connectionHint);
    }
    
  2. acceptRequests()を呼び出し、ArrayList内の GameRequestオブジェクトからリクエスト IDのリストを渡します。 代わりに、あなたのゲームはそれらを受け入れる代わりにリクエストを却下するために dismissRequests()メソッドを呼び出すことができます。 もし決定するためのリクエストがただ 1つならば、あなたのゲームは、代わりに acceptRequest()あるいは dismissRequest()を呼び出す必要があります。

    private void handleRequests(ArrayList<GameRequest> requests) {
        if (requests == null) {
            return;
        }
    
        // Attempt to accept these requests.
        ArrayList<String> requestIds = new ArrayList<String>();
    
        /**
         * Map of cached game request ID to its corresponding game request
         * object.
         */
         final HashMap<String, GameRequest> gameRequestMap
                 = new HashMap<String, GameRequest>();
    
        // Cache the requests.
        for (GameRequest request : requests) {
            String requestId = request.getRequestId();
            requestIds.add(requestId);
            gameRequestMap.put(requestId, request);
        }
    
        // Accept the requests.
        Games.Requests.acceptRequests(mGoogleApiClient, requestIds).setResultCallback(
                new ResultCallback<UpdateRequestsResult>() {
            @Override
            public void onResult(UpdateRequestsResult result) {
                // Scan each result outcome and process accordingly.
                for (String requestId : result.getRequestIds()) {
                    // We must have a local cached copy of the request
                    // and the request needs to be a
                    // success in order to continue.
                    if (!gameRequestMap.containsKey(requestId)
                            || result.getRequestOutcome(requestId)
                            != Requests.REQUEST_UPDATE_OUTCOME_SUCCESS) {
                        continue;
                    }
                    // Update succeeded here. Find the type of request
                    // and act accordingly. For wishes, a
                    // responding gift will be automatically sent.
                    switch (gameRequestMap.get(requestId).getType()) {
                        case GameRequest.TYPE_GIFT:
                            // Process the game gifts request
                            ...
                            break;
                        case GameRequest.TYPE_WISH:
                            // Process the wish request
                            ...
                            break;
                    }
                }
            }
        });
    }