Android

FingerprintJS Pro identification in native Android apps

FingerprintJS Pro's native Android integration allows developers to integrate device identification into native Android apps. Visit the official GitHub repository for examples and package downloads.

Please note that these Pro integrations require using our FingerprintJS Pro API and thus need a public API key.

For native device identification for iOS, please go to iOS agent

Installing the agent

Add the repository to Gradle

If your version of Gradle is earlier than 7, add these lines to your build.gradle:

allprojects {   
  repositories {
  ...
  maven { url 'https://jitpack.io' }    
}}

If your version of Gradle is 7 or newer, add these lines to your settings.gradle:

repositories {
  ...
  maven { url "https://jitpack.io" }
}

Add dependencies to your build.gradle file

dependencies {
  implementation 'com.github.fingerprintjs:fingerprintjs-pro-android:v2.0'

  // If you use Java for you project, add also this line
  implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"

When using Kotlin, be sure to specify the version in your build.gradle file:

buildscript {
    ext.kotlin_version = 'your-kotlin-version'
    ...

Note: You can find your Kotlin version in Android Studio > File > Settings > Languages & Frameworks > Kotlin.

Note: The library depends on kotlin-stdlib. If your application is written in Java, add the kotlin-stdlib dependency first — it's lightweight and has excellent backward/forward compatibility.

Lastly, sync Gradle to synchronize all the dependencies to your Android project.

Get the visitor identifier

Retrieve the visitor identifier using your public API key. You can find your public API key in your dashboard.

Kotlin example:

import com.fingerprintjs.android.fpjs_pro.Configuration
import com.fingerprintjs.android.fpjs_pro.FingerprintJSFactory
...

// Initialization
val factory = FingerprintJSFactory(applicationContext)
val configuration = Configuration(
    apiToken = "<<browserToken>>"
  )
 
val fpjsClient = factory.createInstance(
    configuration
)

// Usage
fpjsClient.getVisitorId { result ->
    val visitorId = result.visitorId
    // Use the visitorId
}

Java example:

import com.fingerprintjs.android.fpjs_pro.Configuration;
import com.fingerprintjs.android.fpjs_pro.FingerprintJS;
import com.fingerprintjs.android.fpjs_pro.FingerprintJSFactory;
...

FingerprintJSFactory factory = new FingerprintJSFactory(this.getApplicationContext());
Configuration configuration = new Configuration(
    "<<browserToken>>"
    ); 

FingerprintJS fpjsClient = factory.createInstance(
    configuration
);

fpjsClient.getVisitorId(new Function1<FingerprintJSProResponse, Unit>() {
    @Override
    public Unit invoke(FingerprintJSProResponse result) {
        String visitorId = result.visitorId;
        // Use the visitorId
        return null;
    }
});

How unique and stable is the visitorId?

The ID is completely unique for every device. It is the same for different applications and it does not change after the application is reinstalled. Only factory reset can wipe it out – which is a common and legal case (the device may be resold or gifted to another person).

Configuration

When create instance of the FingerprintJS class there are options that can be configured:

class Configuration @JvmOverloads constructor(
    val apiToken: String,
    val region: Region = Region.US,
    val endpointUrl: String = region.endpointUrl,
    val extendedResponseFormat: Boolean = false
)

Response format

If extendedResponseFormat flag is set in the Configuration class then in the response there will be such fields as shown below:

data class FingerprintJSProResponse(
    val requestId: String,
    val visitorId: String,
    val confidenceScore: ConfidenceScore,
    val visitorFound: Boolean, // Available with extendedResponseFormat == true
    val ipAddress: String, // Available with extendedResponseFormat == true
    val ipLocation: IpLocation?, // Available with extendedResponseFormat == true
    val osName: String, // Available with extendedResponseFormat == true
    val osVersion: String, // Available with extendedResponseFormat == true
    val errorMessage: String? = null
)

data class IpLocation(
    val accuracyRadius: Int,
    val latitude: Double,
    val longitude: Double,
    val postalCode: String,
    val timezone: String,
    val city: City,
    val country: Country,
    val continent: Continent,
    val subdivisions: List<Subdivisions>
) {

    data class City(
        val name: String
    )

    data class Country(
        val code: String,
        val name: String
    )

    data class Continent(
        val code: String,
        val name: String
    )

    data class Subdivisions(
        val isoCode: String,
        val name: String
    )
}

data class ConfidenceScore(
    val score: Double
)

Error handling

fpjsClient.getVisitorId(
          listener = { visitorId ->
            // Handle ID
          },
          errorListener = { error ->
            when(error){
                is ApiKeyRequired -> {
                    val requestId = error.requestId
                  // Handle error
              }
                ...
            }
          })

Error is a sealed class


sealed class Error(
    val requestId: String = UNKNOWN,
    val description: String? = UNKNOWN
)

and it might me one of:

  • ApiKeyRequired
  • ApiKeyNotFound
  • ApiKeyExpired
  • RequestCannotBeParsed
  • Failed
  • RequestTimeout
  • TooManyRequest
  • OriginNotAvailable
  • HeaderRestricted
  • NotAvailableForCrawlBots
  • NotAvailableWithoutUA
  • WrongRegion
  • SubscriptionNotActive
  • UnsupportedVersion
  • InstallationMethodRestricted
  • ResponseCannotBeParsed
  • NetworkError
  • UnknownError

Tag support to store custom data with each identification

fpjsClient.getVisitorId(
      tags = mapOf("sessionId" to sessionId),
      listener = { visitorId ->
          // Handle ID
      },
      errorListener = { error ->
          // Handle error
      })

Additional Resources


Did this page help you?