Before getting started with the Android SDK, make sure you've completed the prerequisites.
The Android SDK lets you add Passes in Google Wallet. When you add the Google Wallet button in your app, your users will enjoy a simple and delightful experience of adding their passes to Google Wallet.
Follow the steps to add the Google Wallet button to your Android application:
1. Create a Passes Object
Note: A Passes Class is required to create a Passes Object. If you haven't already created one, follow the instructions on how to Create a Passes Class..Define a corresponding GenericObject
, including the following required attributes:
classId
: The id of the Passes Class created in prerequisites.
- id
: A unique id for the object.
genericType
: The type the card belongs to. If your card does not match any of the available options, set it toGENERIC_TYPE_UNSPECIFIED
.cardTitle
: The title of the pass.header
: The header of the pass, such as the name of the user.
logo
subheader
JSON
{
"id": "ISSUER_ID.OBJECT_ID",
"classId": "CLASS_ID",
"genericType": "GENERIC_TYPE_UNSPECIFIED",
"cardTitle": {
"defaultValue": {
"language": "en",
"value": "Card title"
}
},
"subheader": {
"defaultValue": {
"language": "en",
"value": "Attendee"
}
},
"header": {
"defaultValue": {
"language": "en",
"value": "Alex McJacobs"
}
},
"logo": {
"sourceUri": {
"uri": "https://storage.googleapis.com/wallet-lab-tools-codelab-artifacts-public/pass_google_logo.jpg"
}
}
}
2. Create an unsigned JWT with the object
When the GenericObject
is created, wrap it with an unsigned JWT with the payload.GenericObjects
attribute, as shown in the following snippet:
JSON
{
"iss": "OWNER_EMAIL_ADDRESS",
"aud": "google",
"typ": "savetowallet",
"iat": "UNIX_TIME",
"origins": [],
"payload": {
"genericObjects": [ NEW_OBJECT ]
}
}
3. Include the Google Wallet button in your UI
Google Wallet provides a familiar button that you can use to trigger the Add to Google Wallet flow in your application. Vector assets for the button are available in the Button guidelines.
You can import vector assets in Android Studio under File > New > Vector Asset
. Select "Local file" in the wizard, add a name (eg.: add_to_google_wallet_button.xml
) and locate the file in your local drive to import it.
Now, you can use the imported drawable to add the button to your user interface:
<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" />
The button has a layout_height
of 48 dp and must be at least 200 dp wide.
4. Check if the Google Wallet API is available on the target device
Before saving the new object, ensure that the Google Wallet API is available on the target device by calling the getPayApiAvailabilityStatus
method in the PayClient
class. Start by adding a member variable to the activity where you will show the button and instantiate it when the activity is created:
Kotlin
private lateinit var walletClient: PayClient
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
walletClient = Pay.getClient(this)
// Additional logic in your onCreate method
}
Java
private final PayClient walletClient;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
walletClient = Pay.getClient(application);
// Additional logic in your onCreate method
}
Now, use the client to check whether the API is available:
Kotlin
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
}
.addOnFailureListener {
// Hide the button and optionally show an error message
}
}
Java
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
})
// Google Play Services is too old. API availability can't be verified.
.addOnFailureListener(exception -> {
// Hide the button and optionally show an error message
});
}
Finally, call the method defined above in your application when you need to determine the availability of the API.
5. Add the object to Google Wallet
The GenericObject
can be added by passing the unsigned JWT from step 2 to the
savePasses
method. You can start the add operation as a result of clicking the Google Wallet button:
Kotlin
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
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
}
The savePasses
method triggers the save flow and invokes the onActivityResult
method after the save flow has completed. The implementation of onActivityResult
should be similar to the following:
Kotlin
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == addToGoogleWalletRequestCode) {
when (resultCode) {
RESULT_OK ->
// Pass saved successfully. Consider informing the user.
RESULT_CANCELED -> {
// Save operation canceled
}
PayClient.SavePassesResult.SAVE_ERROR -> data?.let { intentData ->
val errorMessage = intentData.getStringExtra(PayClient.EXTRA_API_ERROR_MESSAGE)
// Handle error. Consider informing the user.
}
else -> {
// Handle unexpected (non-API) exception
}
}
}
}
Java
@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. Consider informing the user.
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. Consider informing the user.
}
break;
}
default: {
// Handle unexpected (non-API) exception
}
}
}
}
When the pass is successfully added, the resultCode
contains the value of Activity.RESULT_OK
.
Next steps
- Assess use cases of Generic passes and implement those that suit the business need
- Customize the appearance of your Generic passes by following Brand guidelines
- Submit your UX flow for final review in the "Google Wallet API" section on Google Pay and Wallet Console
- Still have questions? Please review our FAQ.