Android SDK 相關問題

建立憑證並以 JWT 編碼後,即可在 Android 應用程式中發行憑證。如要這麼做,請先確認使用者的裝置是否支援 Google 錢包 API,然後向使用者顯示「新增至 Google 錢包」按鈕,並在使用者輕觸按鈕後將憑證儲存至 Google 錢包。

必要條件

發行票證前,請務必完成下列步驟:

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 錢包 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 相關的商業邏輯放在 Activity 或 Fragment 中 (例如:UI 元素、活動結果),以及檢視區塊模型中的作業邏輯 (例如:用戶端例項化、網路呼叫觸發程序)。

接著,請使用 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 下匯入向量資產。在精靈中選取「本機檔案」,然後新增名稱 (例如: add_to_google_wallet_button.xml),然後在本機磁碟中找出要匯入的檔案。

  • 「新增至 Google 錢包」按鈕
  • 「新增至 Google 錢包」按鈕 (精簡版)

現在,您可以使用匯入的可繪項目,將按鈕新增至使用者介面:

    <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 錢包

將未簽署的 JWT 傳遞至 savePasses 方法,即可新增 OfferObject。 點選 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 的值。