Skip to main content

Android Push Provisioning v2.0.0

· 9 min read

Changes

warning

This version is a major update over 1.0.0 that includes removals and changes in the public interface of the SDK, as well as a completely new distribution method. Make sure you address these changes by following the instructions in the migration guide at the end of the release notes for this version.

Compatibility

Minimum Android SDK: 24 (Android 7.0 Nougat)

Compile SDK: 35

Target SDK: 35

Kotlin: 1.8.0 or newer

Google Pay device requirements: Google Play services must be installed and up to date; NFC only needed for default-payment flows.

Added

  • Added onCancelled() to AddToWalletListener.
  • Added WPPComponents.initializeWeavrSDK(context: Context, uiKey: String) to initialise the SDK instead of WPPComponents.initWeavrGPayClient.
  • Added WPPComponents.getCardStatus to replace WPPComponents.canAddCardToWallet avoiding listeners and using coroutines instead.
  • Added WPPComponents.setDefaultCardInGooglePay to replace WPPComponents.setCardAsDefaultPaymentMethod.
  • Added WPPException to subclass Exception for throwing, as well as to standardise the error reporting within the SDK. Note that the SDK won't be throwing and instead use Outcome to report success or error.
  • Added WeavrSDKErrorCodes to contain a list of error codes the SDK can use.
  • Added states PENDING and SUSPENDED to CardStatus.
  • Added multiple push provisioningPush Provisioning A method that allows cardholders to add their card to a digital wallet (such as Apple Pay or Google Pay) directly from your app. The card details are securely tokenized and sent to the wallet provider, streamlining the process and enhancing the user experience compared to manual provisioning. This feature is currently in beta. providers to maximise up-time and reliability.

Breaking changes

  • Updated SDK access process—contact support@weavr.io to receive the latest package and onboarding instructions.
  • Changed WPPComponents.isGooglePayAvailable to be a synchronous method rather than using coroutines needlessly.
  • Changed onError(WPPException) in AddToWalletListener. This replaces the old onError(WPPError) as the WPPError type had less information on what went wrong.

Removed

  • Removed WPPComponents.launchGpay as the result of WPPComponents.getPushProvisioningLauncher includes a provisionCard method instead.

Deprecated

  • Deprecated WPPComponents.initWeavrGPayClient in favour of WPPComponents.initializeWeavrSDK.
  • Deprecated CardStatusListener in favour of an async method to get the card status.
  • Deprecated WPPComponents.canAddCardToWallet in favour of WPPComponents.getCardStatus.
  • Deprecated WPPComponents.setGPayAsDefaultNFCPaymentMethod in favour of WPPComponents.setGooglePayAsDefaultNFCPaymentMethod. This avoids using coroutines needlessly as the outcome depends only on whether the activity to select was able to be launched or not, not the actual result.
  • Deprecated WPPComponents.getGpayLauncher in favour of WPPComponents.getPushProvisioningLauncher to improve naming consistency.
  • Deprecated WPPComponents.setCardAsDefaultPaymentMethod with WPPComponents.setDefaultCardInGooglePay as the callback was unnecessary due to callback being called from within the method itself.
  • Deprecated WPPResult to be replaced with Outcome. This is because WPPResult would use an optional Success generic type, forcing users to account for nulls everywhere. Additionally made Outcome compatible with Kotlin Result by calling Outcome.asResult.
  • Deprecated the case Unknown of CardStatus, and added UNKNOWN for consistency across state capitalisation.
  • Deprecated the case GPayError of CardStatus. This state will no longer be used.

Other changes to note

  • We have moved the SDK to work with AppCompactActivity preferably. Ensure that your activity is sub-classing it to avoid problems during provisioning.
  • SDK binaries are now distributed directly by Weavr Support—request access via support@weavr.io.

Migration guide

Changes in the project setup

Contact support@weavr.io to receive detailed setup instructions and the SDK package for v2.0.0.

Breaking changes

The following changes are necessary for the correct functioning of your application.

Initialising the SDK

In the past, the SDK was initialised using WPPComponents.initWeavrGPayClient, receiving a token.

From v2.0.0 and onwards, we'll initialise the SDK using WPPComponents.initializeWeavrSDK, taking as input:

  • A Context for the SDK to use, in general this should be the Application context.
  • The UI key, represented as a string, of your application, as obtained from the portal.

The following snippet showcases how to use the new method:

MyApplication.kt
class MyApplication : Application() {

override fun onCreate() {
super.onCreate()
WPPComponents.initializeWeavrSDK(this, BuildConfig.UI_KEY)
}
}

Provisioning a card with WPPComponents

In order to provision a card using the WPPComponents class rather than the AddToWalletButton you need to ensure that you call getPushProvisioningLauncher at the right time, and that you unregister the launcher when your Activity or Fragment is destroyed.

The call to get the launcher may be calling under the hood the registerForActivityResult android method. This method requires you to call it BEFORE the Activity or Fragment provided are created.

Once the call is made, we'll provide you with a launcher object with two methods, a provisionCard method, that as per its name, will attempt to provision the card when called, and an unregister method.

The unregister method must be called on the onDestroy method of your Activity or Fragment to ensure we release resources.

The following Activity showcases how this can be implemented:

MyActivity.kt
class MyActivity: AppCompatActivity() {

private val provisioningLauncher = WPPComponents.getPushProvisioningLauncher(this, object: AddToWalletListener {
override fun onSuccess() {
TODO("Not yet implemented")
}

override fun onError(error: WPPException) {
TODO("Not yet implemented")
}

override fun onCancelled() {
TODO("Not yet implemented")
}
})

override fun onDestroy() {
provisioningLauncher.unregister()
super.onDestroy()
}
}
note

