When a root shell belongs in the architecture
An Android utility may need to run shell commands or move privileged work into a separate process. Odin exposes both paths: a persistent shell for commands and a RootService framework for Binder/AIDL IPC. The library does not root a device; the device and user must already allow root access.
The design is inspired by topjohnwu’s libsu and reworks the interface around Kotlin and coroutines. Keeping root work behind ShellRepository also gives application code a clear boundary between its UI and privileged operations.
import com.valhalla.superuser.ktx.RealShellRepository
import com.valhalla.superuser.ktx.ShellRepository
suspend fun inspectRoot() {
val shell: ShellRepository = RealShellRepository()
if (shell.isRootGranted()) {
val result = shell.exec("id")
if (result.isSuccess) println(result.stdout)
else println("code=${result.code} err=${result.stderr}")
}
}Adapted from the public usage guide. Follow the repository’s installation instructions and check artifact availability before adding a dependency version.
Check access, then inspect the result
Root availability and command success are separate questions. isRootGranted() checks availability. exec() returns an exit code with separate stdout and stderr lists, so a caller can report a failure without treating every returned string as success.
A command that could not execute uses ShellResult.JOB_NOT_EXECUTED, with code −1. When multiple commands are passed to exec(), the returned exit code is from the last command. Execute and inspect separate calls when an earlier step must succeed before the next one runs.
Streaming has a cancellation boundary
Shell.cmd(...).asFlow() emits lines tagged as standard output or standard error. This is useful for presenting progress without losing the distinction between the two streams.
Cancelling a collector does not kill a command already running in the shared shell. The command drains to completion. Coroutine cancellation still propagates to the caller, so the app should distinguish ending observation from stopping the underlying operation.
A few practical questions
Does Odin work without root?
Its privileged operations require root access. Adding the library to an app does not grant Android permissions or root a device.
What is the minimum Android version?
The public README specifies minSdk 24, corresponding to Android 7.0.
Where are the complete APIs documented?
The repository’s docs/USAGE.md covers execution, streamed output, result handling and cancellation. It is the reference for integrating the library.