# Flutter

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

## 📝 Prerequisites

The freeRASP has the following prerequisites that must be met before starting:

* Minimum SDK level: **23 or higher**
* Gradle version: **8.12.1 or higher**
* Compile SDK version: **36**
* Kotlin version: **2.1.0**

{% hint style="info" %}
Did you know Talsec is a big fan of Flutter? 🥳 Check out the great Flutter-first [security articles](https://docs.talsec.app/appsec-articles#flutter-security) we've prepared together with the community!
{% endhint %}

### Android

Some versions of Flutter projects, by default, support lower levels of minimum SDK or Gradle version.

#### Update **minimum SDK and compile SDK level** :

* From the root of your project, go to `android` **>** `app` **>** `build.gradle`
* In `defaultConfig,` update `minSdkVersion` property to at least **23** (Android 6.0) or higher.

{% code title="android/app/build.gradle" %}

```gradle
android {
    compileSdk 35
    // ... some other declarations ...
    defaultConfig {
        minSdkVersion 23
        // ... some other declarations ...
    }
}
```

{% endcode %}

#### Update Gradle and Kotlin version:

* From the root of your project, go to `android` **>** `settings.gradle`
* In `plugins`
  * Update `version` of `com.android.application` plugin to **8.8.1**
  * Update `version` of `org.jetbrains.kotlin.android plugin` to **2.1.0**

{% code title="android/settings.gradle" %}

```gradle
plugins {
    id "dev.flutter.flutter-plugin-loader" version "1.0.0"
    id "com.android.application" version "8.8.1" apply false
    id "org.jetbrains.kotlin.android" version "2.1.0" apply false
}
```

{% endcode %}

In older projects using imperative approach, the paths may be different:

* From the root of your project, go to `android`  **>** `build.gradle`
* In `dependencies` , update version of `com.android.tools.build:gradle` dependecy to **8.8.1**

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

```gradle
dependencies {
    classpath 'com.android.tools.build:gradle:8.8.1'    
    classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
```

{% endcode %}

Then you also need to update gradle wrapper:

* From the root of your project, go to `android` **>** `gradle`**>** `wrapper` **>** `gradle-wrapper.properties`
* In `distributionUrl` update version to **8.12.1**

{% code title="android/gradle/wrapper/gradle-wrapper.properties" %}

```gradle
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12.1-all.zip
```

{% 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 %}

### Utilize active protection

To utilize active protection, you can use

```dart
await Talsec.instance.blockScreenCapture(enabled: true)
```

To check whether the screen capture is blocked, you can use:

```dart
await Talsec.instance.isScreenCaptureBlocked()
```

For more details about all these screen capture methods, see [Screen Capture](/freerasp/freerasp/wiki/threat-detection/screen-capture.md).

### iOS

**Xcode 15** is required to be able to build the application

***

## 📦 Install the plugin

Run the following command inside the project directory to add the freeRASP dependency:

```sh
flutter pub add freerasp
```

***

## ⚙️ Setup the Configuration for your App

To ensure freeRASP functions correctly, you need to provide the necessary configuration and initialize it. All required values must be filled in for the plugin to operate properly. Detailed descriptions of the configuration options are provided[ on the API page](/freerasp/freerasp/integration/flutter/api.md#talsecconfig).

For Android apps, you must get your expected signing certificate hashes in Base64 form. You can go through[ this manual](/freerasp/freerasp/wiki/getting-signing-certificate-hash.md) to learn how to sign your app in more detail, including manual signing and using Google's Play app signing.&#x20;

In the entry point to your app, import freeRASP and add the following code:

{% code title="main.dart" %}

```dart
import 'package:freerasp/freerasp.dart';

void main() {

  // This line is important!
  WidgetsFlutterBinding.ensureInitialized();

  // create a configuration for freeRASP
  final config = TalsecConfig(
    /// For Android
    androidConfig: AndroidConfig(
      packageName: 'your.package.name',
      signingCertHashes: [
        'mVr/qQLO8DKTwqlL+B1qigl9NoBnbiUs8b4c2Ewcz0k='
      ], // Replace with your release (!) signing certificate hash(es)
      supportedStores: ['com.sec.android.app.samsungapps'],
    ),

    /// For iOS
    iosConfig: IOSConfig(
      bundleIds: ['YOUR_APP_BUNDLE_ID'],
      teamId: 'M8AK35...',
    ),
    watcherMail: 'your_email_address@example.com', // for Security Reports, Talsec Portal, Updates
    isProd: true,
    killOnBypass: true,
  );
}
```

{% endcode %}

{% hint style="warning" %}
*It is necessary that Flutter Bindings are initialized. This can be satisfied by calling `WidgetsFlutterBinding.ensureInitialized()`, as shown in the code snippet above.*
{% endhint %}

{% 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

freeRASP executes periodical checks when the application is running. 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) in the wiki to learn more details about the performed checks and their importance for app security.

freeRASP reacts to threats using `ThreatCallback`. Internally, each threat has its own callback (of `VoidCallback` type), which is called when a threat is detected.

<pre class="language-dart" data-title="main.dart"><code class="lang-dart">import 'package:freerasp/freerasp.dart';

void main() {

  // Setting up callbacks
  final callback = ThreatCallback(
      <a data-footnote-ref href="#user-content-fn-1">onAppIntegrity</a>: () => print("App integrity"),
      <a data-footnote-ref href="#user-content-fn-2">onObfuscationIssues</a>: () => print("Obfuscation issues"),
      <a data-footnote-ref href="#user-content-fn-3">onDebug</a>: () => print("Debugging"),
      <a data-footnote-ref href="#user-content-fn-4">onDeviceBinding</a>: () => print("Device binding"),
      <a data-footnote-ref href="#user-content-fn-4">onDeviceID</a>: () => print("Device ID"),
      <a data-footnote-ref href="#user-content-fn-5">onHooks</a>: () => print("Hooks"),
      <a data-footnote-ref href="#user-content-fn-6">onPasscode</a>: () => print("Passcode not set"),
      <a data-footnote-ref href="#user-content-fn-7">onPrivilegedAccess</a>: () => print("Privileged access"),
      <a data-footnote-ref href="#user-content-fn-8">onSecureHardwareNotAvailable</a>: () => print("Secure hardware not available"),
      <a data-footnote-ref href="#user-content-fn-9">onSimulator</a>: () => print("Simulator"),
      <a data-footnote-ref href="#user-content-fn-10">onSystemVPN</a>: () => print("System VPN"),
      <a data-footnote-ref href="#user-content-fn-11">onDevMode</a>: () => print("Developer mode"),
      <a data-footnote-ref href="#user-content-fn-12">onADBEnabled</a>: () => print("USB debugging enabled"),
      <a data-footnote-ref href="#user-content-fn-13">onUnofficialStore</a>: () => print("Unofficial store"),
      <a data-footnote-ref href="#user-content-fn-14">onScreenshot</a>: () => print("Screenshot"),
      <a data-footnote-ref href="#user-content-fn-15">onScreenRecording</a>: () => print("Screen recording"),
      <a data-footnote-ref href="#user-content-fn-16">onMultiInstance</a>: () => print("Multi instance"),
      <a data-footnote-ref href="#user-content-fn-17">onUnsecureWifi</a>: () => print("Unsecure wifi"),
      <a data-footnote-ref href="#user-content-fn-18">onLocationSpoofing</a>: () => print("Location spoofing"),
      <a data-footnote-ref href="#user-content-fn-19">onTimeSpoofing</a>: () => print("Time spoofing"),
      onAutomation: () => print("Automation detected"),
      onMalware: (suspiciousApps) => print("Suspicous apps")
  );

  // Attaching listener
  Talsec.instance.attachListener(callback);
}
</code></pre>

Optionally, you can implement `RaspExecutionStateCallback` to listen whether initial checks were done or not:

```dart
import 'package:freerasp/freerasp.dart';

void main() {
  // Some other code...
  
  final raspExecutionStateCallback = RaspExecutionStateCallback(
      onAllChecksDone: () => print("All checks done")

  // Attaching listener
  Talsec.instance.attachExecutionStateListener(callback);
}
```

***

## 🛡️ Start freeRASP

Start freeRASP to detect threats just by adding this line below the created config and the callback handler:

```dart
void main() async {

  // start freeRASP
  await Talsec.instance.start(config);
}
```

{% hint style="info" %}
For the version you’re integrating, you can find the specific **dSYMs** for debugging in [Releases](https://github.com/talsec/Free-RASP-Flutter/releases).
{% endhint %}

***

## 🌁 Enable source code obfuscation

In order to provide as much protection as possible, freeRASP enhances security measures by implementing ProGuard consumer rules, which obfuscate specific sections of the SDK. **However, these rules are applied to your Android app code as well due to inheritance.**

In certain cases, you may prefer to exclude this rule.

To remove the rule, you need to find `freerasp` in your cache folder. More about where to find the cache folder [here](https://dart.dev/tools/pub/environment-variables). Then navigate to the `freerasp-X.Y.Z/android/build.gradle` file and delete the line:

```gradle
consumerProguardFiles 'consumer-rules.pro'
```

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

***

## 🆔 (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 String)
final yourCustomData = "user_123-456";

try {
    await Talsec.instance.storeExternalId(yourCustomData);
    print("External ID successfully set.");
} on ExternalIdFailureException catch(e) {
    print("Failed to set External ID: ${e.message}");
}
```

{% 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 throws an ExternalIdFailureException, and the value is not stored.<br>
  {% 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 Flutter 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/app-tampering-detection>

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

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

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

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

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

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

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

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

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

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

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

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

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

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

[^16]: 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)

[^17]: Learn more [here](https://docs.talsec.app/freerasp/wiki/threat-detection/unsecure-wifi-detection-android-only).

[^18]: Learn more [here](https://docs.talsec.app/freerasp/wiki/threat-detection/location-spoofing-detection-android-only).

[^19]: Learn more [here](/freerasp/freerasp/wiki/threat-detection/location-spoofing-detection-android-only.md).


---

# 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/flutter.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.