The SDK handles all provisioning logic internally to ensure maximum reliability and compatibility.

The SDK uses modern Android APIs to handle provisioning flows automatically. All activity result handling is managed internally—no manual activity result callbacks are required from your side.

Migrating deprecated methods

These changes will be backwards compatible, but we encourage you to update to avoid breaking changes in the future.

Checking if Google Pay is available

Before interacting with the SDK for any further actions against the Google Pay Wallet, we need to check if Google Pay itself is available within the device, as this is not guaranteed.

To do so, we use WPPComponents.isGooglePayAvailable to check. In the past, this method was a coroutine that required you to call it from a Task or from another suspend fun.

Moving forward, this is implemented as a synchronous method, removing that requirement. Additionally, it will return a new type called Outcome, that behaves similarly to Kotlin's Result type. The main difference between Result and Outcome is that Outcome also includes the error type as a generic, allowing us to strongly type what kind of error we surface, specifically WPPException.

The following snippets showcase different approaches you can take to handle the result:

WPPComponents.isGooglePayAvailable().onSuccess {
googlePayStatusTextView.text = if (it) "Available" else "Unavailable"
}.onFailure {
googlePayStatusTextView.text = "Error: ${it.message}"
}

Getting the card status

In the past, we would fetch the status of the card via WPPComponents.canAddCardToWallet, which takes a listener to pass you back a result.

To simplify the behaviour, and provide more accurate feedback on the state of the card, we have instead introduced WPPComponents.getCardStatus which is a coroutine for simplicity, plus returns an Outcome for better context.

Finally the card states have been updated as per this documentation page.

The following snippet highlights how to use the new method:

WPPComponents.getCardStatus(card.cardNumberLastFour, CardBrand.MASTERCARD).onFailure {
cardStatusTextView.text = "Error: ${it.message}"
}.onSuccess {
cardStatusTextView.text = when (it) {
CardStatus.UNAVAILABLE -> "Unavailable"
CardStatus.PROVISIONED -> "Provisioned"
CardStatus.NOT_PROVISIONED -> "Not provisioned"
CardStatus.NEEDS_IDENTITY_VERIFICATION -> "Needs identity verification"
CardStatus.PENDING -> "Pending"
CardStatus.SUSPENDED -> "Suspended"
CardStatus.UNKNOWN -> "Unknown"
// CardStatus.GPayError -> // Has been deprecated
else -> "Unknown"
}
}

Set Google Pay as default NFC payment method

You can request the user to select their preferred NFC payment method through our SDK. In the past this was done via WPPComponents.setGPayAsDefaultNFCPaymentMethod, which is a coroutine.

We have deprecated that method in favour of WPPComponents.setGooglePayAsDefaultNFCPaymentMethod. This method is synchronous, simplifying its usage for you.

The new method can be called like so:

view.findViewById<Button>(R.id.my_button).setOnClickListener {
WPPComponents.setGooglePayAsDefaultNFCPaymentMethod(requireActivity())
}

Setting a card as the default payment method

Similarly to setting the default payment app, we can also prompt the user to make a specific card the default card within Google Pay.

This was done via the now deprecated WPPComponents.setCardAsDefaultPaymentMethod which took a callback. This has now been simplified to WPPComponents.setDefaultCardInGooglePay which uses coroutines to return an Outcome.

The following snippet illustrates how you can call it:

view.findViewById<Button>(R.id.my_button).setOnClickListener {
CoroutineScope(Dispatchers.Main).launch {
WPPComponents.setDefaultCardInGooglePay(
requireActivity(),
card.cardNumberLastFour,
CardBrand.MASTERCARD
).onSuccess {
Toast.makeText(
context,
"Card set as default in Google Pay",
Toast.LENGTH_SHORT
).show()
}.onFailure {
Toast.makeText(
context,
"Error setting card as default in Google Pay: $it",
Toast.LENGTH_SHORT
).show()
}
}
}

Using the Outcome sealed class

In the past we offered a WPPResult class that behaved similar to Kotlin's Result class.

The downside this class offered was that it would force the value to always be nullable, forcing its users to deal with the potential for null values even in operations where null is guaranteed not to be present.

Moving away from it, we assessed using Result, but its downside was that it doesn't allow to specify the type of the Error.

To resolve both issues, we introduced a new sealed class called Outcome. This class:

  • Respects the generic type passed for the Value, that is, if the type is not nullable, the value will not be nullable
  • Allows to specify the Error type
  • Is interoperable with Result via the asResult computed property

Thanks to these properties, we can grant you flexibility on how to handle the values we return in a strongly typed manner, reduce overhead by not having to deal with nullables, and allow you to choose between our own solution, or Result.

The following snippets showcase different usages of the Outcome class so you can assess which one you prefer:

callToMethodReturningOutcome().onSuccess {
// use `it` to get the value
}.onFailure {
// use `it` to get the generic typed error
}

Getting help

If you encounter issues during migration:

  1. Check this guide - Most common issues are covered above
  2. Review logs - Check Gradle build output for specific errors
  3. Contact Weavr Support - Email: support@weavr.io

When contacting support, please include:

  • Gradle version (./gradlew --version)
  • Android Gradle Plugin version
  • Complete error message
  • Steps to reproduce