View on GitHub

sensibill-android-documentation

Migration Guide

  1. Migration from 1.25.x to 1.26.0
  2. Migration from 1.24.x to 1.25.0
  3. Migration from 1.23.x to 1.24.0
  4. Migration from 1.22.x to 1.23.0
  5. Migration from 1.21.1 to 1.22.0
  6. Migration from 1.20.0 to 1.21.1
  7. Migration from 1.20.x to 1.21.0
  8. Migration from 1.19.x to 1.20.x
  9. Migration from 1.14.x to 1.20.x
  10. Migration from 1.16.x to 1.19.x
  11. Migration from 1.14.x to 1.16.x
  12. Migration from 1.13.x to 1.14.x

1.25.x to 1.26.0

Android Gradle Plugin Version Updated

The following setion only applies if you are using a version of the Android Gradle Plugin below 4.1.x

For the Android Sensibill SDK v1.26.0, we’ve upgraded our Android Gradle Plugin version to 4.1.x and included queries elements in our AndroidManifest.xml files. As a result, you may encounter compilation errors when including the SDK due to previous versions of the Android Gradle Plugin not supporting this type of element. As a fix, Google has released new patch versions of the Android Gradle Plugin for older versions to include support for queries elements. Please ensure that, depending on your Android Gradle Plugin version, you upgrade to the following patch numbers or higher to successfully compile your project with the Sensibill SDK included:

Legacy Capture Removed

As of version 1.26.0, the Sensibill Legacy Capture module has been removed from the SDK. From this point forward, the standalone-capture module must be used instead. If you are not customizing capture at all, this change will be transparent. However, if you are launching capture via ReceiptCaptureActivityBuilder, or applying functional capture customization through ReceiptCaptureActivityBuilder.standardBuilderCreator, please see the Capture section of the Entry Points documentation and ensure you are still using the correct methods to achieve your desired customization.

Auth Module Refactor

A refactor has been done to some interfaces in Android Sensibill Auth modules. Specifically regarding the following interfaces: RegistrationProvider, OAuthProvider, SensibillAuth.

The following section is only relevant if your current integration is using any of the above mentioned interfaces.

All methods in the above now include a new optional parameter: a CoroutineScope with which all provided listeners will be called back upon. By default, this scope is set to a CoroutineScope created on the Dispatchers.IO dispatcher.



1.24.x to 1.25.0

Capture Changes

New Capture Module

A new capture module has been released with this version of the Android SDK, and by default it is set to be used instead of the (now) legacy capture module.

The legacy capture module can still be used if required when starting the capture flow from the ReceiptCaptureActivity (via the ReceiptCaptureActivityBuilder) by setting the following flag:

ReceiptCaptureActivityBuilder.getBuilder()
    // ...
    .withLegacyCaptureFlow(true)
    // ...


ReceiptCaptureActivityBuilder Configurations Updated

There have been a number of changes to the ReceiptCaptureActivityBuilder parameters.

The most important changes are as follows:

A number of new configurations have also been added. For more details of the currently available configurations, see the full documentation here

SDK-Launched Capture Customization

Also new in this version, a method has been added to customize how capture entry points from within the SDK are configured. Updating the variable stored at ReceiptCaptureActivityBuilder.standardBuilderCreator will cause the method provided to be used to configure the ReceiptCaptureActivityBuilder when starting capture flows from within the SDK. Example: Kotlin

ReceiptCaptureActivityBuilder.standardBuilderCreator = {
    val config = it ?: SBFunctionalConfiguration() // Use default config if none provided
    ReceiptCaptureActivityBuilder.getBuilder()
        .withShowProcessing(true)
        .withSecureWindow(config.enableSecureWindow)
        .withModeSummaryOnboarding(true)
}

Java

ReceiptCaptureActivityBuilder.Companion.setStandardBuilderCreator(new Function1<SBFunctionalConfiguration, ReceiptCaptureActivityBuilder>() {
    @Override
    public ReceiptCaptureActivityBuilder invoke(SBFunctionalConfiguration sbFunctionalConfiguration) {
        SBFunctionalConfiguration config = sbFunctionalConfiguration;
        // use default config if none provided
        if (config == null) {
            config = new SBFunctionalConfiguration();
        }
        return ReceiptCaptureActivityBuilder.getBuilder()
                .withShowProcessing(true)
                .withSecureWindow(config.getEnableSecureWindow())
                .withModeSummaryOnboarding(true);
    }
});


