Skip to main content

Android - SdkUtils

SdkUtils is the primary bridge between your module and the Q2 application. It is an abstract Parcelable that exposes everything your module typically needs: authentication tokens, theme and string resources, the active Activity, web-view controls, deep-link helpers, RDC capture, JavaScript execution in the UUX WebView, push utilities, OAuth metadata, and more.

The Q2 application supplies a concrete instance of SdkUtils to your module's constructor at registration time. Do not subclass or instantiate SdkUtils yourself — receive it through your module's constructor and store the reference.

class MyModule(private val sdkUtils: SdkUtils) : LifecycleModule {
override fun onCreate() {
val token = sdkUtils.getQ2Token()
val baseUrl = sdkUtils.getBaseUrl()
// ...
}
}

Class Declaration​

abstract class SdkUtils(private val sdkModuleConfig: SdkModuleConfig) : Parcelable

The constructor parameter sdkModuleConfig carries the entry from settings.json that registered your module — including its data map. Read it with getSdkModuleConfig().

Application & Activity Access​

MethodDescription
getApplication(): ApplicationReturns the host application's Application instance.
getApplicationContext(): ContextReturns the global application Context. Safe to use anywhere; never null.
getActivity(): Activity?Returns the currently displayed Activity. Returns null until LifecycleModule.onCreate() has fired for the first activity, and again whenever the app is in the stopped state. Always null-check before use.
getLaunchIntent(): IntentReturns the Intent that launches the host application. Useful when you need to start a new task that ends back on the main app screen.

Authentication & User Information​

MethodDescription
getQ2Token(): String?Returns the current user's Q2 session token. Returns null if no user is signed in or the session has been invalidated.
getCurrentUserName(): String?Returns the username of the authenticated user, or null if not signed in.
currentUserId: String?Authenticated user ID from in-memory state, or null if no user is signed in. Synchronous — no network call. From Java, access as the no-arg getter sdkUtils.getCurrentUserId(). Added in 26.9.0.
getCurrentUserId(callback: GetUserIdCallback)Deprecated in 26.9.0. Asynchronously delivers the user ID. Invoked with null if no user is signed in. Prefer the synchronous currentUserId property — the callback form implied an async fetch, but the value has always been read from an in-memory holder.

URL & Path Management​

MethodDescription
getBaseUrl(): StringBase URL for Q2 backend API calls.
getUUXUrl(): StringBase URL for UUX (web) resources.
openUUXRoute(route: String, queryParams: Map<String, Any> = emptyMap())Navigates the UUX WebView to an Ember route through the router bridge. Handles pre- and post-login automatically. See openUUXRoute. Added in 26.10.0.
loadPathInUuxViewBeforeLogon(path: String)Deprecated in 26.10.0, use openUUXRoute. Navigates the Core WebView to a path before login. Only effective while the app is foregrounded and Core controls the active view.
loadPathInUuxViewAfterLogon(path: String)Deprecated in 26.10.0, use openUUXRoute. Same as above but after authentication.
runJavascriptInUUX(javaScript: String, callback: ValueCallback<String>?)Executes JavaScript inside the running UUX WebView. The callback receives the return value as a JSON-encoded string. Foreground + Core-controlled view only.
presentUrl(url: String, target: WebNavigationTarget?, config: BrowserConfig?)Navigates the user to an arbitrary URL. See presentUrl for routing options.

openUUXRoute​

Navigates the UUX WebView to a named Ember route. Prefer this over loadPathInUuxViewBeforeLogon / loadPathInUuxViewAfterLogon, both deprecated in 26.10.0.

sdkUtils.openUUXRoute("activity-center")
sdkUtils.openUUXRoute("activity-center", mapOf("isMrdcHistory" to true))
ParameterDescription
routeEmber route name, for example "activity-center". Not a URL path.
queryParamsQuery params handed to the route. Defaults to empty.

