release: v0.1.4 — onglet Journal (diagnostic VPN), limitation des applications (plages horaires, temps d'écran)
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
82d47fcd72
commit
6086e8aeff
23 files changed
+816
-40
No files matched your search
@@ -0,0 +1,67 @@
|
||||
package com.jttools.datacontrol.log
|
||||
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import java.io.File
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
import java.util.concurrent.Executors
|
||||
|
||||
/**
|
||||
* Journal de diagnostic : garde les [MAX_LINES] dernières lignes en mémoire et dans un fichier
|
||||
* (survit au redémarrage de l'app), consultable dans l'onglet « Journal ».
|
||||
*/
|
||||
object AppLog {
|
||||
private const val MAX_LINES = 400
|
||||
private const val FILE_NAME = "journal.txt"
|
||||
|
||||
private val io = Executors.newSingleThreadExecutor()
|
||||
private val fmt = SimpleDateFormat("MM-dd HH:mm:ss", Locale.FRANCE)
|
||||
private val lines = ArrayDeque<String>()
|
||||
private val _entries = MutableStateFlow<List<String>>(emptyList())
|
||||
val entries: StateFlow<List<String>> = _entries.asStateFlow()
|
||||
|
||||
@Volatile private var file: File? = null
|
||||
|
||||
fun init(context: Context) {
|
||||
if (file != null) return
|
||||
val f = File(context.filesDir, FILE_NAME)
|
||||
file = f
|
||||
synchronized(lines) {
|
||||
runCatching { if (f.exists()) lines.addAll(f.readLines().takeLast(MAX_LINES)) }
|
||||
_entries.value = lines.toList()
|
||||
}
|
||||
i("App", "Journal ouvert")
|
||||
}
|
||||
|
||||
fun i(tag: String, message: String) = add("I", tag, message)
|
||||
fun w(tag: String, message: String) = add("W", tag, message)
|
||||
fun e(tag: String, message: String, t: Throwable? = null) =
|
||||
add("E", tag, if (t == null) message else "$message — ${t.javaClass.simpleName}: ${t.message}")
|
||||
|
||||
private fun add(level: String, tag: String, message: String) {
|
||||
Log.println(when (level) { "E" -> Log.ERROR; "W" -> Log.WARN; else -> Log.INFO }, "DataControl/$tag", message)
|
||||
val line = "${fmt.format(Date())} $level $tag: $message"
|
||||
synchronized(lines) {
|
||||
lines.addLast(line)
|
||||
while (lines.size > MAX_LINES) lines.removeFirst()
|
||||
_entries.value = lines.toList()
|
||||
val snapshot = lines.toList()
|
||||
io.execute { runCatching { file?.writeText(snapshot.joinToString("\n")) } }
|
||||
}
|
||||
}
|
||||
|
||||
fun clear() {
|
||||
synchronized(lines) {
|
||||
lines.clear()
|
||||
_entries.value = emptyList()
|
||||
io.execute { runCatching { file?.writeText("") } }
|
||||
}
|
||||
}
|
||||
|
||||
fun asText(): String = synchronized(lines) { lines.joinToString("\n") }
|
||||
}
|
||||
Reference in new issue
Block a user