Capture Onboarding Moved

This section only is relevant to integrators who have customized the UI of the Capture Onboarding page. This change also does not apply to the old “capture tips” page, only the capture onboarding page.

The class with which the entire capture onboarding content layout can be overridden has been moved as such: Old: Module - sensibill-capture-camera-ui Location - com.getsensibill.capture.controllers.CaptureTipsViewController New: Module - sensibill-sdk-ui Location - com.getsensibill.ui.receipt.capture.onboarding.CaptureOnboardingActivity

The UI element styles have also changed names.

Java 8 Compatability

Starting with Version 1.25.0, the Sensibill Android SDK is built with Java 8 compatibility enabled. In order to use the SDK, integrating projects must also build with Java 8 compatibility enabled. In order to enable Java 8 support, add the following code snippet to your app module’s build.gradle file

android {
    // ...

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    kotlinOptions {
        jvmTarget = JavaVersion.VERSION_1_8.toString()
    }

    // ...
}


New Config Option - Secure Flag

A new configuration option has been added to the SBFunctionalConfiguration class: enableSecureWindow. Enabling this flag will cause Sensibill Activities to set secure flags to the Activity’s window (WindowManager.LayoutParams.FLAG_SECURE). The effect of enabling this flag is that users will no longer be able to take screenshots, or record video from the device’s screen while a Sensibill Activity are in the foreground. This flag defaults to false NOTE: If a Sensibill SDK Fragment is hosted within an Activity belonging to the host app, the Activity will need to set these flags itself to enable the functionality within the given Sensibill SDK Fragment.



1.23.x to 1.24.0

Receipt Processing changes

The Receipt Processing flow (when uploading a receipt to the server) was changed on this version. It was refactored to be more consistent and reliable, and to provide the TransactionDataObserver more meaningful status and error codes to help with troubleshooting.

The TransactionDataObserver is an interface that is used to observe the status of a receipt being processed. It consists solely of the notify method, which has the following signature: fun notify(transaction: Transaction)

The receipt processing changes in this version mainly affect the Transaction object that is sent to notify. Below is a summary of those changes.

Transaction.Status

The PENDING status has been broken down into two new statuses: UPLOADING and PROCESSING.

This is in order to properly separate the image upload step from the data extraction step that happens after the image has been uploaded. Previously, PENDING represented both the image upload and data extraction steps; therefore, it was required to check the TransactionId field to differentiate the two states.

With this update, UPLOADING should be interpreted as the image upload step (receipt image is being sent to the server). When the upload finishes, a new notification with the PROCESSING status will be sent.

During the PROCESSING state, one can now expect that the transactionId is present in the provided Transaction object and can be used to track the corresponding operation on the backend.

Due to the above change, PENDING now is deprecated and will display an error when used, notifying the integrator to adopt the new UPLOADING and PROCESSING statuses as replacements where appropriate.

To account for these changes, if your app was previously observing Transaction.Status your code should be updated according to the following example:

Before:

when (transaction.status) {
    Transaction.Status.PENDING -> {
        if (transaction.transactionId.isNullOrEmpty()) {
            showMessage("Receipt Processing Started")
        } else {
            showMessage("Receipt Image Uploaded/Data Process Started")
        }
    }

    Transaction.Status.COMPLETED -> showMessage("Receipt Available!")

    Transaction.Status.FAILED -> showMessage("Receipt Process Failed")
}

After:

when (transaction.status) {
    Transaction.Status.UPLOADING -> showMessage("Image Upload In Progress") // transactionId is NOT present here

    Transaction.Status.PROCESSING -> showMessage("Receipt Image Uploaded/Data Process Started") // transactionId is present here

    Transaction.Status.COMPLETED -> showMessage("Receipt Available!")

    Transaction.Status.FAILED -> showMessage("Receipt Process Failed")
}

More detailed information about the different statuses can be found in the reference documentation here: Transaction.Status

Transaction.Error

Transaction now has a new error field.

