# User Identifier & Properties

{% hint style="info" %}
User Identifier Management

User Identifiers are used to uniquely identify users. For information about the meaning and importance of User Identifiers, and how to choose them, refer to the [Manage User Identifiers](/en/getting-started/user-identifier.md) documentation.
{% endhint %}

## User Identifier

### Default Identifiers Provided by Hackle

The Android SDK includes functionality to manage the device's identifier. Therefore, users can be automatically identified without separately providing a User Identifier.

You can query the identifiers managed by the SDK as follows.

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
// 디바이스ID 가져오기
val deviceId = hackleApp.deviceId

// 세션 ID 가져오기
val sessionId = hackleApp.sessionId

// 사용자 정보 모두 가지고 오기
val user = hackleApp.user
```

{% endtab %}

{% tab title="Java" %}

```java
// 디바이스ID 가져오기
String deviceId = hackleApp.getDeviceId();

// 세션 ID 가져오기
String sessionId = hackleApp.getSessionId();

// 사용자 정보 모두 가지고 오기
User user = hackleApp.getUser();
```

{% endtab %}
{% endtabs %}

#### Modify Device ID

You can inject a custom device ID instead of using the device ID provided by Hackle.

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
// 디바이스 ID 변경
hackleApp.setDeviceId("CUSTOM_DEVICE_ID")

// 빌더 패턴 사용
val user = User.builder()
    .deviceId("CUSTOM_DEVICE_ID") // 디바이스 ID
    .build()

hackleApp.setUser(user)
```

{% endtab %}

{% tab title="Java" %}

```java
// 디바이스 ID 변경
hackleApp.setDeviceId("CUSTOM_DEVICE_ID");
```

{% endtab %}
{% endtabs %}

#### Set User Identifier (User ID)

You can set the identifier for a logged-in user.

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
// 로그인 한 사용자 ID 추가
hackleApp.setUserId("LOGIN_ID")

// 빌더 패턴 사용
val user = User.builder()
    .userId("LOGIN_ID") // 사용자 ID
    .build()

hackleApp.setUser(user)
```

{% endtab %}

{% tab title="Java" %}

```java
// 로그인 한 사용자 ID 추가
hackleApp.setUserId("LOGIN_ID");
```

{% endtab %}
{% endtabs %}

### Additional Identifiers

You can add identifier types other than the default identifiers (deviceId, userId) as follows.

{% hint style="info" %}
Additional identifiers are not integrated with the [Hackle ID](/en/getting-started/user-identifier/hackle-id.md).
{% endhint %}

{% hint style="danger" %}
Calling `setUser` overwrites the current device's user information.

* If you are currently using userId A and call `setUser` without passing userId A, the userId changes from A to null.
* If you are currently using a custom deviceId and call `setUser` without passing the current deviceId, the custom deviceId reverts to the Hackle deviceId.
* If you use additional identifiers and do not pass them when calling `setUser`, the additional identifiers are reset.
* For properties, the cached properties on the device may be retained or reset in the following cases:
  * If the userId and deviceId are the same before and after `setUser`, cached properties are retained.
  * If the userId or deviceId changes before and after `setUser`, cached properties are deleted.
    {% endhint %}

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
import io.hackle.sdk.common.User

val user = User.builder()
    .userId("143")                   // 사용자 ID (핵클 통합 식별자 사용가능)
    .deviceId("ae2182e0")            // 디바이스 ID (핵클 통합 식별자 사용가능)
    .identifier("myCustomId", "42")  // Custom ID
    .build()

hackleApp.setUser(user)
```

{% endtab %}

{% tab title="Java" %}

```java
import io.hackle.sdk.common.User

User user = User.builder()
    .userId("143")                   // 사용자 ID (핵클 통합 식별자 사용가능)
    .deviceId("ae2182e0")            // 디바이스 ID (핵클 통합 식별자 사용가능)
    .identifier("myCustomId", "42")  // Custom ID
    .build();

hackleApp.setUser(user);
```

{% endtab %}
{% endtabs %}

## User Property

The Hackle SDK supports adding user properties.

* Properties must be sent as key-value pairs (Property Key and Property Value).
* A maximum of 128 properties can be added.

<table><thead><tr><th width="133.04296875">Category</th><th width="127.60546875">Type</th><th>Constraints</th></tr></thead><tbody><tr><td>Property Key</td><td><code>string</code></td><td><ul><li>Character limit is 128 characters.</li><li>Case-insensitive.</li><li>For example, AGE and age are recognized as the same Property Key.</li></ul></td></tr><tr><td>Property Value</td><td><code>boolean</code>, <code>string</code>, <code>number</code>, <code>array</code></td><td><ul><li>For string type, the character limit is 1024 characters.</li><li>String type is case-sensitive.</li><li>For example, APPLE and apple are recognized as different Property Values.</li><li>For number type, up to 15 integer digits and up to 6 decimal places are supported.</li></ul></td></tr></tbody></table>

### Add User Property

You can add a user property simply. Calling the function below works the same as adding a property using `set` in a `PropertyOperations` object.

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
// 속성 설정
hackleApp.setUserProperty("gender", "female");
```

{% endtab %}

{% tab title="Java" %}

```java
// 속성 설정
hackleApp.setUserProperty("gender", "female");
```

{% endtab %}
{% endtabs %}

### Configure User Properties

You can add or remove user properties.

<table><thead><tr><th width="150">Supported Functions</th><th>Description</th></tr></thead><tbody><tr><td><code>set</code></td><td>Sets a User Property. If a Property Value already exists for the Property Key, it is overwritten.</td></tr><tr><td><code>setOnce</code></td><td><p>Sets a User Property value only once. If a property already exists for the Property Key, it is ignored.</p><p>For example, you can use this to set a user's registration date or initial sign-up location.</p></td></tr><tr><td><code>unset</code></td><td>Removes a User Property.</td></tr><tr><td><code>clearAll</code></td><td>Removes all User Properties.</td></tr></tbody></table>

Instantiate a `PropertyOperations` object with the user properties you want to configure. Then call `updateUserProperties` to update the user properties. You can configure multiple properties at once.

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
import io.hackle.sdk.common.PropertyOperations;

// 속성 설정
var operations = PropertyOperations.builder()
    .set("age", 42)
    .set("grade", "GOLD")
    .setOnce("sign_up_date", "2020-07-03")
    .build();

hackleApp.updateUserProperties(operations);

// 속성 지우기
var clearOperations = PropertyOperations.clearAll();

hackleApp.updateUserProperties(clearOperations);
```

{% endtab %}

{% tab title="Java" %}

```java
import io.hackle.sdk.common.PropertyOperations;

// 속성 설정
PropertyOperations operations = PropertyOperations.builder()
    .set("age", 42)
    .set("grade", "GOLD")
    .setOnce("sign_up_date", "2020-07-03")
    .build();

hackleApp.updateUserProperties(operations);

// 속성 지우기
PropertyOperations clearOperations = PropertyOperations.clearAll();

hackleApp.updateUserProperties(clearOperations);
```

{% endtab %}
{% endtabs %}

## Reset User

You need to reset the previously configured information. When reset, all previously configured identifiers and properties are cleared.

{% hint style="danger" %}
Resetting the user also clears all user properties stored on the server. If you want to handle logout, use `hackleApp.setUserId(null)`.

Setting null to userId handles logout on the client side.
{% endhint %}

```kotlin
hackleApp.resetUser();
```


---

# 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://docs.hackle.io/en/development-guide/android/user-identifier.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.