Three behaviours the deprecated pair did not have:

  • No pre-/post-login decision. Called while the user is unauthenticated, the route is held in a latest-wins slot and replayed when they reach the post-login landing page. Called after login, it navigates immediately. A held route is dropped on login failure, so it is never replayed into a different user's session on a shared device.
  • Re-enters the current route. Because it goes through the Ember router bridge rather than loading a path, calling it for the route already on screen refreshes that route instead of no-opping. Use this when you need a list to reload after your module wrote to it.
  • UUX version differences are handled for you. The bridge selects the correct router method and maps renamed legacy route names based on the UUX version the app is running against. There is no minimum UUX version to check and no per-FI branching to write.

Unlike the deprecated methods, openUUXRoute does not silently no-op before login. It no-ops only when the app is backgrounded or Core does not own the active view.

presentUrl​

Routes a URL to one of three destinations based on the target:

enum class WebNavigationTarget { UUX, OVER_BROWSER, EXTERNAL_BROWSER }

data class BrowserConfig(
val redirectUriKey: String? = "q2_mobile_app_redirect_uri",
val redirectUriValue: String?
)
TargetBehaviour
UUXLoads the URL inside the existing UUX WebView. Mobile parameters are appended automatically.
OVER_BROWSEROpens the URL in the SDK's in-app browser (Custom Tab-style overlay). Use BrowserConfig to specify a redirect URI that closes the overlay when the user is sent back to.
EXTERNAL_BROWSERHands the URL off to the OS to open in the default external browser.
sdkUtils.presentUrl(
url = "https://example.com/return-flow",
target = WebNavigationTarget.OVER_BROWSER,
config = BrowserConfig(redirectUriValue = "myapp://oauth-return")
)

Theme & UI Resources​

MethodDescription
getCurrentThemeName(): String?Name of the currently applied theme, or null if none.
getCurrentTheme(): JSONObject?Full theme as a JSONObject — colors, fonts, spacing, etc.
getColor(id: String): String?Theme color value (e.g., "#FF0000") for the given identifier.
getString(id: String): String?Resource string for the given key (legacy — prefer stringsUtils.getString).
getFont(id: String): TypefaceTheme Typeface for the given identifier.
stringsUtils: StringsUtilsStrongly-typed strings accessor. Use sdkUtils.stringsUtils.getString("my.key"). Recommended over getString(id) for new code.
interface StringsUtils {
fun getString(key: String): String
}

Device Information​

MethodDescription
getUserDefinedDeviceName(): StringThe user-supplied device nickname, used in push and SAC enrollment.
getDeviceID(): StringStable unique identifier for this device installation.

getDeviceID() returns ANDROID_ID when the platform provides it. Since 26.10.0, if ANDROID_ID is unavailable the SDK mints a random identifier once, persists it encrypted, and reuses it for the life of the install, so the method no longer returns an empty value on those devices. The identifier is stable per install, not per physical device, and is scoped to the app signing key. Do not treat it as a hardware ID.

UI Controls​

MethodDescription
showLoadingView(message: String? = null)Displays the SDK's built-in loading overlay above the WebView. Optionally pass a message to display under the spinner. Foreground + Core-controlled view only.
hideLoadingView()Hides the loading overlay.
showDialogFragment(dialog: DialogFragment)Displays a DialogFragment using Core's FragmentManager.
showFragment(fragment: Fragment)Pushes a full-screen Fragment onto the Core navigation stack.
hideFragment()Pops the most recently shown fragment from the Core navigation stack.

Logging & Analytics​

MethodDescription
logEvent(eventName: String, data: Map<String, String>)Logs a structured analytics event with arbitrary key/value attributes. Routed through the SDK logger.

Configuration & Settings​

MethodDescription
getSetting(name: String): String?Reads a top-level value from settings.json.
getSdkModuleConfig(): SdkModuleConfigReturns the SdkModuleConfig for your module — the entry from settings.json that registered it. Read your data block via config.data.
getQ2ConfigObject(callback: Q2ConfigResponseCallback)Asynchronously fetches the Q2 server-side configuration object. Use for tenant/runtime-driven feature flags.
getSSOContent(vendorId: Int, callback: SSOContentResponseCallback)Asynchronously fetches an outbound SSO payload for the given vendor ID. Used by InboundSSO/Outbound SSO modules.
val cameraLicense = sdkUtils.getSdkModuleConfig().data
?.optString("licenseKey")
.orEmpty()

Method Module Requests​

