The Frollo Android SDK is designed to simplify integration of the Frollo APIs by providing all the tools needed to manage caching of data from the APIs and authentication. Linking of data between APIs and retry of requests when authentication has expired is all managed automatically.
The Frollo Android SDK is broken down into multiple components that reflect the features on our APIs. At a high level the features are broken down as follows:
Authentication of the user is currently managed by use of OAuth2. Users can be authenticated by any OpenID Connect compliant identity provider or the Frollo identity provider.
Authentication is supported using the following OAuth2 flows:
Authentication provides the access token needed to access Frollo APIs and manages refreshing the access token if it expires.
See OAuth2Authentication for more details.
User management provides utilities to manage the user profile and device. The user profile can contain personal information about the user used to personalise the Frollo experience, for example providing location relevant recommendations and comparisons on spending.
The following are taken care of here:
The following are available depending on how authentication and users are configured for your tenant:
See UserManagement for more details.
Aggregation manages the user's financial and other accounts data. This gives an aggregate view of a user's bank accounts, loans, credit information, loyalty, insurance and other data. Linking and customisation of this data is also managed here.
Account data can come from many different sources including:
An institution is referred to as a Provider and the login or connection to that provider as a ProviderAccount. The actual account data is referred to as an Account as each provider account may have multiple accounts linked to it. An example would be:
Provider: ANZ
Provider Account: user@example.com
Supported account types include:
Transactions can support tagging for personalisation at a granular level or allow for spending breakdown to be mesaured at higher level through automatic categorisation and allocation to "buckets". Buckets include income, living, lifestyle and savings. Naming of these buckets can be changed at the UI level and allocation between them can be determined by configuration of the host tenant. These are referred to as a BudgetCategory in the API.
The following features are part of aggregation:
Note: Aggregation refers the the aggregated view of accounts seen within Frollo, wether this includes accounts from external aggregation partners will depend on how your tenant is configured.
See Aggregation for more details.
Bills allows users to manage bills and track payments against them. Bill detection is automatic and users can then confirm they wish to track payments against these bills or a user can add manual bills if needed.
The following features are part of bills:
See Bills for more details.
Budgets and pay day allow the user to setup a budget based on their own pay cycle. Budgets can be setup to track spending against merchants, categories and buckets. Setting up budgets at the bucket level allows users to group spending together and easily track against proven budgeting methods (e.g. envelope or buckets).
The following features are part of budgets and pay day:
Coming Soon to SDK
Reports give a breakdown of a user's spending or an account balance history. Reports can be used to show the user spending in the current month or allow the user to drill down and explore their spend in a variety of ways. Reports data is also suitable for driving graphs.
Reports can be generated across different time periods and broken down into several different ways including by category, by merchant and by bucket.
The following features are part of reports:
See Reports for more details.
Goals help the user set savings or debt repayment goals and meet them. Goals allow the user to set a target amount and/or date and/or how much they can afford each month and their target date/repayment/total is calculated from this. Savings towards this goal are automatically tracked from deposits to an associated bank or savings account.
The following features are part of goals and challenges:
See Goals for more details.
Events allow user actions to drive changes or chains of actions on the Frollo host. For example a user could reach some fitness goals using HealthKit and trigger an event to increase their lifestyle budget for the next week as a reward.
See Events for more details.
Messages allow feedback to be provided to the user in the form of nudges and other content. Messages are a customisable content delivery system allowing the system to provide reminders back to the user to keep on track, drive offers or any manner of content the user may need.
The following features are supported as part of messages:
See Messages for more details
Surveys allow you to collect feedback and conduct surveys from the user. This can be used to find how a user feels about their financial situation and drive events based on that or even just get feedback on the consuming application.
The following features are supported as part of surveys:
See Surveys for more details
Gradle tools plugin version 3.5.1+ - In your project level build.gradle
dependencies {
classpath "com.android.tools.build:gradle:3.5.1"
//..
}
Gradle version must be 5.4.1+
Modify Gradle version in your gradlewrapper.properties as below
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
minSdkVersion in your gradle file must be 23 or above. Frollo SDK does not support Android versions below Marshmallow (6.0).
defaultConfig {
//..
minSdkVersion 23
//..
}
To integrate Frollo Android SDK to your Android app use the following steps:
Add below line to the dependencies in your app/build.gradle file
dependencies {
//..
implementation project(":frollo-android-sdk-release-3.3.0")
}
Add this line just below your apply plugins in your app/build.gradle file
apply from: '../frollosdk.gradle'
Define a appAuthRedirectScheme in your module level build.gradle. This should be unique redirect uri for your app.
Example: If your redirect url is frollo-sdk-example://authorize, then you would do as below
defaultConfig {
//..
manifestPlaceholders = ['appAuthRedirectScheme': 'frollo-sdk-example']
//..
}
For more details see Integration Requirements under OAuth2 Authentication using Authorization Code
<application> element in your AndroidManifest.xml.If you have enabled progaurd please add below lines to your progaurd rules file
# KEEP FROM OBFUCATION - Frollo SDK
-keep class us.frollo.frollosdk.** {*;}
-keepclassmembers class us.frollo.frollosdk.** {*;}
Pull the Frollo SDK code base
If you are using GIT version control for your project, add Frollo SDK as a submodule in your project
git submodule add git@bitbucket.org:frollo1/frollo-android-sdk.git
git submodule update --init --recursive
or
Clone SDK repo inside your project's root directory
git clone git@bitbucket.org:frollo1/frollo-android-sdk.git
You should see a folder named frollo-android-sdk inside your root project directory and within it, the SDK code.
Checkout a stable release branch
cd frollo-android-sdk
git fetch
git checkout release/3.3.0 (replace the version number with the most stable version number)
Add frollo-android-sdk module to your settings.gradle file
include ':app', ':frollo-android-sdk'
Add below line to the dependencies in your app/build.gradle file
dependencies {
//..
implementation project(":frollo-android-sdk")
}
Define a appAuthRedirectScheme in your module level build.gradle. This should be unique redirect uri for your app.
Example: If your redirect url is frollo-sdk-example://authorize, then you would do as below
defaultConfig {
//..
manifestPlaceholders = ['appAuthRedirectScheme': 'frollo-sdk-example']
//..
}
For more details see Integration Requirements under OAuth2 Authentication using Authorization Code
<application> element in your AndroidManifest.xml.If you have enabled progaurd please add below lines to your progaurd rules file
# KEEP FROM OBFUCATION - Frollo SDK
-keep class us.frollo.frollosdk.** {*;}
-keepclassmembers class us.frollo.frollosdk.** {*;}
Add below line to the dependencies in your <library module name>/build.gradle file
dependencies {
//..
implementation(name: 'frollo-android-sdk-release-3.3.0', ext: 'aar')
}
Add below to your project level build.gradle file
allprojects {
//..
repositories {
//..
flatDir {
dirs project(':<library module name>').file('libs')
}
}
}
Add this line just below your apply plugins in your <library module name>/build.gradle file
apply from: 'frollosdk.gradle'
Define a appAuthRedirectScheme in your app and module level build.gradle files. This should be unique redirect uri for your app.
Example: If your redirect url is frollo-sdk-example://authorize, then you would do as below
defaultConfig {
//..
manifestPlaceholders = ['appAuthRedirectScheme': 'frollo-sdk-example']
//..
}
For more details see Integration Requirements under OAuth2 Authentication using Authorization Code
<application> element in your AndroidManifest.xml.If you have enabled progaurd please add below lines to your progaurd rules file
# KEEP FROM OBFUCATION - Frollo SDK
-keep class us.frollo.frollosdk.** {*;}
-keepclassmembers class us.frollo.frollosdk.** {*;}
Import the FrolloSDK and ensure you run setup with your tenant URL provided by us. Do not attempt to use any APIs before the setup completion handler returns. You will also need to pass in your custom authentication handler or use the default OAuth2 implementation.
class MyApplication : Application() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// OAuth2 Config
val configuration = FrolloSDKConfiguration(
authenticationType = OAuth2(
redirectUrl = "<REDIRECT_URI>",
authorizationUrl = "https://id.frollo.us/oauth/authorize",
tokenUrl = "https://id.frollo.us/oauth/token"),
clientId = "<APPLICATION_CLIENT_ID>",
serverUrl = "https://<API_TENANT>.frollo.us/api/v2/")
// Custom Authentication Config
val customAuthentication = CustomAuthentication()
val configuration = FrolloSDKConfiguration(
authenticationType = Custom(
accessTokenProvider = customAuthentication,
authenticationCallback = customAuthentication),
clientId = "<APPLICATION_CLIENT_ID>",
serverUrl = "https://<API_TENANT>.frollo.us/api/v2/")
FrolloSDK.setup(this, configuration = configuration) { result ->
when (result.status) {
Result.Status.SUCCESS -> completeSetup()
Result.Status.ERROR -> Log.e(TAG, result.error?.localizedDescription)
}
}
}
}
Before any data can be refreshed for a user they must be authenticated first. If using OAuth2 authentication you can check the logged in status of the user on the OAuth2Authentication class.
if (FrolloSDK.oAuth2Authentication.loggedIn) {
showMainActivity()
} else {
showLoginActivity()
}
If the user is not authenticated then the user must login or an access token must be provided by the custom Authentication access token provider. Authentication can be done using OAuth2 or a custom implementation can be provided if you wish to manage the user's access token manually or share it with other APIs.
Using OAuth2 based authentication Resource Owner Password Credential flow and Authorization Code with PKCE flow are supported. Identity Providers must be OpenID Connect compliant to use the in-built OAuth2Authentication authentication class. If using OAuth2 authentication you can use oAuth2Authentication
Using the ROPC flow is the simplest and can be used if you are implementing the SDK in your own highly trusted first party application. All it requires is email and password and can be used in conjunction with a native UI.
See loginUser(email:password:completion:)
FrolloSDK.oAuth2Authentication.loginUser(email = "jacob@example.com", password = "$uPer5ecr@t") { result ->
when (result.status) {
Result.Status.ERROR -> displayError(result.error?.localizedDescription, "Login Failed")
Result.Status.SUCCESS -> completeLogin()
}
}
Authenticating the user using Authorization Code flow involves a couple of extra steps to configure. The first is to present the ChromeTabs to the user to take them through the web based authorization flow. The Activity this should be presented from must be passed to the SDK.
You need to define a appAuthRedirectScheme in your module level build.gradle. This should be unique redirect uri for your app.
Example: If your redirect url is frollo-sdk-example://authorize, then you would do as below
defaultConfig {
//..
manifestPlaceholders = [
'appAuthRedirectScheme': 'frollo-sdk-example'
]
//..
}
If you are using a deep link scheme which is same as your appAuthRedirectScheme, then add below component to your manifest
Example: If your redirect url is frollo-sdk-example://authorize, and you have defined appAuthRedirectScheme: 'frollo-sdk-example' in your gradle file.
<!-- AppAuth Custom Redirect URI -->
<activity android:name="net.openid.appauth.RedirectUriReceiverActivity"
android:exported="true"
tools:node="replace">
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="${appAuthRedirectScheme}" android:host="authorize"/>
</intent-filter>
</activity>
Completion intent and Cancelled intent should be provided to the SDK to support web based OAuth2 login and other links that can affect application behaviour.
class LoginActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
//...
startAuthorizationCodeFlow()
}
private fun startAuthorizationCodeFlow() {
val completionIntent = Intent(this, CompletionLoginWebActivity::class.java)
val cancelIntent = Intent(this, LoginActivity::class.java)
cancelIntent.putExtra(EXTRA_FAILED, true)
cancelIntent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
FrolloSDK.oAuth2Authentication.loginUserUsingWeb(
activity = this,
scopes = listOf(OAuth2Scope.OFFLINE_ACCESS, OAuth2Scope.EMAIL, OAuth2Scope.OPENID),
completedIntent = PendingIntent.getActivity(this, 0, completionIntent, 0),
cancelledIntent = PendingIntent.getActivity(this, 0, cancelIntent, 0),
toolBarColor = resources.getColor(R.color.colorPrimary, null))
}
}
The next step is to pass the intent received by the Completion Activity to the SDK to complete the login process and exchange the authorization code for a token.
class CompletionLoginWebActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
//...
FrolloSDK.oAuth2Authentication.handleWebLoginResponse(intent) { result ->
when (result.status) {
Result.Status.SUCCESS -> {
startActivity<MainActivity>()
finish()
}
Result.Status.ERROR -> displayError(result.error?.localizedDescription, "Login Failed")
}
}
}
}
class LoginActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
//...
startAuthorizationCodeFlow()
}
private fun startAuthorizationCodeFlow() {
FrolloSDK.authentication.loginUserUsingWeb(
activity = this,
scopes = listOf(OAuth2Scope.OFFLINE_ACCESS, OAuth2Scope.EMAIL, OAuth2Scope.OPENID),
toolBarColor = resources.getColor(R.color.colorPrimary, null))
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == Authentication.RC_AUTH) {
if (resultCode == RESULT_CANCELED) {
displayAuthCancelled();
} else {
// The next step is to pass the intent received to the SDK to complete the login process and exchange the authorization code for a token.
FrolloSDK.authentication.handleWebLoginResponse(intent) { result ->
when (result.status) {
Result.Status.SUCCESS -> {
startActivity<MainActivity>()
finish()
}
Result.Status.ERROR -> displayError(result.error?.localizedDescription, "Login Failed")
}
}
}
}
}
}
Custom authentication can be provided by conforming to the AccessTokenProvider interface and AuthenticationCallback interface ensuring all interface functions are implemented appropriately.
After logging in, your cache will be empty in the SDK. Refresh important data such as Messages immediately after login.
FrolloSDK.messages.refreshUnreadMessages { result ->
when (result.status) {
Result.Status.ERROR -> displayError(result.error?.localizedDescription, "Refreshing Messages Failed")
Result.Status.SUCCESS -> Log.d("Accounts Refreshed")
}
}
Alternatively refresh data on startup in an optimized way using refreshData on the main SDK. This will refresh important user data first, delaying less important ones until later.
FrolloSDK.refreshData()
Fetching objects from the cache store is easy. Just call the SDK fetch APIs and observe the returned LiveData.
FrolloSDK.messages.fetchMessages(read = false).observe(owner, Observer<Resource<List<Message>>> { resource ->
when (resource?.status) {
Resource.Status.SUCCESS -> loadMessages(resource.data)
Resource.Status.ERROR -> displayError(result.error?.localizedDescription, "Fetching Messages Failed")
}
})
Optionally implement the lifecycle handlers by extending Application class to ensure FrolloSDK can keep cached data fresh when suspending and resuming the app.
class MyApplication : Application(), LifecycleObserver {
override fun onCreate() {
super.onCreate()
ProcessLifecycleOwner.get().lifecycle.addObserver(this)
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
fun onAppBackgrounded() {
FrolloSDK.onAppBackgrounded()
}
@OnLifecycleEvent(Lifecycle.Event.ON_START)
fun onAppForegrounded() {
FrolloSDK.onAppForegrounded()
}
}
Follow the steps here and here to setup Firebase client for Android.
FirebaseInstanceId.getInstance().instanceId
.addOnCompleteListener(OnCompleteListener { task ->
if (!task.isSuccessful) {
Log.w(TAG, "getInstanceId failed", task.exception)
return@OnCompleteListener
}
// Get new Instance ID token
val token = task.result?.token
token?.let { FrolloSDK.notifications.registerPushNotificationToken(it) }
})
class MyFirebaseMessagingService : FirebaseMessagingService() {
override fun onNewToken(token: String?) {
token?.let { FrolloSDK.notifications.registerPushNotificationToken(it) }
}
}
class MyFirebaseMessagingService : FirebaseMessagingService() {
override fun onMessageReceived(remoteMessage: RemoteMessage?) {
remoteMessage?.data?.let { data ->
if (data.isNotEmpty()) {
FrolloSDK.notifications.handlePushNotification(data)
}
}
}
}
intent.extras?.let {
FrolloSDK.notifications.handlePushNotification(it)
}
|
FrolloSDK manages the lifecycle of the SDK. Only one instance should be instantiated and then used (after setup completes) during the lifetime of the app. |
|
|
Manages all aggregation data including accounts, transactions, categories and merchants. |
|
|
Authentication manages the authentication of the user, managing the user profile and logout of the user. |
|
|
Frollo SDK base classes |
|
|
Manages bills and bill payments |
|
|
Frollo SDK core classes |
|
|
Types of Frollo SDK errors |
|
|
Handles events and allows triggering of events on the host. |
|
|
Tracking and managing goals |
|
|
Frollo SDK logging |
|
|
Manages refreshing and caching of messages. |
|
|
Frollo SDK data models |
|
|
Frollo SDK shared models |
|
|
Frollo SDK account models |
|
|
Frollo SDK merchant models |
|
|
us.frollo.frollosdk.model.coredata.aggregation.provideraccounts |
Frollo SDK provider account models |
|
Frollo SDK provider models |
|
|
Frollo SDK transaction user tag models |
|
|
us.frollo.frollosdk.model.coredata.aggregation.transactioncategories |
Frollo SDK transaction category models |
|
Frollo SDK transaction models |
|
|
Frollo SDK bill and bill payment models |
|
|
Frollo SDK goal models |
|
|
Frollo SDK message models |
|
|
Frollo SDK report models |
|
|
Frollo SDK shared models |
|
|
Frollo SDK survey models |
|
|
Frollo SDK user models |
|
|
Frollo SDK provider display models |
|
|
Frollo SDK OAuth2 models |
|
|
Manages registration for and handling of incoming push notifications. |
|
|
Manages all aspects of reporting of aggregation data including spending and balances. |
|
|
Manages fetching & submitting surveys. |
|
|
Manages the user details and device |