import android.os.Process import android.util.Log import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.callbackFlow import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import java.io.BufferedReader import java.io.InputStreamReader import java.util.LinkedList object LogcatFlow { const val TAG = "LogcatFlow" private val runtime = Runtime.getRuntime() private const val MAX_LOGS = 100 fun logcatFlow(): Flow> = callbackFlow { val process = runtime.exec("logcat -v threadtime") val logcatReader = BufferedReader(InputStreamReader(process.inputStream)) // Logs are filtered using PID of the app. val pid = Process.myPid().toString() val logList = LinkedList() val job = launch(Dispatchers.IO) { try { logcatReader.use { reader -> reader.forEachLine { line -> if (line.contains(pid)) { if (logList.size >= MAX_LOGS) { logList.poll() } logList.add(line) trySend(ArrayList(logList)) } } } } catch (e: Exception) { Log.d(TAG, "logcatFlow: $e") close(e) } finally { withContext(Dispatchers.IO) { process.destroy() } } } awaitClose { job.cancel() process.destroy() } }.flowOn(Dispatchers.IO) }