Skip to content

Client to Server

For this integration method, the DeviceAssure library collects device data and automatically sends it to the DeviceAssure API for validation. Results are returned directly to your application via callbacks.

This is the recommended approach as it automatically uses the nearest DeviceAssure service endpoint for optimal response time.

Note: A valid licence key is required for Client to Server integration.


Overview

There are three main steps to validate a device:

  1. Initialize the DeviceAssure library with the application context
  2. Call the check() method with your licence key and callback handler
  3. Handle the validation results returned via the callback

Implementation

Step 1: Initialize the Library

Initialize DeviceAssure in your Application class's onCreate() method:

import android.app.Application
import com.deviceassure.android.library.DeviceAssure

class MyApplication : Application() {

    override fun onCreate() {
        super.onCreate()
        DeviceAssure.init(applicationContext)
    }
}
import android.app.Application;
import com.deviceassure.android.library.DeviceAssure;

public class MyApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        DeviceAssure.init(this.getApplicationContext());
    }
}

Step 2: Define the Callback Interface

Create a delegate interface to handle responses:

import org.json.JSONObject

interface DeviceAssureDelegate {
    fun onResponse(json: JSONObject)
    fun onError(error: String)
}
import org.json.JSONObject;

public interface DeviceAssureDelegate {
    void onResponse(JSONObject json);
    void onError(String error);
}

Step 3: Create a Callback Handler

import com.deviceassure.android.library.Callback
import org.json.JSONObject

class DeviceAssureCallback(private val delegate: DeviceAssureDelegate) : Callback {

    override fun taskComplete(result: JSONObject) {
        delegate.onResponse(result)
    }

    override fun handleError(errorStr: String) {
        delegate.onError(errorStr)
    }

    override fun progressUpdate(percent: Int?) {
        // Track progress if needed
    }
}
import org.json.JSONObject;
import com.deviceassure.android.library.Callback;

public class DeviceAssureCallback implements Callback {

    private DeviceAssureDelegate delegate;

    public DeviceAssureCallback(DeviceAssureDelegate delegate) {
        this.delegate = delegate;
    }

    @Override
    public void taskComplete(JSONObject result) {
        delegate.onResponse(result);
    }

    @Override
    public void handleError(String errorStr) {
        delegate.onError(errorStr);
    }

    @Override
    public void progressUpdate(Integer percent) {
        // Track progress if needed
    }
}

Note: Callback also declares two deprecated hooks, statusUpdate() and a no-argument taskComplete(). The library never calls either and they do not need to be implemented.

Step 4: Perform Validation

Call the check() method from anywhere in your application:

DeviceAssure.check("<LICENCE_KEY>", DeviceAssureCallback(this))
DeviceAssure.check("<LICENCE_KEY>", new DeviceAssureCallback(this));

Complete Example

import android.app.Application
import android.util.Log
import com.deviceassure.android.library.DeviceAssure
import org.json.JSONObject

class MyApplication : Application(), DeviceAssureDelegate {

    override fun onCreate() {
        super.onCreate()

        // Initialize the library
        DeviceAssure.init(applicationContext)

        // Perform validation
        DeviceAssure.check("<LICENCE_KEY>", DeviceAssureCallback(this))
    }

    override fun onResponse(json: JSONObject) {
        Log.d(TAG, "Validation result: $json")
        // Check the "result" field for AUTHENTIC, NON-AUTHENTIC, etc.
    }

    override fun onError(error: String) {
        Log.e(TAG, "Validation error: $error")
    }

    companion object {
        private const val TAG = "DeviceAssure"
    }
}
import android.app.Application;
import android.util.Log;
import org.json.JSONObject;
import com.deviceassure.android.library.DeviceAssure;

public class MyApplication extends Application implements DeviceAssureDelegate {

    private static final String TAG = "DeviceAssure";

    @Override
    public void onCreate() {
        super.onCreate();

        // Initialize the library
        DeviceAssure.init(this.getApplicationContext());

        // Perform validation
        DeviceAssure.check("<LICENCE_KEY>", new DeviceAssureCallback(this));
    }

    @Override
    public void onResponse(JSONObject json) {
        Log.d(TAG, "Validation result: " + json.toString());
        // Check the "result" field for AUTHENTIC, NON-AUTHENTIC, etc.
    }

    @Override
    public void onError(String error) {
        Log.e(TAG, "Validation error: " + error);
    }
}

The Suspending API

Kotlin callers can use checkAsync() instead of a callback. It suspends until the validation completes and returns a ValidationResult, so the outcome is handled at the call site rather than in a separate class.

Note: The suspending API is for Kotlin callers. A suspend function compiles to a method that takes a Continuation parameter, which is not a usable API from Java, so Java integrators use the callback API shown above — it runs the same validation and reports the same outcomes.

Call it from any coroutine scope — for example an Activity's lifecycleScope:

import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import com.deviceassure.android.library.DeviceAssure
import com.deviceassure.android.library.ValidationResult
import kotlinx.coroutines.launch

class ValidationActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        lifecycleScope.launch {

            when (val result = DeviceAssure.checkAsync("<LICENCE_KEY>")) {
                is ValidationResult.Success -> Log.d(TAG, "Validation result: ${result.response}")
                is ValidationResult.Error -> Log.e(TAG, "Validation error: ${result.message}")
            }
        }
    }

    companion object {
        private const val TAG = "DeviceAssure"
    }
}

Note: This example uses two dependencies you need to declare yourself, for different reasons: launch comes from org.jetbrains.kotlinx:kotlinx-coroutines-android — the library already supplies this at runtime, but not on your compile classpath, so writing this code needs your own compile-time declaration too — and lifecycleScope from androidx.lifecycle:lifecycle-runtime-ktx, which the library does not use at all. See Runtime Dependencies for the coroutines compile-classpath requirement.

ValidationResult is a sealed type with exactly two cases, so a when over it needs no else branch:

Case Property
ValidationResult.Success response - the JSON response from the DeviceAssure API
ValidationResult.Error message - the reason the validation did not complete

It also provides convenience accessors, so you do not have to branch explicitly:

Member Behaviour
isSuccess / isError Whether the validation completed
getOrNull() The response, or null on error
getOrThrow() The response, or throws ValidationException on error
onSuccess { } / onError { } Runs the given action for that case, and returns the result so calls can be chained

For example:

lifecycleScope.launch {

    DeviceAssure.checkAsync("<LICENCE_KEY>")
            .onSuccess { response -> Log.d(TAG, "Validation result: $response") }
            .onError { message -> Log.e(TAG, "Validation error: $message") }
}

When to Call Validation

The check() method can be called from anywhere in the application, but it is recommended to call it:

  • On application install
  • On application create (onCreate())

Exception: If certain permissions are required before calling the library (e.g., to allow collection of the TAC), wait until those permissions are granted.


Performance Notes

  • The library uses a background thread to avoid blocking the main UI thread
  • If background processing doesn't complete within 10 seconds, it terminates and returns data collected up to that point
  • For best results, request necessary permissions before calling validation

See Also