ForgeRock Developer Experience

Set up device profiling in Android apps

This page shows how to detect the DeviceProfileCallback, how to collect the device profile, and how to send the profile to AM.

AM includes collected device information in its audit logs by default.

To configure AM to filter out this information and ensure no personally identifiable information (PII) is written to the audit logs, refer to Prevent auditing of device data.

Handle a device profile callback

If an authentication journey uses the device profile node, the SDK returns DeviceProfileCallback to collect device attributes.

You use various SDK methods to handle the callback.

Use the default device profile callback

Call the DeviceProfileCallback.execute() method to collect the device profile:

callback.execute(context, new FRListener<Void>() {
public void onSuccess(Void result) {
// call next


public void onException(Exception e) {

Customize the device profile callback

  1. Extend the callback that you want to override, providing two constructors that match the parent constructors.

  2. Annotate the constructor with the @Keep annotation.

  3. Override the default implementation:

    public class MyCustomDeviceProfileCallback extends DeviceProfileCallback {
     public MyCustomDeviceProfileCallback() {
     public MyCustomDeviceProfileCallback(JSONObject jsonObject, int index) {
         super(jsonObject, index);
     public void execute(Context context, FRListener<Void> listener) {
         super.execute(context, listener);
  4. Register the callback:


Manually collect device profile information

Instead of responding to a device callback, your app can get the device profile using default collectors.

You can also modify the default collectors. A set of collectors are predefined.

The FRDevice uses the default predefined collector to collect device profile:

The following code collects the device profile using the default collectors:

FRDeviceCollector.DEFAULT.collect(context, listener);

Default collectors

Collector name Description


Main collector that includes other collectors and provides a collector version.


Collect BLE support information of the device.


Collect browser information of the device; specifically, the User-Agent.


Collect camera information of the device.


Collect display information of the device.


Collect hardware-related information, such as the number of CPUs, number of active CPUs, and so on.


Collect location Information of the device.


Collect network information of the device.


Collect platform-related information, such as device jailbreak status, time zone/locale, OS version, device name, and device model.


Collect telephony information of the device.

Sample device profile

  "identifier": "d50cdb5ce8d055a3-86bd35e1b975a14d76b40940112c2380264c8efd",
  "metadata": {
    "platform": {
      "platform": "Android",
      "version": 31,
      "device": "emulator64_x86_64_arm64",
      "deviceName": "sdk_gphone64_x86_64",
      "model": "sdk_gphone64_x86_64",
      "brand": "google",
      "locale": "en_US",
      "timeZone": "America/Vancouver",
      "jailBreakScore": 1
    "hardware": {
      "hardware": "ranchu",
      "manufacturer": "Google",
      "storage": 5951,
      "memory": 1968,
      "cpu": 4,
      "display": {
        "width": 1080,
        "height": 2148,
        "orientation": 1
      "camera": {
        "numberOfCameras": 2
    "browser": {
      "userAgent": "Mozilla/5.0 (Linux; Android 12; sdk_gphone64_x86_64 Build/SPB5.210812.003; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/91.0.4472.114 Mobile Safari/537.36"
    "bluetooth": {
      "supported": true
    "network": {
      "connected": true
    "telephony": {
      "networkCountryIso": "us",
      "carrierName": "T-Mobile"
  "location": {
    "latitude": 37.4219711,
    "longitude": -122.0849955
  "lastSelectedDate": 1634068456582,
  "alias": "sdk_gphone64_x86_64"

Create a custom collector

  1. Create a custom "DeviceCollector" class that implements the DeviceCollector interface:

    public class MyCustomMetadataCollector implements DeviceCollector {
     private static final List<DeviceCollector> COLLECTORS = new ArrayList<>();
     static {
         //Pick from existing Collector or implement your own collector
         COLLECTORS.add(new PlatformCollector());
         COLLECTORS.add(new NetworkCollector());
         COLLECTORS.add(new TelephonyCollector());
     public String getName() {
         return "metadata";
     public void collect(Context context, FRListener<JSONObject> listener) {
         collect(context, listener, new JSONObject(), COLLECTORS);
  2. Use FRDeviceCollectorBuilder to add your custom Collector:

    public class MyCustomDeviceProfileCallback extends DeviceProfileCallback {
     public MyCustomDeviceProfileCallback() {
     public MyCustomDeviceProfileCallback(JSONObject jsonObject, int index) {
         super(jsonObject, index);
     public void execute(Context context, FRListener<Void> listener) {
         FRDeviceCollector.FRDeviceCollectorBuilder builder = FRDeviceCollector.builder();
         if (isMetadata()) {
             builder.collector(new MyCustomMetadataCollector());
         if (isLocation()) {
             builder.collector(new LocationCollector());
    , new FRListener<JSONObject>() {
             public void onSuccess(JSONObject result) {
                 Listener.onSuccess(listener, null);
             public void onException(Exception e) {
                 Listener.onException(listener, null);

Device profile attributes

By default, the ForgeRock SDK collects the following device attributes:

Attribute Value


A unique ID for the device.

To learn more about the device identifier, refer to Uniquely identifying devices.


The location of a device (longitude and latitude values).

This is configured in the node and requires user permissions.


Metadata for the device, including:


The device OS, such as Android or iOS.


The name of the device.


The locale of the device, such as en.


The time zone of the device, such as Africa/Johannesburg.


The brand of the device, such as Apple.


A value between 0 and 1 that denotes the tampering level for a device.

Obtain user permission for the device location

Your app requires the user’s authorization to access the device location.

For information about how to request the authorization, refer to Request location permissions.

Implement default jailbreak/rooted device detection

The FRRootDetector class is responsible for analyzing whether the device is tampered.

The class analyzes the device by using multiple device tamper detectors, and returns the highest score in the range between 0.0 to 1.0 from all the detectors.

You can customize the metadata.platform.jailBreakScore with Root Detector.

Sample using default tamper detection:

// The DEFAULT Detector uses all available detectors in the SDK to determine if the device is rooted.
RootDetector rootDetector = FRRootDetector.DEFAULT;

// Check if device is rooted
double rootedScore = rootDetector.isRooted(context)

// Evaluate the result
if rootedScore == 0.0 {
    // Detectors score result with 0.0, likely device is not rooted
else if rootedScore <= 0.5 {
    // Some of the detectors returned a possible positive result that indicates the device might be rooted
else {
    // Most of the detectors returned a possible positive result that indicates the device is likely rooted

Customize jailbreak/rooted detection

The SDKs provide a set of industry-standard detectors that allow you to customize the detectors to use.

Sample custom tamper detection code:

// Using Builder to choose two detectors
RootDetector rootDetector = FRRootDetector.builder()
        .detector(new SuCommandDetector())
        .detector(new RootAppDetector())

// Get result
double rootedScore = rootDetector.isRooted(context)

Implement custom detectors

You can provide your own detectors by implementing the RootDetector interface on Android. The interface represents the definition of an individual analyzer for detecting when the device is rooted or jailbroken.

Each detector determines whether the device is rooted or jailbroken. Each collector returns a result score as a Double, within the range of 0.0 to 1.0.

Sample custom detector code:

// Add custom detector to RootDetector
RootDetector rootDetector = FRRootDetector.builder()
        .detector(new RootDetector() {
            public double isRooted(Context context) {
                return 0;

// Get result
double rootedScore = rootDetector.isRooted(context);

More information

Copyright © 2010-2024 ForgeRock, all rights reserved.