Options¶
Pass options once, to DeaSdk.init. They are read when the SDK starts. A later init call returns
the running instance and keeps its options, including when it passes a different appId.
DeaOptions holds what the SDK captures. A few settings are named arguments of DeaSdk.init
itself, next to DeaOptions.
The sample below uses path_provider for
modelDirectory. Add it to your app first:
import 'dart:io' show Platform;
import 'package:dea_sdk/dea_sdk.dart';
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
final support = await getApplicationSupportDirectory();
DeaSdk.init(
DeaOptions(
appId: Platform.isIOS ? 'YOUR_IOS_APP_ID' : 'YOUR_ANDROID_APP_ID',
requireConsent: true,
events: const [
EventKind.down,
EventKind.move,
EventKind.up,
EventKind.cancel,
EventKind.scroll,
EventKind.hover,
EventKind.keyDown,
],
motionRate: 50,
idleMotionMs: 3000,
touchMarginMs: 200,
),
appKey: Platform.isIOS ? 'YOUR_IOS_APP_KEY' : 'YOUR_ANDROID_APP_KEY',
modelDirectory: support,
);
runApp(const MyApp());
}
Core options¶
appId¶
| Type | Default | Required |
|---|---|---|
String |
— | Yes |
The app id DEA issued for this platform's app. DEA registers your Android app and your iOS app separately, so pass the Android id on Android and the iOS id on iOS. See Accounts and keys.
The SDK reads the id to know it is running for a production app. It does not send it to DEA.
requireConsent¶
| Type | Default | Required |
|---|---|---|
bool |
true |
No |
When true, nothing is recorded until the user has agreed. See
User Consent.
Set it to false only when consent is already established outside the SDK — for example, your app
asks during onboarding and calls DeaSdk.init only after the user agrees.
debug¶
| Type | Default | Required |
|---|---|---|
bool |
false |
No |
Requests diagnostic output. The published Flutter package carries no log, so in that package this
option has no effect. Leave it false.
onLog¶
| Type | Default | Required |
|---|---|---|
void Function(LogEntry entry)? |
null |
No |
Called with each SDK log entry. The published Flutter package carries no log, so this is never called there. The SDK never sends a log entry anywhere itself.
Capture options¶
events¶
| Type | Default | Required |
|---|---|---|
List<EventKind> |
The six pointer kinds (pointerKinds) |
No |
The input kinds to capture. Capturing fewer kinds reduces work but also reduces the evidence the score is built on.
| Value | Captures |
|---|---|
EventKind.down |
A finger, stylus or mouse button goes down |
EventKind.move |
A pointer moves while down |
EventKind.up |
A pointer is lifted |
EventKind.cancel |
The system cancels a pointer |
EventKind.scroll |
Mouse-wheel and trackpad scrolling |
EventKind.hover |
A mouse or stylus moves without touching |
EventKind.keyDown |
A key press your app reports with captureKey |
EventKind.keyUp |
A key release your app reports with captureKey |
Key kinds are not in the default list and are never captured automatically. Add them only if your
app reports typing — see
Report typing. Without them, captureKey
does nothing.
The same list also filters what your app forwards with capturePointer: a kind that is not listed
is dropped.
motionRate¶
| Type | Default | Required |
|---|---|---|
int (Hz) |
50 |
No |
The accelerometer and gyroscope rate to request. Values below 25 are raised to 25. Once the
device has delivered motion data, getSessionInfo().device.sensorRate reports this rate; it reads
0 while no motion data has arrived, and while motion is switched off with setMotion(false).
idleMotionMs¶
| Type | Default | Required |
|---|---|---|
int (ms) |
3000 |
No |
When no one has touched the screen for this long, motion data is recorded at a reduced rate — one
reading every idleMotionMs — until the next touch. 0 records every reading.
touchMarginMs¶
| Type | Default | Required |
|---|---|---|
int (ms) |
200 |
No |
Motion data is always kept at the full rate for this long before and after each touch, even while idle.
Note:
idleMotionMsandtouchMarginMsshape the motion data the score is computed from: each touch is scored with the motion reading taken just before it. Keep the defaults.
Attestation options¶
These are arguments of DeaSdk.init, not fields of DeaOptions. DEA issues their values when it
registers your app, one set per platform:
| Value | iOS | Android |
|---|---|---|
appId (in DeaOptions) |
Required | Required |
appKey |
Required | Required |
playIntegrityProject |
Ignored | Required |
appKey¶
| Type | Default | Required |
|---|---|---|
String? |
null |
Yes, for Attest |
The app key DEA issued together with this platform's appId: the Android app's key on Android,
the iOS app's key on iOS. The key is public — it identifies your app and ships inside it — and the
SDK sends it to DEA as the X-App-Key header when it registers the device key. See
Accounts and keys.
Without it, attest() answers Verdict.unsupported (with supported false) without contacting
DEA, and its detail says that no appKey was given. Capture and the classification do not need
it.
registryAppId¶
| Type | Default | Required |
|---|---|---|
String? |
null |
No |
An argument of DeaSdk.init. The appId the SDK writes inside the proofs it signs, which DEA
accepts only when it names the app behind appKey. Set it to this platform's appId. Left null,
proofs carry a built-in development id instead. Attest and getClassification() do not read it; the proof calls on the
Ads page do.
playIntegrityProject¶
| Type | Default | Required |
|---|---|---|
int? |
null |
Yes on Android, for Attest. Ignored on iOS |
The Google Cloud project number DEA issued for your Android app, together with its appId and
appKey. Ignored on iOS. See
Attest.
DeaSdk.init(
const DeaOptions(appId: 'YOUR_APP_ID'),
appKey: 'YOUR_APP_KEY',
playIntegrityProject: 123456789012,
);
Model options¶
The SDK scores with a model built into the package. It can also download a newer model published
by DEA and keep it on the device. These are arguments of DeaSdk.init.
modelDirectory¶
| Type | Default | Required |
|---|---|---|
Directory? (dart:io) |
null |
No |
Where a downloaded model is kept; the SDK creates dea/models inside it. Pass your app's
application-support directory, for example from
path_provider's getApplicationSupportDirectory().
Without it there is nowhere to keep a model: no update check runs, and the SDK always scores with the built-in model. With a directory:
- At start-up, a model kept by an earlier run is loaded before the first input is scored.
- The SDK asks DEA's model host whether a newer model is published at every start, again when the
app returns to the foreground once a day has passed since the last answered check, and when you
call
checkForModel(). An unchanged answer downloads nothing. - A newer model is downloaded, checked, and starts scoring at once; it is kept for later runs. A model older than, or the same as, the one in use is never loaded.
A check runs in the background: it never blocks scoring and never throws. Production apps read DEA's production model channel.
modelUpdates¶
| Type | Default | Required |
|---|---|---|
bool |
true |
No |
Set it to false to stop update checks. The kept model is deleted, and the SDK scores with the
built-in model. Has no effect without modelDirectory.
modelTimeout¶
| Type | Default | Required |
|---|---|---|
Duration |
30 seconds | No |
How long one model request may take before it is abandoned.