# Android

> Use Nosmai Moderation in a native Android (Kotlin) app: image, video, text and live-camera moderation.

> For AI agents: the complete documentation index is at https://nosmai.com/llms/moderations.txt

Product: Nosmai Moderation
Group: platform-guides
Source: https://nosmai.com/docs/moderations/android/

## Install

1. Download the latest `nosmai-detection.aar` from the [releases page](https://github.com/nosmai/moderation-sdk-android/releases).
1. Put it in your app module's `libs/` folder (for example `app/libs/nosmai-detection.aar`).
1. Reference it in Gradle (below). The SDK is self-contained: everything runs on-device and all models are bundled, so there are no extra dependencies to add.

```kotlin
android {
    defaultConfig {
        minSdk = 24
        ndk { abiFilters += "arm64-v8a" }   // the SDK ships arm64-v8a
    }
}

dependencies {
    implementation(files("libs/nosmai-detection.aar"))
    // CameraX, only needed for the live-camera path
    val camerax = "1.4.2"
    implementation("androidx.camera:camera-core:$camerax")
    implementation("androidx.camera:camera-camera2:$camerax")
    implementation("androidx.camera:camera-lifecycle:$camerax")
    implementation("androidx.camera:camera-view:$camerax")
}
```

**Permissions** (`AndroidManifest.xml`): `INTERNET` for the license check and `CAMERA` for the live path only.

## Initialize

`init` is blocking (network plus model load), so call it off the main thread. It returns `false` if the license is invalid or expired.

```kotlin
import com.nosmai.detection.NosmaiSDK

Executors.newSingleThreadExecutor().execute {
    val ok = NosmaiSDK.init(context, "NOSMAI-XXXX")
}
```

## Moderate an image

```kotlin
val bitmap = BitmapFactory.decodeFile(path)
val r = NosmaiSDK.analyzeImage(bitmap)          // NosmaiResult
if (r.isUnsafe) {
    // r.nsfw -> SAFE / WARN / BLOCK
    Log.d("Mod", "nsfw ${r.nsfw}")
}
```

## Moderate a video

```kotlin
NosmaiSDK.analyzeVideo(
    context, uri, frameIntervalMs = 500L,
    onProgress = { p -> /* 0..1 */ },
    onComplete = { v -> /* v.isUnsafe, v.categories, v.flags */ },
)
```

## Moderate text

Call `init` first, since it validates the license. `initText` needs that before it can load the text model.

```kotlin
NosmaiSDK.initText(context)                      // after init(), off the main thread
val t = NosmaiSDK.moderateText("some message")   // NosmaiTextResult
if (t.blocked) Log.d("Mod", "${t.category} via ${t.layer} (${t.matchedWord})")
```

## Live camera (CameraX)

Feed CameraX frames to `pushFrame`. Results arrive on the main thread via `NosmaiListener`.

```kotlin
NosmaiSDK.startStream(object : NosmaiListener {
    override fun onResult(r: NosmaiResult) { /* every frame */ }
    override fun onUnsafe(r: NosmaiResult) { /* turned unsafe */ }
    override fun onSafe() { /* recovered */ }
})

val analysis = ImageAnalysis.Builder()
    .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
    .setOutputImageRotationEnabled(true)
    .build()
    .also { it.setAnalyzer(executor) { proxy -> NosmaiSDK.pushFrame(proxy) } }

cameraProvider.bindToLifecycle(owner, CameraSelector.DEFAULT_BACK_CAMERA, preview, analysis)

// on leave
NosmaiSDK.stopStream()
```

## Thresholds and performance

```kotlin
NosmaiSDK.setNsfwThreshold(NosmaiNsfwClass.EXPLICIT, 0.45f) // BLOCK
NosmaiSDK.setNsfwThreshold(NosmaiNsfwClass.SEXY, 0.55f)     // WARN

// Live only: how often the NSFW check runs. HIGH is snappiest, LOW saves battery.
NosmaiSDK.setPerformanceMode(NosmaiPerformanceMode.HIGH)
```

## Cleanup

```kotlin
NosmaiSDK.shutdown()
```

> [!NOTE]
All `NosmaiListener` callbacks are delivered on the main thread, so you can update UI directly.