MethodDescription
suspend executeMethodRequest(request: MethodRequest): JSONArrayDispatches a typed MethodRequest to every registered MethodModule that opts into it, and returns each module's JSONObject response packed into a JSONArray. See MethodModule.
viewModelScope.launch {
val params = sdkUtils.executeMethodRequest(MethodRequest.OAUTH_AUTHORIZATION_PARAMS)
// params is a JSONArray of JSONObjects, one per responding module
}

OAuth​

Available in applications that authenticate via OAuth. Available since sdk_interfaces 0.3.10.

PropertyDescription
oAuthUtils: OAuthUtils?OAuth metadata accessor, or null if the application is not using OAuth. Populated post-authorization. The accessToken field was added in MSDK Android 26.6.0.
interface OAuthUtils {
val idToken: String
val accessToken: String
}

Push Notifications​

MethodDescription
sacCapabilities: SacCapabilitiesSecure Account Creation capabilities for this installation. Added in 26.10.0.
isSacViaPushAllowed(): BooleanDeprecated in 26.10.0, use sacCapabilities.allowSacViaPush.
isSacModificationDisabled(): BooleanDeprecated on arrival in 26.10.0, use sacCapabilities.disableSacModification.
getSDKPushUtils(): SDKPushUtilsPush registration metadata.
data class SacCapabilities(
val allowSacViaPush: Boolean, // SAC via push is available at all
val disableSacModification: Boolean // an existing SAC enrollment may not be changed
)
- if (sdkUtils.isSacViaPushAllowed()) { … }
+ if (sdkUtils.sacCapabilities.allowSacViaPush) { … }

disableSacModification is new in 26.10.0 and has no non-deprecated predecessor. The deprecated methods delegate to sacCapabilities, so existing call sites keep working.

interface SDKPushUtils {
val pushRegistrationToken: String?
val deviceNickname: String?
val isEnabledForSAC: Boolean
val isPushEnabled: Boolean // app-level setting
val isPushEnabledAtOS: Boolean // OS-level permission
val pushUserId: Int
}

Remote Deposit Capture (RDC)​

The SDK exposes the underlying check-capture flow as an ActivityResultContract that any module can drive. This is the same machinery used by the deposit-check feature inside Core, and respects whatever CameraModule implementation has been registered (see Camera Module).

MethodDescription
getRdcContract(): ActivityResultContract<RDCRequest, RDCImageResult>Returns an ActivityResultContract you can register with any ActivityResultRegistryOwner to capture check images.

Request and result types​

data class RDCRequest(
val first: CheckSide, // FRONT or BACK
val second: CheckSide? = null, // optional second side for combined captures
val cameraModuleName: String = "", // force a specific legacy mob module by name
val additionalConfig: Map<String, Any> = emptyMap()
)

enum class CheckSide { FRONT, BACK }

sealed class RDCImageResult : Parcelable {
data class Success(val frontImage: File?, val backImage: File?) : RDCImageResult()
data class Error(val exception: Exception? = null, val errorCode: String? = null) : RDCImageResult()

object ErrorCodes {
const val USER_CANCELLED = "USER_CANCELLED"
const val LICENSE_ERROR = "LICENSE_ERROR"
}
}

Resolution behaviour​

When getRdcContract() is invoked:

  1. If RDCRequest.cameraModuleName is non-empty, the SDK uses the legacy mob_modules entry with that name.
  2. Otherwise, if a registered sdk_modules CameraModule is available, it is used.
  3. Otherwise, the SDK falls back to the default legacy mrdcCamera mob module.

If the active CameraModule returns LICENSE_ERROR, the SDK auto-falls-back to the legacy module.

Example​

class MyDepositFragment : Fragment() {

private lateinit var rdcLauncher: ActivityResultLauncher<RDCRequest>

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
rdcLauncher = registerForActivityResult(sdkUtils.getRdcContract()) { result ->
when (result) {
is RDCImageResult.Success -> handleImages(result.frontImage, result.backImage)
is RDCImageResult.Error -> when (result.errorCode) {
RDCImageResult.ErrorCodes.USER_CANCELLED -> { /* user backed out */ }
RDCImageResult.ErrorCodes.LICENSE_ERROR -> showLicenseError()
else -> showGenericError(result.exception)
}
}
}
}

