Moderation / Moderation · Android

Moderation · Android

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

Install

  1. Download the latest nosmai-detection.aar from the releases page.
  2. Put it in your app module’s libs/ folder (e.g. app/libs/nosmai-detection.aar).
  3. 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.
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 (license check) and CAMERA (live only).

Initialize

init is blocking (network + model load) — call it off the main thread. Returns false if the license is invalid/expired.

import com.nosmai.detection.NosmaiSDK

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

Moderate an image

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

Moderate a video

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

Moderate text

Call init first — it validates the license; initText needs that before it can load the (encrypted) text model.

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.

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 & performance

NosmaiSDK.setThreshold(NosmaiCategory.WEAPON, 0.7f)
NosmaiSDK.setNsfwThreshold(NosmaiNsfwClass.EXPLICIT, 0.45f) // BLOCK
NosmaiSDK.setNsfwThreshold(NosmaiNsfwClass.SEXY, 0.55f)     // WARN

// Live-only: how often the (heavier) object detector runs. NSFW always runs
// every frame. HIGH = snappiest, LOW = battery saver.
NosmaiSDK.setPerformanceMode(NosmaiPerformanceMode.HIGH)

Cleanup

NosmaiSDK.shutdown()

NOTE

All NosmaiListener callbacks are delivered on the main thread, so you can update UI directly.

Nosmai

We make advanced camera and AI technology accessible to every developer. By packaging hard problems into simple

developers
legal
newsletter

Product updates and release notes. No spam.

© 2026 nosmai, inc · all rights reserved