In case of a failure in the receipt processing, the Transaction object will contain an error explaining the reason for the failure.

Although it is not expected that errors will occur during this processing, if a transaction reaches the FAILED state, an error will be provided to give extra information that can be shared with Sensibill for further investigation.

Possible error types:

Error Description
NO_ERROR Transaction is still in a valid state
UNKNOWN Error origin is not known
UPLOAD_CANCELLED_NO_IMAGE Transaction state is invalid for upload: image data was not found
UPLOAD_CANCELLED_BIG_IMAGE Transaction state is invalid for upload: image data is over the limit (2mb)
UPLOAD_INVALID_RESPONSE On upload request, the server returned a response that could not be interpreted and is considered invalid
POLL_INVALID_RESPONSE On wait request, the server returned a response that could not be interpreted and is considered invalid
STOPPED_ON_SERVER Server returned a stopped status for transaction
FAILED_ON_SERVER Server returned a failed status for transaction
BAD_REQUEST Server returned status code 400 (bad request)
UNAUTHORIZED Server returned status code 401 (unauthorized)
FORBIDDEN Server returned status code 403 (forbidden)

More detailed information can be found in the reference documentation. Transaction.Error

Transaction.localId

Field localId is now Non-Null localId: String? -> localId: String and you can now expect to always have a localId in the notification. If a null check was performed before on this field, that can be removed when using the newer version.

Deprecated fields in Transaction: image & externalTransactionId

Last call for fields image and externalTransactionId. These fields have not been used for some time and will be removed in a future version.



1.22.x to 1.23.0

AndroidX is a major improvement to the original Android Support Library, which is no longer maintained. androidx packages fully replace the Support Library by providing feature parity and new libraries. Reference

It is recommended to use official guides when making migrating to AndroidX. The following links are a good start:

AndroidX Overview - https://developer.android.com/jetpack/androidx

Migrating to AndroidX - https://developer.android.com/jetpack/androidx/migrate

Before:

myTransactionDataObserver = TransactionDataObserver { transaction ->
            when (transaction.status) {
                // ...
            }
        }

After:

myTransactionDataObserver = TransactionDataObserver.fromLambda { transaction ->
            when (transaction.status) {
                // ...
            }
        }

Note: Due to our Kotlin conversion, tighter restrictions are now placed on Nullability in some interfaces. For example, the transaction parameter that comes in the notify method is now non-null.

Before:

 myTokenProvider = TokenProvider { oldToken, userId, listener ->
            // ...
        }

After:

 myTokenProvider = TokenProvider.fromLambda { oldToken, userId, listener ->
            // ...
        }
val builder = InitializationBuilder(context, DefaultEnvironment.BETA_SANDBOX)
    .certificatePinning(false)
    .build()
SensibillSDK.initialize(builder, ...)

And for SensibillAuth as follows:

val auth = SensibillAuthBuilder(context, sensibill_env, oauthSettings)
    .certificatePinning(false)
    .build()



1.21.1 to 1.22.0

Will run into a build time error More than one file was found with OS independent path 'META-INF/proguard/coroutines.pro if using a build tool less than 3.5.3.

Note: If updating the gradle version is not possible, adding the following rule to your build.gradle can potentially mitigate the issue:

android {
...
    packagingOptions {
        pickFirst('META-INF/proguard/coroutines.pro')
    }
...
}



1.21.0 to 1.21.1



1.20.x to 1.21.0



1.19.x to 1.20.x



1.14.x to 1.20.x

Build Dependency Changes

Package / Class Name Change

Deprecated Function



1.16.x to 1.19.x



1.14.x to 1.16.x

Build Dependency Changes

Package / Class Name Change

1.14.x 1.16.x
com.getsensibill.oauthclient.OauthUser com.getsensibill.oauthclient.OauthSession

Deprecated Function

Deprecated function Reason
InitializationBuilder.transactionDataObserver Transaction Data Observer is no longer added to the InitializationBuilder. Added to SensibillSDK directly (SensibillSDK.addTransactionDataObserver())
InitializationBuilder.receiptDataObserver Receipt Data Observer is no longer added to the InitializationBuilder. Added to SensibillSDK directly (SensibillSDK.addReceiptDataObserver())

