パスを作成して JWT でエンコードしたら、Android アプリで発行する準備が整います。そのためには、ユーザーのデバイスで Google Wallet API が利用可能であることを確認し、[Google ウォレットに追加] ボタンを表示して、ユーザーがボタンをタップしたらパスを Google ウォレットに保存する必要があります。
前提条件
パスを発行する前に、次のことを確認してください。
- オンボーディング ガイドのすべての手順を完了している。
- 少なくとも 1 つのパスクラスを作成します。
- 少なくとも 1 つのパス オブジェクトを作成します。
- JWT でパスのクラスとパスのオブジェクトをエンコードします。
1. Google ウォレット Android SDK をインストールする
Google ウォレット Android SDK を使用するには、アプリレベルの build.gradle ファイルの dependencies セクションに com.google.android.gms:play-services-pay を追加します。
implementation "com.google.android.gms:play-services-pay:16.5.0"
2. Google Wallet API の利用可能性を確認する
新しいオブジェクトを保存する前に、PayClient クラスの getPayApiAvailabilityStatus メソッドを呼び出して、Google Wallet API が対象デバイスで使用可能であることを確認します。
まず、ボタンを表示するアクティビティにメンバー変数を追加し、そのアクティビティが作成されたときに変数をインスタンス化します。
Kotlin
import com.google.android.gms.pay.PayClient
private lateinit var walletClient: PayClient
override fun onCreate(savedInstanceState: Bundle?) {
  super.onCreate(savedInstanceState)
  walletClient = Pay.getClient(this)
  // Additional logic in your onCreate method
}Java
import com.google.android.gms.pay.PayClient;
private final PayClient walletClient;
@Override
protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  walletClient = Pay.getClient(application);
  // Additional logic in your onCreate method
}他の設計パターンを使用している場合は、ドメイン固有のビジネス ロジックを適切に配置することを検討してください。たとえば、MVVM パターンを使用する場合は、UI 関連のビジネス ロジック(UI 要素、アクティビティの結果など)を Activity または Fragment に配置し、操作ロジック(クライアントのインスタンス化、ネットワーク呼び出しのトリガーなど)をビューモデルに配置します。
次に、PayClient を使用して API が使用可能かどうかを確認します。
Kotlin
import com.google.android.gms.pay.PayApiAvailabilityStatus
private fun fetchCanUseGoogleWalletApi() {
  walletClient
    .getPayApiAvailabilityStatus(PayClient.RequestType.SAVE_PASSES)
    .addOnSuccessListener { status ->
      if (status == PayApiAvailabilityStatus.AVAILABLE) {
        // The API is available, show the button in your UI
      } else {
        // The user or device is not eligible for using the Pay API
      }
    }
    .addOnFailureListener {
      // Hide the button and optionally show an error message
    }
}Java
import com.google.android.gms.pay.PayApiAvailabilityStatus;
private void fetchCanAddPassesToGoogleWallet() {
  walletClient
    .getPayApiAvailabilityStatus(PayClient.RequestType.SAVE_PASSES)
    .addOnSuccessListener(status -> {
      if (status == PayApiAvailabilityStatus.AVAILABLE) {
        // The API is available, show the button in your UI
      } else {
        // The user or device is not eligible for using the Pay API
      };
    })
    .addOnFailureListener(exception -> {
      // Google Play Services is too old, or API availability not verified
      // Hide the button and optionally show an error message
    });
}最後に、API が使用可能かどうかを判断する際にアプリで上記のメソッドを呼び出します。
API が利用できない場合の処理
API を使用できない理由としては、Android または Google Play 開発者サービスのバージョンが古い、ユーザーの国で Google ウォレットが利用できない、などが考えられます。
API を使用できない場合は、ボタンを非表示にして、別の統合にフォールバックする(たとえば、JWT リンクを使用する)ことを検討してください。なお、当該ユーザーは今後 API を利用できるようになる可能性があります。
3. [Google ウォレットに追加] ボタンを追加する
Google ウォレットには、アプリから Google ウォレットへの追加フローをトリガーするための、見慣れたボタンが用意されています。このボタンのベクター アセットはボタン ガイドラインから入手できます。
ベクター アセットは、Android Studio で File > New > Vector Asset を使用してインポートできます。ウィザードで [Local file] を選択して名前(例:
add_to_google_wallet_button.xml)を指定し、ローカル ドライブでそのファイルを探してインポートします。
これで、インポートしたドローアブルを使用してユーザー インターフェースにボタンを追加できます。
<ImageButton android:id="@+id/addToGoogleWalletButton" android:layout_width="match_parent" android:layout_height="48dp" android:minWidth="200dp" android:clickable="true" android:src="@drawable/add_to_google_wallet_button" />
ボタンの layout_height は 48 dp です。幅は 200 dp 以上にする必要があります。
4. ユーザーの Google ウォレットにパスを追加する
EventObject を追加するには、無署名の JWT を savePasses メソッドに渡します。Google ウォレット ボタンがクリックされた結果として、追加操作を開始できます。
Kotlin
import android.os.Bundle
import android.view.View
import com.google.android.gms.samples.wallet.databinding.ActivityCheckoutBinding
private val addToGoogleWalletRequestCode = 1000
private lateinit var layout: ActivityCheckoutBinding
private lateinit var addToGoogleWalletButton: View
override fun onCreate(savedInstanceState: Bundle?) {
  super.onCreate(savedInstanceState)
  // Use view binding to access the UI elements
  layout = ActivityCheckoutBinding.inflate(layoutInflater)
  setContentView(layout.root)
  addToGoogleWalletButton = layout.addToGoogleWalletButton
  addToGoogleWalletButton.setOnClickListener {
    walletClient.savePasses(newObjectJson, this, addToGoogleWalletRequestCode)
  }
  // Additional logic in your onCreate method
}Java
import android.os.Bundle;
import android.view.View;
import com.google.android.gms.samples.wallet.databinding.ActivityCheckoutBinding;
private static final int ADD_TO_GOOGLE_WALLET_REQUEST_CODE = 999;
private ActivityCheckoutBinding layout:
private View addToGoogleWalletButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  // Use view binding to access the UI elements
  layout = ActivityCheckoutBinding.inflate(getLayoutInflater());
  setContentView(layout.getRoot());
  addToGoogleWalletButton = layout.addToGoogleWalletButton;
  addToGoogleWalletButton.setOnClickListener(v -> {
    walletClient.savePasses(newObjectJson, this, ADD_TO_GOOGLE_WALLET_REQUEST_CODE);
  });
  // Additional logic in your onCreate method
}結果の処理
savePasses メソッドを呼び出すと保存フローがトリガーされ、保存フローが完了した後に  onActivityResult メソッドが呼び出されます。onActivityResult の実装は次のようになります。
Kotlin
import android.content.Intent
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
  super.onActivityResult(requestCode, resultCode, data)
  if (requestCode == addToGoogleWalletRequestCode) {
    when (resultCode) {
      RESULT_OK -> {
        // Pass saved successfully
      }
      RESULT_CANCELED -> {
        // Save operation canceled
      }
      PayClient.SavePassesResult.SAVE_ERROR -> data?.let { intentData ->
        val errorMessage = intentData.getStringExtra(PayClient.EXTRA_API_ERROR_MESSAGE)
        // Handle error
      }
      else -> {
          // Handle unexpected (non-API) exception
      }
    }
  }
}Java
import android.content.Intent;
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
  super.onActivityResult(requestCode, resultCode, data);
  if (requestCode == ADD_TO_GOOGLE_WALLET_REQUEST_CODE) {
    switch (resultCode) {
      case RESULT_OK: {
        // Pass saved successfully
        break;
      }
      case RESULT_CANCELED: {
        // Save operation canceled
        break;
      }
      case PayClient.SavePassesResult.SAVE_ERROR: {
        if (data != null) {
          String apiErrorMessage = data.getStringExtra(PayClient.EXTRA_API_ERROR_MESSAGE);
          // Handle error
        }
        break;
      }
      default: {
        // Handle unexpected (non-API) exception
      }
    }
  }
}パスの追加が成功すると、resultCode の値は  Activity.RESULT_OK になります。
 
    ![[Google ウォレットに追加] ボタン](https://google-developers.gonglchuangl.net/static/wallet/images/branding/add-to-wallet-button-primary.png?authuser=002&hl=ja)
![縮小形の [Google ウォレットに追加] ボタン](https://google-developers.gonglchuangl.net/static/wallet/images/branding/add-to-wallet-button-condensed.png?authuser=002&hl=ja)