# Android

{% hint style="success" %}
**Example**: <https://github.com/talsec/Free-RASP-Android/tree/master/FreeRASPDemoApp>
{% endhint %}

{% hint style="info" %}
Let your AI assistant (Cursor, Claude, Gemini, Codex) add freeRASP into your app (experimental): [AI-Assisted Integration](/freerasp/freerasp/integration/android/ai-assisted-integration.md)
{% endhint %}

## 📝 Prerequisites

freeRASP requires a minimum **SDK** level of **23**. To update the minimum SDK level of the application, follow these steps:

1. From the root of your project (or module level), go to the `build.gradle`.
2. Update `minSdkVersion` to at least **23** (Android 6.0) or higher.

{% code title="build.gradle" %}

```gradle
buildscript {
    ext {
      minSdkVersion 23
    }
}
```

{% endcode %}

### Add permissions for checks

Some checks require additional permissions in order to work properly. If your app already has these permissions, you don't need to add them again.

#### Screenshot and Screen Recording Detection

To [detect screenshots](/freerasp/freerasp/wiki/threat-detection/screen-capture.md#screenshot-detection) and screen recordings , add the following permissions to your `AndroidManifest.xml` file inside the `<manifest>` root tag:

```xml
<uses-permission android:name="android.permission.DETECT_SCREEN_CAPTURE" />
<uses-permission android:name="android.permission.DETECT_SCREEN_RECORDING" />
```

{% hint style="warning" %}
Screenshot Detection is supported **on Android 14 (API level 34) and higher**. \
\
Screen Recording Detection is supported **on Android 15 (API level 35) and higher**.\
\
Application of **FLAG\_SECURE** on Android Window or calling `blockScreenCapture(true)` disables this callback.
{% endhint %}

#### Location Spoofing Detection

To detect location spoofing, add the following permissions to your `AndroidManifest.xml` file inside the `<manifest>` root tag:

```xml
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
```

#### Unsecure WiFi Detection

To detect unsecure WiFi, add the following permissions to your `AndroidManifest.xml` file inside the `<manifest>` root tag:

```xml
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
```

{% hint style="warning" %}
[Some permissions also require runtime request. ](https://developer.android.com/training/permissions/requesting)
{% endhint %}

***

## 📦 Add the dependency

Set Talsec's Artifact Registry in your **project's** `settings.gradle` *(or* `build.gradle`*).* You should comment out the relevant section in `settings.gradle`, if you want to use `build.gradle`, as `settings.gradle` is preferred:

*Config via settings.gradle:*

{% tabs %}
{% tab title="settings.gradle (:project)" %}

```gradle
repositories {
    google()
    mavenCentral()
    maven { url "https://jitpack.io" }
    maven { url "https://europe-west3-maven.pkg.dev/talsec-artifact-repository/freerasp" }
}
```

{% endtab %}

{% tab title="settings.gradle.kts (:project)" %}

```kts
repositories {
    google()
    mavenCentral()
    maven { url = uri("https://jitpack.io") }
    maven { url = uri("https://europe-west3-maven.pkg.dev/talsec-artifact-repository/freerasp") }
}
```

{% endtab %}
{% endtabs %}

*Config via build.gradle:*

{% tabs %}
{% tab title="build.gradle (:project)" %}

```gradle
repositories {
    google()
    mavenCentral()
    maven { url "https://jitpack.io" }
    maven { url "https://europe-west3-maven.pkg.dev/talsec-artifact-repository/freerasp" }
}
```

{% endtab %}

{% tab title="build.gradle.kts (:project)" %}

```kts
repositories {
    google()
    mavenCentral()
    maven { url = uri ("https://jitpack.io") }
    maven { url = uri ("https://europe-west3-maven.pkg.dev/talsec-artifact-repository/freerasp") }
}
```

{% endtab %}
{% endtabs %}

{% hint style="warning" %}
Make sure that **Talsec's maven dependency** is at the **last** position.
{% endhint %}

Set dependencies in your **:app** module's `build.gradle`:

{% code title="\[build.gradle (: app)]" %}

```gradle
dependencies {
    // freeRASP SDK  
    implementation 'com.aheaditec.talsec.security:TalsecSecurity-Community:18.0.2'
}
```

{% endcode %}

***

## ⚙️ Setup the Configuration for your App

To ensure freeRASP functions correctly, you need to provide the necessary configuration. All required values must be filled in for the plugin to operate properly. Use the following template to configure the plugin. Detailed descriptions of the configuration options are provided [on the API page](/freerasp/freerasp/integration/android/api.md).

1. To guarantee protection starts immediately, initialize **freeRASP** inside the `onCreate` method of your `Application` subclass. If you don't have a custom `Application` class, create one extending Application:<br>

   <pre class="language-kotlin" data-title="FreeRaspApplication.kt"><code class="lang-kotlin">class FreeRaspApplication : Application() {
       override fun onCreate() {
           super.onCreate()
       }
   }
   </code></pre>

2. Add a new subclass to `AndroidManifest.xml`, inside `<application>` tag:<br>

   <pre class="language-xml" data-title="AndroidManifest.xml"><code class="lang-xml">&#x3C;application
       android:name=".FreeRaspApplication"
   />
   </code></pre>

3. Set up the Configuration for your app with your values, which are explained in more detail in [API](/freerasp/freerasp/integration/android/api.md).<br>

   <pre class="language-kotlin" data-title="FreeRaspApplication.kt"><code class="lang-kotlin">private companion object {
       private const val EXPECTED_PACKAGE_NAME = "com.aheaditec.talsec.demoapp" // Don't use Context.getPackageName!
       private val EXPECTED_SIGNING_CERTIFICATE_HASH_BASE64 = arrayOf(
           "mVr/qQLO8DKTwqlL+B1qigl9NoBnbiUs8b4c2Ewcz0k="
       ) // Replace with your release (!) signing certificate hashes
       private const val WATCHER_MAIL = "your_email_address@example.com" 
       private val SUPPORTED_ALTERNATIVE_STORES = arrayOf(
           "com.sec.android.app.samsungapps"
           // add other stores, such as the Samsung Galaxy Store
       )
       private val IS_PROD = true
       private val KILL_ON_BYPASS = true
   }
   </code></pre>

   <pre class="language-kotlin" data-title="FreeRaspApplication.kt"><code class="lang-kotlin">override fun onCreate() {
       ...
       
       val config = TalsecConfig.Builder(
           EXPECTED_PACKAGE_NAME,
           EXPECTED_SIGNING_CERTIFICATE_HASH_BASE64)
           .watcherMail(WATCHER_MAIL)
           .supportedAlternativeStores(SUPPORTED_ALTERNATIVE_STORES)
           .prod(IS_PROD)
           .killOnBypass(KILL_ON_BYPASS)
           .build()
   }
   </code></pre>

{% hint style="info" %}
**Configuration Parameters**

* **`isProd`** - a boolean flag that determines whether the freeRASP integration is in the Dev or Release version. If you want to learn more about `isProd`, visit this [wiki section](/freerasp/freerasp/wiki/isprod-flag.md).
* **`killOnBypass`** - a boolean flag that enables the freeRASP in-SDK reaction to kill the application if it detects any unwanted manipulation with the callback mechanisms.
* **`watcherMail`** - By providing your watcherMail, you consent to receive security reports, product updates, and other essential communications from Talsec. [Learn more](/freerasp/freerasp/wiki/role-of-watchermail.md) about the role of `watcherMail`.
  {% endhint %}

***

## 👷 Handle detected threats

You can handle the detected threats using **listeners**. For example, you can log the event, show a window to the user or kill the application. See the [Threat detection](/freerasp/freerasp/wiki/threat-detection.md) to learn more details about the performed checks and their importance for app security.

1. Create a `ThreatListener.ThreatDetected` object and override the methods you want to handle. You don't need to override all methods; only implement the ones relevant to your app's security policy.<br>

   <pre class="language-kotlin" data-title="FreeRaspApplication.kt"><code class="lang-kotlin">
   val threatDetectedListener = object : ThreatListener.ThreatDetected() {

       override fun <a data-footnote-ref href="#user-content-fn-1">onRootDetected</a>() {
           println("onRootDetected")
       }
       
       override fun <a data-footnote-ref href="#user-content-fn-2">onDebuggerDetected</a>() {
           println("onDebuggerDetected")
       }
       
       override fun <a data-footnote-ref href="#user-content-fn-3">onEmulatorDetected</a>() {
           println("onEmulatorDetected")
       }
       
       override fun <a data-footnote-ref href="#user-content-fn-4">onTamperDetected</a>() {
           println("onTamperDetected")
       }
       
       override fun <a data-footnote-ref href="#user-content-fn-5">onUntrustedInstallationSourceDetected</a>() {
           println("onUntrustedInstallationSourceDetected")
       }
       
       override fun <a data-footnote-ref href="#user-content-fn-6">onHookDetected</a>() {
           println("onHookDetected")
       }
       
       override fun <a data-footnote-ref href="#user-content-fn-7">onDeviceBindingDetected</a>() {
           println("onDeviceBindingDetected")
       }
       
       override fun <a data-footnote-ref href="#user-content-fn-8">onObfuscationIssuesDetected</a>() {
           println("onObfuscationIssueDetected")
       }
       
       override fun <a data-footnote-ref href="#user-content-fn-9">onScreenshotDetected</a>() {
           println("onScreenshotDetected")
       }
       
       override fun <a data-footnote-ref href="#user-content-fn-10">onScreenRecordingDetected</a>() {
           println("onScreenRecordingDetected")
       }
       
       override fun <a data-footnote-ref href="#user-content-fn-11">onMultiInstanceDetected</a>() {
           println("onMultiInstanceDetected")
       }
       
       override fun <a data-footnote-ref href="#user-content-fn-12">onUnsecureWifiDetected</a>() {
           println("onUnsecureWifiDetected")
       }
       
       override fun <a data-footnote-ref href="#user-content-fn-13">onTimeSpoofingDetected</a>() {
           println("onTimeSpoofingDetected")
       }
       
       override fun <a data-footnote-ref href="#user-content-fn-14">onLocationSpoofingDetected</a>() {
           println("onLocationSpoofingDetected")
       }
       
       override fun onAutomationDetected() {
           println("onAutomationDetected")
       }
       
       override fun <a data-footnote-ref href="#user-content-fn-15">onMalwareDetected</a>(suspiciousApps: List&#x3C;SuspiciousAppInfo>) {
           println("onMalwareDetected")
       }
   }
   </code></pre>

   <div data-gb-custom-block data-tag="hint" data-style="info" class="hint hint-info"><ul><li>If you encounter issues importing <code>ThreatListener.ThreatDetected</code>, please use 'Sync Project with Gradle Files' to resolve them.“</li><li>For the <strong>onMalwareDetected(suspiciousApps: List&#x3C;SuspiciousAppInfo>)</strong> callback, make sure you visit <a href="https://github.com/talsec/freeMalwareDetection-Android/tree/d48b64aa517d5910b7709abd93ea8908d17b858f"><strong>freeMalwareDetection</strong></a>, a powerful feature designed to scan for malicious or suspicious apps.</li></ul></div>

2. Optionally, you can use a device state listener to get additional information about the device state, like passcode lock and HW-backed Keystore state:<br>

   <pre class="language-kotlin" data-title="FreeRaspApplication.kt"><code class="lang-kotlin">val deviceStateListener = object : ThreatListener.DeviceState() {
       
       override fun <a data-footnote-ref href="#user-content-fn-16">onUnlockedDeviceDetected</a>() {
           println("onUnclockedDeviceDetected")
       }
       
       override fun <a data-footnote-ref href="#user-content-fn-17">onHardwareBackedKeystoreNotAvailableDetected</a>() {
           println("onHardwareBackedKeystoreNotAvailableDetected")
       }

       override fun <a data-footnote-ref href="#user-content-fn-18">onDeveloperModeDetected</a>() {
           println("onDeveloperModeDetected")
       }
       
       override fun <a data-footnote-ref href="#user-content-fn-19">onADBEnabledDetected</a>() {
           println("onADBEnabledDetected")
       }

       override fun <a data-footnote-ref href="#user-content-fn-20">onSystemVPNDetected</a>() {
           println("onSystemVPNDetected")
       }
   }
   </code></pre>

3. Optionally, you can use the `RaspExecutionState` listener, to get information about state of check execution:<br>

   <pre class="language-kotlin" data-title="FreeRaspApplication.kt"><code class="lang-kotlin">val raspExecutionListener = object : ThreatListener.RaspExecutionState() {
       
       override fun onAllChecksFinished() {
           println("onAllChecksFinished")
       }
   }
   </code></pre>

4. Modify initialization of `ThreatListener`:<br>

   <pre class="language-kotlin" data-title="FreeRaspApplication.kt"><code class="lang-kotlin">override fun onCreate() {
       ...
       // Register the listeners
       // You can choose which listeners to register based on your needs:
       
       // Option A: Listens only for threats detected
       // ThreatListener(threatDetectedListener).registerListener(this)
       
       // Option B: Listens for threats detected and device state
       // ThreatListener(threatDetectedListener, deviceStateListener).registerListener(this)
       
       // Option C: Listens for threats detected and execution state
       // ThreatListener(threatDetectedListener, raspExecutionListener).registerListener(this)
       
       // Option D: Listens for all threats, device state, and execution state
       ThreatListener(threatDetectedListener, deviceStateListener, raspExecutionListener).registerListener(this)
   }
   </code></pre>

5. *(Optional)* Screen Capture & Recording Protection:
   * You can use **freeRASP** to detect screenshots (`onScreenshotDetected`), screen recordings (`onScreenRecordingDetected`).
   * To actively prevent capture entirely (resulting in a black screen), use `Talsec.blockScreenCapture(activity, true)`. You can verify the blocking status using `Talsec.isScreenCaptureBlocked()`. For more details, see [Screen Capture](/freerasp/freerasp/wiki/threat-detection/screen-capture.md).&#x20;
   * **Prerequisites**: Detection features require Android 14+ (Screenshots) or Android 15+ (Recordings) and specific permissions. Please ensure you have added them as described in the [Add permissions](https://docs.talsec.app/freerasp/integration/android#add-permissions-for-checks) section.
   * **Implementation**: We recommend integrating these methods at the `Application` level using `ActivityLifecycleCallbacks` to ensure they cover the entire app lifecycle:

{% code title="FreeRaspApplication.kt" %}

```kotlin
class FreeRaspApplication : Application() {
    
    override fun onCreate() {
        ...
        registerActivityLifecycleCallbacks(object : ActivityLifecycleCallbacks {
            override fun onActivityCreated(activity: Activity, bundle: Bundle?) {
                Talsec.blockScreenCapture(activity, false)
            }

            override fun onActivityStarted(activity: Activity) {}

            override fun onActivityResumed(activity: Activity) {
                ScreenProtector.registerScreenCallbacks(activity)
            }

            override fun onActivityPaused(activity: Activity) {
                ScreenProtector.unregisterScreenCallbacks(activity)
            }

            override fun onActivityStopped(activity: Activity) {}

            override fun onActivitySaveInstanceState(activity: Activity, bundle: Bundle) {}

            override fun onActivityDestroyed(activity: Activity) {}
        })
    }
}
```

{% endcode %}

{% hint style="info" %}
**ScreenProtector**\
You can detect when a screenshot or recording occurs without blocking it, which is useful for auditing or specific security reactions. The ScreenProtector utility automatically handles Android API level checks (Android 14+ for screenshots, Android 15+ for recordings).
{% endhint %}

***

## 🛡️ Start freeRASP

{% code title="FreeRaspApplication.kt" fullWidth="false" %}

```kotlin
override fun onCreate() {
    ...
    Talsec.start(this, config, TalsecMode.BACKGROUND)
}
```

{% endcode %}

{% hint style="info" %}
We recommend starting Talsec with `TalsecMode.BACKGROUND` to prevent performance impacts in the application.
{% endhint %}

***

## 🌁 Enable source code obfuscation

You can make sure that the obfuscation is enabled by checking the value of `minifyEnabled` property in your **module's** `build.gradle` file.

Read more about why this is important in the[ wiki](/freerasp/freerasp/wiki/source-code-obfuscation.md).

{% tabs %}
{% tab title="build.gradle" %}

```gradle
android {
    ...
    buildTypes {
        release {
            minifyEnabled true
            shrinkResources true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}
```

{% endtab %}

{% tab title="build.gradle.kts" %}

```
android {
    
    // ...

    buildTypes {
        getByName("release") {
            isMinifyEnabled = true
            isShrinkResources = true
            proguardFiles(
                getDefaultProguardFile("proguard-android.txt"),
                "proguard-rules.pro"
            )
        }
    }
}
```

{% endtab %}
{% endtabs %}

***

## 🆔 (Optionally) Set External ID

The `externalId` allows you to send a custom identifier (such as a User ID) to the [Talsec Portal](https://my.talsec.app/). This identifier will be visible in the Dashboard, enabling you to correlate security incidents with specific users in your system.

```kotlin
// pass your custom data (as @NonNull String)
val yourCustomData = "user_123-456"
val result = Talsec.storeExternalId(this, yourCustomData)

when(result) {
    is ExternalIdResult.Success -> {
        println("External ID successfully set.")
    }
    is ExternalIdResult.Error -> {
    println("Failed to set External ID: ${result.errorMsg}")
}

if (result is ExternalIdResult.Error) {
    println("Failed to set External ID: ${result.errorMsg}")
}
```

{% hint style="info" %}
**Requirements**

* **Allowed characters**: Only alphanumeric characters (a-z, A-Z, 0-9) and the following special characters: +, \_, -, /, :, =.
* If the ID contains any other characters, the method returns ExternalIdResult. Error and the value is not stored.
  {% endhint %}

***

## ☢️ (Optionally) Integrate freeMalwareDetection

**freeMalwareDetection** is a powerful feature designed to enhance the security of your Android application by quickly and efficiently **scanning for malicious or suspicious applications** (e.g. Android malware) based on **various blacklists and security policies**.&#x20;

It helps to detect apps with **suspicious package names, hashes, or potentially dangerous permissions**.

Visit the [freeMalwareDetection](https://docs.talsec.app/freemalwaredetection) repository to learn more about this feature! For the integration, refer to the [integration guide](https://docs.talsec.app/freemalwaredetection/integration-guide/malware-detection-configuration) for the Android platform.

***

## 🖥️ Check Talsec Portal

Check out [Data Visualisation Portal](/freerasp/freerasp/data-visualisation-portal.md) and register using your [watcherMail](/freerasp/freerasp/wiki/role-of-watchermail.md) to see your data. If you integrated the SDK successfully, the application will be present **after a few hours**. The visualisations will be active later due to the bucketing mechanism.

{% hint style="warning" %}
You have to use the **same email for the Portal** as you used for the **watcherMail** parameter.
{% endhint %}

[^1]: Learn more: <https://docs.talsec.app/freerasp/wiki/threat-detection/detecting-rooted-or-jailbroken-devices>

[^2]: Learn more: <https://docs.talsec.app/freerasp/wiki/threat-detection/debugger-detection>

[^3]: Learn more: <https://docs.talsec.app/freerasp/wiki/threat-detection/emulator-detection>

[^4]: Learn more: <https://docs.talsec.app/freerasp/wiki/threat-detection/app-tampering-detection>

[^5]: Learn more: <https://docs.talsec.app/freerasp/wiki/threat-detection/detecting-unofficial-installation>

[^6]: Learn more: <https://docs.talsec.app/freerasp/wiki/threat-detection/hook-detection>

[^7]: Learn more: <https://docs.talsec.app/freerasp/wiki/threat-detection/device-binding-detection>

[^8]: Learn more: <https://docs.talsec.app/freerasp/wiki/threat-detection/missing-obfuscation-detection-android-devices-only>

[^9]: Learn more: <https://docs.talsec.app/freerasp/wiki/threat-detection/screen-capture#screenshot-detection>

[^10]: Learn more: <https://docs.talsec.app/freerasp/wiki/threat-detection/screen-capture#screen-recording-detection>

[^11]: Learn more: [https://docs.talsec.app/freerasp/wiki/threat-detection/multi-instance-detection](https://docs.talsec.app/freerasp/wiki/threat-detection/multi-instance-detection-android-devices-only)

[^12]: Learn more:[https://docs.talsec.app/freerasp/wiki/threat-detection/unsecure-wifi-detection-android-only](https://docs.talsec.app/freerasp/wiki/threat-detection/multi-instance-detection-android-devices-only)

[^13]: Learn more:\
    [https://docs.talsec.app/freerasp/wiki/threat-detection/time-spoofing-detection-android-only](https://docs.talsec.app/freerasp/wiki/threat-detection/multi-instance-detection-android-devices-only)

[^14]: Learn more:\
    [https://docs.talsec.app/freerasp/wiki/threat-detection/location-spoofing-detection-android-only](https://docs.talsec.app/freerasp/wiki/threat-detection/multi-instance-detection-android-devices-only)

[^15]: Learn more:\
    <https://docs.talsec.app/freemalwaredetection>

[^16]: Learn more: <https://docs.talsec.app/freerasp/wiki/threat-detection/passcode>

[^17]: Learn more: <https://docs.talsec.app/freerasp/wiki/threat-detection/secure-hardware-detection-keystore-keychain-secure-storage-check>

[^18]: Learn more: <https://docs.talsec.app/freerasp/wiki/threat-detection/developer-mode-detection-android-devices-only>

[^19]: Learn more: <https://docs.talsec.app/freerasp/wiki/threat-detection/adb-enabled-detection-android-devices-only>

[^20]: Learn more: <https://docs.talsec.app/freerasp/wiki/threat-detection/system-vpn-detection>


---

# 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.talsec.app/freerasp/freerasp/integration/android.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.