private fun captureFrontAndBack() {
rdcLauncher.launch(
RDCRequest(
first = CheckSide.FRONT,
second = CheckSide.BACK,
additionalConfig = mapOf("CameraLicense" to myLicenseKey)
)
)
}
}

Associated Interfaces​

SSOContentResponseCallback​

interface SSOContentResponseCallback {
fun onReceivingSSOContent(responseString: String?)
fun onReceivingErrorContent(errorResponseString: String?)
fun onFailure(exception: Throwable)
}

Q2ConfigResponseCallback​

interface Q2ConfigResponseCallback {
fun onReceivingQ2ConfigObject(responseObject: JSONObject?)
fun onReceivingErrorContent(errorResponseString: String?)
fun onFailure(exception: Throwable)
}

GetUserIdCallback​

Deprecated in 26.9.0. Retained only for the deprecated getCurrentUserId(callback:) overload; new code should read sdkUtils.currentUserId directly.

interface GetUserIdCallback {
fun value(userId: String?)
}

End-to-End Example: a MethodModule using SdkUtils​

class BaseUrlMethodModule(private val sdkUtils: SdkUtils) : MethodModule {

/**
* Tecton-callable method that returns the authenticated user's ID,
* or an empty string if the user is not signed in.
*/
fun getUserId(
context: Context,
data: String,
callback: MethodModule.MethodModuleCallback
) {
val token = sdkUtils.getQ2Token()
if (token == null) {
callback.returnValue("")
return
}

val userId = sdkUtils.currentUserId
sdkUtils.logEvent(
"BaseUrlMethodModule.getUserId",
mapOf("authenticated" to "true")
)
callback.returnValue(userId.orEmpty())
}
}

Setting Up DevApp For Development​

Most SdkUtils features are available without any additional configuration — register your module in devapp/src/main/assets/conf/settings.json (see Configuring settings.json) and the Q2 application will inject a real SdkUtils instance into your constructor when the module is loaded.

A few features have extra prerequisites:

  • Authentication APIs (getQ2Token, currentUserId, oAuthUtils): require an active session. Sign into DevApp before calling them.
  • UUX APIs (runJavascriptInUUX, openUUXRoute, loadPathInUuxView*, presentUrl(... UUX)): require the WebView to be foregrounded and under Core's control. They no-op silently otherwise. openUUXRoute is the exception to the "sign in first" rule: called pre-login it holds the route and replays it after authentication, so you can test it from the login screen.
  • getRdcContract(): requires either a registered CameraModule SDK module or a legacy mrdcCamera mob module entry. DevApp ships with a working default; see the Camera Module page for setup details.
  • Push utilities (getSDKPushUtils, sacCapabilities): require push to be configured for the build. Set "push": true in settings.json and enable the Q2PushService mob module.
  • OAuth utilities (oAuthUtils): require the InboundSSO SDK module to be enabled and an OAuth-backed login to have completed.

Testing & Debugging Tips​

  • Authentication state: the easiest way to detect "not signed in" is to check getQ2Token() == null rather than waiting for callbacks to deliver null.
  • Foreground/background behaviour: UI helpers (showLoadingView, runJavascriptInUUX, openUUXRoute, loadPathInUuxView*, presentUrl(... UUX)) silently no-op when the app is in the background or when Core does not own the active view. Always design for that case rather than assuming the call always succeeds.
  • Log routing: logEvent writes through the SDK's structured logger. Use adb logcat and filter on your event names, or check the standard Q2 analytics pipeline if your build is wired to one.
  • Method requests: executeMethodRequest is suspend — call it from a coroutine. The returned JSONArray contains one entry per MethodModule that responded; modules that return null are excluded.
  • RDC contract: register the contract once in onCreate/init, never inside event handlers — Activity Result contracts must be registered before the Activity/Fragment reaches the STARTED state.

Notes​

  • Many UI methods only function while the application is in the foreground and Core controls the active view. They will silently no-op otherwise.
  • Authentication-dependent methods can return null at any time; never assume a token or user ID is present.
  • Async helpers use callbacks specifically so the SDK can dispatch work off the main thread — avoid blocking inside the callback methods.