Runtime permissions
Manifest declarations get you compile-time visibility. Android still requires explicit runtime grants for the permissions Relavoi depends on. Here is what to ask for and when.
READ_PHONE_STATE (API 23+)
Required for call-state detection (Relavoi.verification.isCallActive() and the call observer).
private val phonePermLauncher = registerForActivityResult(
ActivityResultContracts.RequestPermission()
) { granted ->
if (!granted) {
// Fallback: verify() still works but won't auto-fire on call detection
}
}
private fun ensurePhonePermission() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE)
!= PackageManager.PERMISSION_GRANTED) {
phonePermLauncher.launch(Manifest.permission.READ_PHONE_STATE)
}
}
Suggested moment to ask: the first time the user enters a screen that displays the call-verification banner — not at app launch.
POST_NOTIFICATIONS (API 33+)
Required to display incoming-call push notifications.
private val notifPermLauncher = registerForActivityResult(
ActivityResultContracts.RequestPermission()
) { /* user decision */ }
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
notifPermLauncher.launch(Manifest.permission.POST_NOTIFICATIONS)
}
Suggested moment: immediately before calling Relavoi.push.registerToken(...).
SYSTEM_ALERT_WINDOW (overlay)
Optional. Lets the SDK show its floating verification bubble (FloatingBubbleService) as a system overlay even when your app is not the active screen — useful if the user has the native dialer open during the call.
This permission cannot be requested through the standard runtime flow. Send the user to system settings:
import android.content.Intent
import android.net.Uri
import android.provider.Settings
private fun requestOverlayPermission() {
if (!Settings.canDrawOverlays(this)) {
val intent = Intent(
Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:$packageName")
)
overlayPermLauncher.launch(intent)
}
}
private val overlayPermLauncher = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) { /* result.resultCode does not reflect grant; re-check Settings.canDrawOverlays */ }
If overlay permission is denied, the floating bubble cannot be shown — render your own in-app banner inside your Activity instead (see Call verification).
Checking permission status
The SDK exposes a helper for the phone-state grant; check the other two with the standard Android APIs:
import androidx.core.content.ContextCompat
import android.content.pm.PackageManager
import android.provider.Settings
val hasPhoneState = Relavoi.verification.hasPhoneStatePermission(this)
val hasNotifications = ContextCompat.checkSelfPermission(
this, Manifest.permission.POST_NOTIFICATIONS
) == PackageManager.PERMISSION_GRANTED
val hasOverlay = Settings.canDrawOverlays(this)
Useful for a settings screen that shows the user which features are currently degraded.
:::warning Do not ask all at once A wall of permission prompts at launch tanks grant rates. Ask each permission contextually — when the feature it unlocks is about to be used. :::