Notes for Migration

before:

        // Create Observers
        myTransactionDataObserver = MyTransactionDataObserver()
        myReceiptDataObserver = MyReceiptDataObserver()

        // Add to initializer
        initializationBuilder.transactionDataObserver(myTransactionDataObserver)
        initializationBuilder.receiptDataObserver(myReceiptDataObserver)

        // Initialize
        mInitializer = initializationBuilder.build()
        SensibillSDK.getInstance().initialize(mInitializer)

after:

        // Create Observers
        myTransactionDataObserver = MyTransactionDataObserver()
        myReceiptDataObserver = MyReceiptDataObserver()

        // Initialize
        SensibillSDK.getInstance().initialize(mInitializer)

        // Add to SDK
        SensibillSDK.addTransactionDataObserver(myTransactionDataObserver)
        SensibillSDK.addReceiptDataObserver(myReceiptDataObserver)
SensibillSDK.removeTransactionDataObserver(myTransactionDataObserver)
SensibillSDK.removeReceiptDataObserver(myReceiptDataObserver)



1.13.x to 1.14.x

Feature Added

ReceiptCaptureActivityBuilder used to create intent for ReceiptCapture

Function Name Change

Old Function Name New Function Name
OAuthSettings.getApikey() OAuthSettings.getApiKey()
SensibillSDK.getInstance() SensibillSDK.INSTANCE (in Java)

Package / Class Name Change

Migration to core module

1.13.x 1.14.x
com.getsensibill.sensibillsdk.interfaces.OnTrackEventListener com.getsensibill.core.analytic.OnTrackEventListener
com.getsensibill.sensibillsdk.tracker.events.AnalyticsEvent com.getsensibill.core.analytic.OnTrackEventListener
com.getsensibill.sensibillsdk.utilities.base.ActivityLifecycleListener com.getsensibill.core.ActivityLifecycleListener
com.getsensibill.sensibillsdk.interfaces.TokenProvider com.getsensibill.tokenprovider.TokenProvider
com.getsensibill.sensibillsdk.utilities.Transaction com.getsensibill.core.analytic.Transaction
com.getsensibill.sensibillsdk.utilities.TransactionDataObserver com.getsensibill.core.TransactionDataObserver
com.getsensibill.sensibillsdk.InitializationBuilder com.getsensibill.core.InitializationBuilder
com.getsensibill.sensibillsdk.Initializer com.getsensibill.core.Initializer
com.getsensibill.sensibillsdk.SensibillSDK com.getsensibill.core.SensibillSDK
com.getsensibill.sensibillsdk.interfaces.LoginError com.getsensibill.core.LoginError
com.getsensibill.sensibillsdk.interfaces.SDKStartup com.getsensibill.core.SDKStartup

Migration to UI module

1.13.x 1.14.x
com.getsensibill.sensibillsdk.SBMainTabsFragment com.getsensibill.ui.SBMainTabsFragment
com.getsensibill.sensibillsdk.receipt.capture.ReceiptCaptureActivity com.getsensibill.ui.receipt.capture.ReceiptCaptureActivity
com.getsensibill.sensibillsdk.receipt.controllers.detail.ReceiptDetailActivity com.getsensibill.ui.receipt.controllers.detail.ReceiptDetailActivity
com.getsensibill.sensibillsdk.receipt.controllers.detail.ReceiptDetailActivity com.getsensibill.ui.receipt.controllers.detail.ReceiptDetailActivity

Deprecated Function

SensibillSDK.isInitialized() - removed, now use SensibillSDK.state() to check state of SDK. Check migration notes for details

SensibillSDK.login() - removed, replaced to use SensibillSDK.start(). Check migration notes for details

Notes for migration

Update Package Names
SensibillSDK object
SensibillSDK.verifyToken removed
SensibillSDK.login(accessToken, username, cb) -> ‌SensibillSDK.start(username, cb)
SensibillAuth.startLibrary()
Authentication
TokenProvider is the only way to Initialization

before:

     mSensibillAuth.startLibrary(mInitializer, username, listener)

after:

     if (SensibillSDK.getState() == CoreState.INITIALIZED) {
         SensibillSDK.start(username, listener)
     }