# Android Programming

<div data-full-width="false"><figure><img src="/files/SgEk4iC2jJtafLsmxvqC" alt="" width="156"><figcaption></figcaption></figure></div>

## Android Studio Project Setup <a href="#toc148556252" id="toc148556252"></a>

These instructions assume that you will likely be adding the AuthenticAction™ SDK to a project within one of the common IDE, such as Android Studio. Also, the instructions in this section assume a development methodology leveraging Gradle build configuration to declare inclusion of the applicable AuthenticAction™ archive dependencies.

***Note:** If your application development build tools do not include the use of Gradle, it will be the responsibility of the developer to appropriately declare build inclusion of the AuthenticAction™ SDK archive files appropriate for the build methodology being used.*

***Note**: These instructions assume that you will likely be adding the AuthenticAction™ SDK to an Android project within one of the common IDE, such as Android Studio.*

You can import AuthenticAction™ SDK into your project by manually importing \*.arr files downloaded from a file repository. Details of the repository will be shared with you by IronVest.

### Manual importing of the Android Archive Repository (“aar”) File  <a href="#toc148556253" id="toc148556253"></a>

* [x] **Step 1:** Place the IronVest SDK within your projects ‘app/libs' folder.
  1. IronVest will supply the necessary libraries in the form of an Android Archive (ARR) file(s).
  2. This SDK aar file(s) should be placed in your target module's (usually `app`) ‘/libs’ folder, as shown in figure 1 below.

