FREE SDK · VERSION 3.2.0
Make your first
local security check.
Install Guardian, inspect the device, and choose how your app responds. No Sentinel account, Client ID, or subscription required.
Android · Android API 24+ · JVM target 17
STEP 01
Install from the package registry.
Use the published SDK package below. You do not need access to the private source repository. The instructions target Guardian 3.2.0.
// settings.gradle.kts — dependencyResolutionManagement.repositories
mavenCentral()
// app/build.gradle.kts — dependencies
implementation("io.github.jimmyleonardo:aegis-guardian:3.2.0")
// Set minSdk = 24 or higher and JVM target = 17 in your app.
// Sync Gradle after adding the dependency.STEP 02
Scan and choose your required checks.
This example requires root, emulator, and hooking to report clear. It prints all statuses so you can see which checks ran. The selected decision stays local; it is not a Sentinel assessment.
import android.app.Activity
import android.os.Bundle
import android.widget.TextView
import com.jimmyleonardo.guardian.AegisGuardian
import com.jimmyleonardo.guardian.SecurityCheck
import java.util.concurrent.Executors
// Example Activity: inspect off the UI thread, then display the result.
class GuardianExampleActivity : Activity() {
private val worker = Executors.newSingleThreadExecutor()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val output = TextView(this).apply { text = "Checking device…" }
setContentView(output)
val guardian = AegisGuardian.Builder(applicationContext)
.setRequiredChecks(setOf(
SecurityCheck.ROOT,
SecurityCheck.EMULATOR,
SecurityCheck.HOOKING
))
.build() // No Sentinel configuration or credentials.
worker.execute {
val message = try {
val report = guardian.inspect()
val decision = guardian.securityPolicy.evaluate(report)
val summary = report.checks.joinToString("\n") {
"${it.check}: ${it.status}"
}
val result = if (decision.allowed) "Selected checks passed"
else "Pause action: ${decision.blockedChecks}"
"$result\n\n$summary"
} catch (error: Exception) {
"Inspection failed. Pause the sensitive action."
}
runOnUiThread {
if (!isDestroyed) output.text = message
}
}
}
override fun onDestroy() {
worker.shutdown()
super.onDestroy()
}
}
// Register this Activity in AndroidManifest.xml to open the example.
// In production, put the selected-check decision before your sensitive flow.Premium Frida is intentionally excluded. Requiring it in a free local policy would prevent that policy from passing. Add other free checks only when your flow needs them. The default policy blocks nothing.
Run native Android and iOS probes off the UI thread. Flutter’s scan is asynchronous and uses native worker queues. Each scan is a snapshot; call it at deliberate points in your app, rather than assuming continuous protection.
STEP 03
Read statuses, not just a boolean.
Use report.checks for the per-check result and report.detectedThreats for detected findings. A missing result, failed scan, or unavailable required check must not become a passed decision.
| Status | Meaning | How to handle it |
|---|---|---|
clear | The probe completed without detecting the selected signal. | Passes a required-check policy; it is not proof of device integrity. |
detected | The probe found a security signal. | Pause the selected flow or apply your app’s response. |
unavailable | The probe could not provide a result, or it needs premium access. | A required check must not pass. Free local Frida uses this status. |
notConfigured | An optional check has no expected configuration. | Configure it before requiring it, for example local app identity. |
unsupported | The platform does not support this check. | Exclude it only when your policy accepts that platform limitation. |
The aggregate includes premium Frida, which is unavailable in local-only scans. Evaluate an explicit free-check policy instead of using isSecure as an automatic allow rule. Policy decisions also reject missing, unavailable, unsupported, or unconfigured required checks.
Android probes are best-effort: some underlying detectors cannot distinguish every inaccessible signal from a negative finding. A local clear result is not cryptographic proof that a device is safe.
OPTIONAL CONFIGURATION
Add your expected app identity.
Supply your own expected identity when you need local diagnostics. Android compares the signing certificate; iOS compares the Bundle ID. These are different checks and do not replace server-authorized app verification.
// Replace this with your own release signing certificate SHA-256.
// This is a local certificate comparison, not server verification.
val report = guardian.inspect(expectedSignatureSha256 = releaseFingerprint)The snippet extends the scan setup above. On Android, releaseFingerprint is your own certificate value. Without expected identity configuration, the optional app identity check is notConfigured. If you require it in your policy, configure it first.
OPTIONAL PROTECTION
Protect sensitive screens.
Screen privacy is an explicit, separate API. It is not enabled by scanning the device. Attach protection to the current screen or window and manage its lifetime in your app.
// Inside an Activity, on the UI thread, before sensitive content is shown:
val guardian = AegisGuardian.Builder(applicationContext)
.enableScreenProtection()
.build()
val protection = guardian.protectScreen(this)
if (protection.isFailure) {
// Keep sensitive content hidden and handle the error.
return
}
// Display your sensitive screen after protection succeeds.Test screenshots, app switching, background/foreground transitions, and multiple windows on your target devices. On iOS, the overlay can obscure content while inactive or captured, but cannot guarantee that a screenshot or first captured frame is hidden.
KNOW YOUR PLATFORM
What the free SDK includes.
| Capability | Android | iOS | Flutter |
|---|---|---|---|
| Root / jailbreak | Local indicators | Local indicators | Native platform checks |
| Emulator / simulator | Local indicators | Local indicators | Native platform checks |
| Debugger & hooking frameworks | Local signals | Local signals | Native platform checks |
| VPN / proxy | Local settings / signals | Local settings / signals | Native platform checks |
| USB debugging / developer options | Supported | Unsupported | Android only |
| Local identity diagnostics | APK certificate comparison | Bundle ID comparison | Platform-specific options |
| Screen privacy | FLAG_SECURE | Inactive / capture overlay | Native screen protection |
| Frida / server identity / blocklists | Sentinel premium | Sentinel premium | Sentinel premium |
Screen privacy is opt-in and is separate from the scan report. Android uses FLAG_SECURE. iOS uses an inactive/capture overlay and cannot prevent screenshots; capture notifications can arrive after a frame.
COMMON QUESTIONS
Get your first scan working.
Why does isSecure return false on a clean device?
A local report contains premium Frida as unavailable. The aggregate isSecure value requires supported checks to be clear, so it can remain false. Evaluate the free checks you explicitly require, as shown above.
The example pauses on an emulator or simulator.
The sample policy requires the emulator check to be clear. Use a physical device for that policy, or deliberately adjust the development policy. Do not silently remove the check from a release policy.
A debugger, VPN, or developer option was detected.
Development tools and legitimate VPNs can trigger signals. Choose checks and responses for your actual risk model. The sample requires root, emulator, and hooking; other reported signals are displayed for inspection.
Flutter throws MissingPluginException.
Stop the app and rebuild after installing the plugin. Check native dependency installation and minimum OS versions. Hot reload does not install native SDK code. Guardian supports Android and iOS, not Flutter web or desktop.
An identity check fails or is not configured.
Use the correct release certificate on Android; debug builds and Play App Signing can have different certificates. iOS checks the expected Bundle ID only. Pass the Android and iOS options only on their matching platforms.
iOS binary integration fails in an older Xcode.
The 3.2.0 binary was built and tested with Xcode 27. Older toolchains are untested. Check your toolchain and deployment target; contact us if you need a compatible distribution.
Does the SDK automatically stop my app?
Local inspection returns a report. The examples evaluate a policy and display a decision; your app must handle that decision before its selected flow. A failed scan must not be treated as a passed check.
WHEN YOUR TEAM NEEDS MORE
Connect the signals.
Control the response.
Sentinel adds subscription-enabled Frida results, server-authorized identity checks, blocklists, investigations, and centralized risk policies. Your backend enforces the assessment before sensitive actions.
Compare Free & Enterprise →