Migration Guide
- Migration from 1.23.x to 1.24.0
- Migration from 1.22.x to 1.23.0
- Migration from 1.21.1 to 1.22.0
- Migration from 1.20.0 to 1.21.1
- Migration from 1.20.x to 1.21.0
- Migration from 1.19.x to 1.20.x
- Migration from 1.14.x to 1.20.x
- Migration from 1.16.x to 1.19.x
- Migration from 1.14.x to 1.16.x
- Migration from 1.13.x to 1.14.x
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
- The Sensibill Android SDK is now compatible with the latest artifacts from Android Jetpack libraries. Jetpack comprises the androidx.* package libraries, unbundled from the platform APIs.
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
- The
SBFunctionalConfiguration.enableFolders
front-end configuration is now deprecated and will not be handled by the SDK. To disable folders, a backend configuration must be made. -
The
SBFunctionalConfiguration.enableNotifications
front-end configuration is now deprecated and will not be handled by the SDK. To disable notifications, a backend configuration must be made. - New way to create a
TransactionDataObserver
object in Kotlin:
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 nownon-null
.
- New way to create a
TokenProvider
object in Kotlin:
Before:
myTokenProvider = TokenProvider { oldToken, userId, listener ->
// ...
}
After:
myTokenProvider = TokenProvider.fromLambda { oldToken, userId, listener ->
// ...
}
- Certificate Pinning is now ENABLED by default. In order to disable it, add the following configuration to the
InitializationBuilder
:
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
-
Changes have been made to
SensibillSDK.initialize()
and the old usage (just providing anInitializer
) is now deprecated. AnSDKInitializeListener
Should now be provided as well to the method andSensibillSDK.start()
should only be called after theSDKInitializeListener
calls back with a successful result. -
minSdkVersion has been changed from 18 to 21. If host application has a minSdkVersion less than 21, version must be upgraded.
-
withExternalMetadata
option in the ReceiptCaptureActivityBuilder has been deprecated. If host application is using property, it should be removed. -
Requires an upgrade of gradle build tool to at least
3.5.3
(com.android.tools.build:gradle:3.5.3)
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 than3.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
- All necessary Sensibill dependencies are now included in
sensibill-sdk-all
. You may need to remove other Sensibill dependencies from yourbuild.gradle
file when migrating to this and future versions.
1.20.x to 1.21.0
- No interface changes between 1.20.x to 1.21.x
1.19.x to 1.20.x
- No interface changes between 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
- No interface changes between 1.16.x to 1.19.x
1.14.x to 1.16.x
Build Dependency Changes
- Compile SDK version: 28
- Target SDK version: 28
- Build Tools version: 28.0.3
- Android Support Library version: 28.0.0
- Android Gradle Tool version: 3.2.0
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
- Function to add TransactionObserver and ReceiptDataObserver moved to SensibillSDK object from InitializationBuilder
- The above must be done after initialization
- Example:
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)
- It is also possible now to remove the observers by calling:
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
-
many of the non-ui classes under com.getsensibill.sensibillsdk are now under com.getsensibill.core
-
token provider is now separate module: com.getsensibill.tokenprovider
-
getNewAuthToken() has new implementation. From synchronous to async
-
SessionListener under sensibillAuth module
-
UI elements now under getsensibill.ui
SensibillSDK object
- SensibillSDK functions can be called directly. No more .getInstance()
- in Java, still call .INSTANCE
SensibillSDK.verifyToken removed
- In sensibill-client to be released in -> “com.getsensibill:sensibill-client:1.14.8”
SensibillSDK.login(accessToken, username, cb) -> SensibillSDK.start(username, cb)
- No access token passed on start, uses provided token provider to get access token on start.
SensibillAuth.startLibrary()
-
Not available anymore
-
Authentication is not a wrapper of SDK
-
Must check if SensibillSDK is initialized
Authentication
-
Was renamed to SensibillAuth
-
SensibillAuthBuilder was renamed to AuthenticationBuilder
TokenProvider is the only way to Initialization
-
Must use Authentication object if no custom TokenProvider.
-
For the SensibillSDK interface, one can call functions directly. No more .getInstance() (in Java, still call .INSTANCE)
-
SensibillAuth.startLibrary() is not available anymore. SensibillSDK.start() is used instead. But before, check if SensibillSDK is already initialized.
before:
mSensibillAuth.startLibrary(mInitializer, username, listener)
after:
if (SensibillSDK.getState() == CoreState.INITIALIZED) {
SensibillSDK.start(username, listener)
}
- SensibillSDK.login(accessToken, username, cb) is also not needed anymore, SensibillSDK.start(username, cb) will be enough. Since now token provider is added on the initialization, there is no need for a separate method to start with token. And token provider will give access token during on start process.