!\[A screenshot of a project tree

Figure 1: Place the release “.arr” files within module's ‘/libs’ folder of your Android project.]\(/files/JMpru6YOwJLkxesw5mIf)

***Note:** The filename, shown as “\<collector-release>.aar”, may have a formal release naming, following the convention, “ivaasdk.x.x.x.aar”, where “x.x.x” indicates the major version, subversion, and revision of the SDK. If more than one file was provided, put all the files in the same folder.*

* Edit your projects module-level application ‘gradle’ file. Add the following line to declare the import of the aar file:

```gradle
// build.gradle (Module :app)

implementation fileTree(dir: 'libs', include: ['*.aar'])
```

* [x] **Step 2:** Add Dependencies Declarations to Project Gradle File

- Edit your gradle build file to add the lines below to declare the necessary dependencies:

```gradle
    implementation 'com.google.code.gson:gson:2.10.1'
    implementation 'com.google.android.gms:play-services-location:21.0.1'
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4'
    implementation 'com.squareup.okhttp3:okhttp:4.11.0'
    implementation 'com.squareup.moshi:moshi-kotlin:1.14.0'
    implementation 'org.msgpack:msgpack-core:0.9.3'
    implementation 'com.google.android.gms:play-services-safetynet:18.0.1'
    implementation 'com.google.guava:guava:31.0.1-jre'
    implementation 'androidx.camera:camera-camera2:1.2.3'
    implementation 'androidx.camera:camera-lifecycle:1.2.3'
    implementation 'androidx.camera:camera-view:1.2.3'
    implementation 'androidx.security:security-crypto:1.0.0'
    implementation 'com.squareup.retrofit2:retrofit:2.9.0'
    implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
    implementation 'com.squareup.retrofit2:adapter-rxjava2:2.9.0'
    implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
```

{% hint style="info" %}
For the dependencies above it's important to specify the version of the 3rd party library that is actually in use by your application to avoid versions collision
{% endhint %}

## Android Application Programming Guidelines <a href="#toc148556255" id="toc148556255"></a>

The AuthenticAction™ SDK includes a process known as the “collector agent” which, when instantiated, provides a simple means of monitoring user interaction and activity related to your application without requiring extensive programming on your part. Collector agent provides you with an option to start biometric session to protect sensitive areas of your application with user's biometrics. You can control whether and where to show camera preview in the background. Collector agent exposes API to submit custom events (for example in cases when the input is not collected automatically by the collector agent). In this section you can learn how to achieve that.

This section describes:

* How to declare and initialize the collector agent
* How to set and update Customer Session ID (CSID), User ID (UID) and Context
* How to display camera preview during biometric auth session
* How to start and stop biometric authentication during specific activity
* How to submit custom events

### CollectorAgent Instance Declaration and Initialization <a href="#toc147174512" id="toc147174512"></a>

Make sure your project has an Application class like (and it is declared in Manifest file). Declare the following variables inside Application class of your app. Customer ID (CID) and Base URL to be provided by Ironvest specifically for your AuthenticAction™ instance:

```kotlin
class App: Application() { 
    //...
    lateinit var c: CollectorAgent
    private var isCollectorAgentInit = false
    val CID = "<c_id>"
    val BASE_URL = "<base_url>"
    //...
}
```

Assign and initialize SDK inside onCreate() callback of Application class. If Client Session ID (CSID) & UserID are available here from the application lifecycle perspective, you can use this opportunity to set the initial values. Usually CSID and UserID are available when a users is already authenticated and logged-in into your service.

{% code title="Inside App class" %}

```kotlin
override fun onCreate() {
    super.onCreate()
    c = CollectorAgent.initialize(this, BASE_URL, CID)
        
    /* Optional Block */
    c.setCSID("<csId>")
    c.setUserID("<userId>")
}
```

{% endcode %}

### Setting and updating CSID and UserID&#x20;

Client Session ID (CSID) & UserID are used to correlate the activity to a specific user and user's session. Identifying the user is necessary to be able to perform biometric authentication, while assigning user activity to a particular session is needed for session validation and follow-up investigation. These values may change throughout the application lifecycle and need to be updated accordingly to reflect the changes to the SDK. Context designates a particular activity performed by the user and is useful for correct and intuitive data representation. All these values can be set at once or separately, depending on the application state and needs.

Start by declaring `collectorAgent` variable inside the relevant Activity / Fragment class of your application:

```kotlin
    private lateinit var collectorAgent: CollectorAgent
```

Set the values inside `onCreate()` method of that Activity / Fragment class

{% code title="Inside onCreate() method:" %}

```kotlin
    collectorAgent = CollectorAgent.get()
    collectorAgent.setCSID(csid)
    collectorAgent.setUserID(userId)
    collectorAgent.sendContext("Wire Transfer") // "Wire Transfer" is an example, can be any string
```

{% endcode %}

### Displaying camera preview during Biometric Authentication

To display the preview of the camera, first add the following camera preview UI element to the xml file of the activity:

```xml
<io.sro.collector.auth.CollectorCameraPreview
        android:id="@+id/cameraPreview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
```

(NOTE: you can adjust the layout width and height to fit preferred UI)

Next, declare the following variables inside of your Activity class:

```kotlin
private lateinit var cameraPreview: CollectorCameraPreview // layout for camera preview
private var isAuthRunning = false /* controls the state of auth: to grant ACCESS_NOTIFICATION_POLICY user has to leave the app and go to settings and then come back to app, so using isAuthRunning to start auth automatically on back-press to client app */
```

Then, add the following code inside of the `onCreate()` method of your Activity class:

```kotlin
cameraPreview = findViewById(R.id.cameraPreview)
        c.setAuthCompletedListener {
            cameraPreview.post {
                cameraPreview.startAuth()
            }
        }
```

#### Preview Customization

`CollectorCameraPreview` supports multiple customization options, which is controlled via xml attributes or respective functions/properties.

{% hint style="info" %}
Supported starting version`0.0.65` (2024-06-1) and above
{% endhint %}

1. Preview customization: preview scale type (fit, fill, etc.), camera preview fade in/out animation duration.&#x20;
2. Overlay customization: custom color or image resource, scale type, bounds adjustments, visibility strategy (always visible or follow actual camera preview visibility)

{% hint style="info" %}
Supported starting version`0.0.71` (2024-07-1) and above
{% endhint %}

3. You can now decide whether to keep the last captured frame in the preview after biometric capture is stopped or leave it blank. See `preview_isDisplayLastFrameEnabled` option below

The following example explicitly demonstrates all custom xml attributes with their default values:

```xml
<io.sro.collector.auth.CollectorCameraPreview
    ...
    app:cameraScale="fill_center"
    app:overlay_isAdjustViewBounds="false"
    app:overlay_isAlwaysVisible="false"
    app:overlay_scaleType="centerCrop"    
    app:overlay_src="#80FFFFFF"
    app:preview_fadeInDuration="-1"       
    app:preview_fadeOutDuration="-1"
    app:preview_isDisplayLastFrameEnabled="false" #since 0.0.71
 />
```

### Biometric Authentication in Activity

Start authentication:

```kotlin
if (collectorAgent.isAuthRunning() == false) {
    cameraPreview.startAuth()
    isAuthRunning = true
}
```

Stop authentication:

```kotlin
if (collectorAgent.isAuthRunning() == true) {
    cameraPreview.stopAuth()
    isAuthRunning = false
}
```

The following is an example of how to start authentication automatically on switching back to the client app from device Settings (following permissions adjustment):

```kotlin
override fun onResume() {
    super.onResume()
    if (isAuthRunning) {
        preview.startAuth()
    }
}
```

### Named authentic actions

Optionally, authentic action can be named with `actionID`, thus can be configured remotely with different capture frequency if matches server configuration.&#x20;

{% hint style="info" %}
Supported starting version `0.0.59` (2024-05-1) and above
{% endhint %}

```kotlin
cameraPreview.startAuth(actionID = "custom_authentic_action_id")
```

### Authentic Action Start Task

{% hint style="info" %}
Since `0.0.75` (2024-10-01)
{% endhint %}

{% hint style="info" %}
Since `0.0.76` (2024-10-02) `startAuth` and `stopAuth` functions are thread-safe
{% endhint %}

The `startAuth` function returns an `AuthStartTask` object, which allows you to track the task's state. By adding a listener, the task will notify you of intermediate signals (e.g., waiting for configuration completion, initialising the camera, etc.) and terminal signals (success, cancel, failure).

Only one task can be active at a time. Any attempt to start a new AuthenticAction™ flow will cancel the ongoing task.

```kotlin
collectorAgent
    .startAuth(/*optional params*/)
    .addOnAuthStartSignalChangedListener { task, oldSignal, newSignal ->
        // React to signals, etc.
    }
```

Or:

```kotlin
cameraPreview
   .startAuth(/*optional params*/)
   .addOnAuthStartSignalChangedListener { task, oldSignal, newSignal ->
      // React to signals, etc.
   }
```

The task can also be converted into a Flow (`asFlow`) or used within a coroutine as a suspend function (`await`). However, when used as a coroutine, the task will only receive the terminal signal.

As flow:

```kotlin
val task = collectorAgent.startAuth()
scope.launch {
    task
        .asFlow()
        .collectLatest { signal -> /*  React to signals, etc. */ }
}
```

As coroutine:

```kotlin
val task = collectorAgent.startAuth()
scope.launch {
    task.await()
}
```

The task also supports cancellation. Cancelling a task is equivalent to calling `CollectorAgent.get().stopAuth()`. The latter, by the way, also triggers the cancellation signal for the ongoing task.

```kotlin
task.cancel()
```

There are overloaded methods for `startAuth`. By default, `startAuth` relies on the `setOnAuthCompletedListener` callback (i.e., when the SDK setup is completed). Therefore, any attempts to call `startAuth` before the SDK initialisation is complete will result in the task's immediate completion with a terminal signal.

However, your application may want to delay the start of the AuthenticAction™ until the ongoing SDK setup is complete. To achieve this, call `startAuth` with the `awaitAuthSetup` parameter set to `true`. This changes the task's behaviour (only if the SDK setup is incomplete): instead of terminating, the task will receive intermediate signals. This provides an alternative approach to starting `startAuth` without relying on the `setOnAuthCompletedListener`.

```kotlin
collectorAgent.startAuth(
    //...,
    awaitAuthSetup = true,
)
```

However, if the ongoing SDK setup fails due to network connectivity issues, the task will receive a terminal signal. To mitigate this, an additional parameter, `awaitAuthSetupNetworkConnection`, can be set along with `awaitAuthSetup`. This further modifies the task's behaviour: instead of receiving a terminal signal, a network failure will result in an intermediate signal. The SDK will automatically retry the setup and resume the task. Keep in mind that without a network connection, the task may remain active indefinitely.

```kotlin
val task = collectorAgent
    .startAuth(
        //...,
        awaitAuthSetup = true,
        awaitAuthSetupNetworkConnection = true
    )

// optionally configure task, e.g. add listener, observe as coroutine and/or flow.
```

### Submitting custom events

To submit external input events that are not collected automatically by the Collector library please use the following SDK function:

```kotlin
val collectorAgent = CollectorAgent.getInstance(/*...*/)

collectorAgent.submitExternalInputEvent(
    eventType = EventType.Click,
    elementId = 0,
    elementName = "Toggle Auth",
    inputType = InputType.Submit,
    sourceClassName = "Source class Name",
    inputText = "Input Text"
)
```

### Instance Cleanup

{% hint style="info" %}
Since 0.0.73 (2024-09-10)
{% endhint %}

Single SDK instance is suffice for the most usage scenarios. However, SDK supports an ability to clear current instance. This might be useful for advanced scenario, when SDK is used only in limited application scope. To clear existing instance simply perform the following functions:

```kotlin
CollectorAgent.clearInstance()
```

Do not attempt to use instance of `CollectorAgent` after cleanup. These attempts result in errors.  SDK re-initialisation steps are required before using `CollectorAgent` again.

## Troubleshooting

### Compose

{% hint style="info" %}
Jetpack Compose full support is coming soon. In the current version automatic collection and reporting of the form field values may not perform correctly. You're encouraged to use custom fields collection API in that case.
{% endhint %}

### Logs

The SDK generates logs throughout its execution. The logs are being written to logcat. Please refer to the [Android Studio documentation](https://developer.android.com/studio/debug/logcat) for how to review and retrieve these logs.

Debug information (logs) can be controlled via:

<pre class="language-kotlin"><code class="lang-kotlin"><strong>CollectorAgent.get().isDebug = true // set to false for release build
</strong></code></pre>

### Preparing the release with .aar

In case you are experiencing issues when building release application using SDK's .aar files you might need to isolate each .aar file into separate modules, as shown in a figure 2 below.

<figure><img src="/files/bn0MNri7ywNLUcCBIwPa" alt=""><figcaption><p><strong>Figure 2:</strong> <em>".aar" isolation in separate modules.</em></p></figcaption></figure>

Additionally create `build.gradle` file for each isolated module and paste the following content,  adjusting actual .aar file name ("auth-sdk-release.aar" in this example):

```gradle
configurations.maybeCreate("default")
artifacts.add("default", file("auth-sdk-release.aar"))
```

Optionally, in multi-module project it is a good practice to create separate android module that declares isolated modules as `api` dependencies along with the list of dependencies of the section ["Manual importing of the Android Archive Repository (“aar”) File"](#toc148556253) (step 2). This approach centralises all SDK components in one place, making it clear and reusable.

## Tips and tricks

### Permissions

The SDK requires various permissions to perform correctly. The following permissions are required:

* Take pictures and record video
* Device location

The optimal app design should explain how these permissions are utilized and inform the users to enable them.

### Camera Preview

By default `CollectorCameraPreview` has a 50% transparent white overlay, which suits most scenarios. However, if you need a clear image with no overlay, you can remove it either in XML or programmatically.

#### XML

```xml
<io.sro.collector.auth.CollectorCameraPreview
    ...
    app:overlay_src="@null"/> // clears the default #80FFFFFF color overlay
```

#### Programmatically

```kotlin
cameraPreview.setOverlayImageDrawable(null)
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docsjs.ironvest.com/ironvest-authenticaction-developer-documentation/authenticaction-client-sdk/android-programming.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
