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 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
}

자바

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 패턴을 사용한다면 활동 또는 프래그먼트 (예: 뷰 모델 (예: 클라이언트 인스턴스화, 네트워크 호출 트리거)에는 운영 로직을 배치합니다.

그런 다음 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
    }
}

자바

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를 사용할 수 없는 사용자도 향후 API 사용이 가능할 수 있습니다.

3. 'Google 월렛에 추가' 버튼 추가

Google 월렛은 애플리케이션에서 Google 월렛에 추가 흐름을 트리거하는 데 사용할 수 있는 익숙한 버튼을 제공합니다. 버튼의 벡터 애셋은 버튼 가이드라인에서 확인할 수 있습니다.

Android 스튜디오의 File > New > Vector Asset에서 벡터 애셋을 가져올 수 있습니다. 마법사에서 'Local file'을 선택하고 이름 (예: 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는 48dp이고 너비는 200dp 이상이어야 합니다.

4. 사용자의 Google 월렛에 패스 추가

서명되지 않은 JWT를 savePasses 메서드에 전달하여 LoyaltyObject를 추가할 수 있습니다. 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
}

자바

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
      }
    }
  }
}

자바

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 값이 포함됩니다.