Skip to content

Commit 00560f3

Browse files
committed
fix: notification/toast on RimeMessage will be popped up repeatedly
- Implements logcat command DSL and Flow extensions to simplify codes
1 parent 46916af commit 00560f3

File tree

4 files changed

+84
-41
lines changed

4 files changed

+84
-41
lines changed

app/src/main/java/com/osfans/trime/daemon/RimeDaemon.kt

+19-21
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package com.osfans.trime.daemon
77
import android.app.NotificationChannel
88
import android.app.NotificationManager
99
import android.app.PendingIntent
10+
import android.content.Context
1011
import android.content.Intent
1112
import android.os.Build
1213
import androidx.core.app.NotificationCompat
@@ -21,11 +22,10 @@ import com.osfans.trime.core.lifecycleScope
2122
import com.osfans.trime.core.whenReady
2223
import com.osfans.trime.ui.main.LogActivity
2324
import com.osfans.trime.util.appContext
25+
import com.osfans.trime.util.logcat
2426
import com.osfans.trime.util.toast
2527
import kotlinx.coroutines.CoroutineScope
2628
import kotlinx.coroutines.Dispatchers
27-
import kotlinx.coroutines.flow.launchIn
28-
import kotlinx.coroutines.flow.onEach
2929
import kotlinx.coroutines.launch
3030
import kotlinx.coroutines.runBlocking
3131
import kotlinx.coroutines.withContext
@@ -151,9 +151,6 @@ object RimeDaemon {
151151
.let { notificationManager.notify(id, it) }
152152
realRime.finalize()
153153
realRime.startup(fullCheck)
154-
realRime.messageFlow
155-
.onEach(::handleRimeMessage)
156-
.launchIn(TrimeApplication.getInstance().coroutineScope)
157154
TrimeApplication.getInstance().coroutineScope.launch {
158155
// cancel notification on ready
159156
realRime.lifecycle.whenReady {
@@ -162,44 +159,45 @@ object RimeDaemon {
162159
}
163160
}
164161

165-
private suspend fun handleRimeMessage(it: RimeMessage<*>) {
162+
suspend fun onRimeMessage(
163+
ctx: Context,
164+
it: RimeMessage<*>,
165+
) {
166166
if (it is RimeMessage.DeployMessage) {
167167
when (it.data) {
168168
RimeMessage.DeployMessage.State.Start -> {
169169
withContext(Dispatchers.IO) {
170-
Runtime.getRuntime().exec(arrayOf("logcat", "-c"))
170+
logcat { clear() }
171171
}
172172
}
173173
RimeMessage.DeployMessage.State.Success -> {
174-
ContextCompat.getMainExecutor(appContext).execute {
175-
appContext.toast(R.string.deploy_finish)
174+
ContextCompat.getMainExecutor(ctx).execute {
175+
ctx.toast(R.string.deploy_finish)
176176
}
177177
}
178178
RimeMessage.DeployMessage.State.Failure -> {
179179
val intent =
180-
Intent(appContext, LogActivity::class.java).apply {
180+
Intent(ctx, LogActivity::class.java).apply {
181181
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
182182
val log =
183183
withContext(Dispatchers.IO) {
184-
Runtime
185-
.getRuntime()
186-
.exec(
187-
arrayOf("logcat", "-d", "-v", "brief", "-s", "rime.trime:W"),
188-
).inputStream
189-
.bufferedReader()
190-
.readText()
184+
logcat {
185+
format("brief")
186+
filterspec("rime.trime", "W")
187+
dump()
188+
}.inputStream.bufferedReader().readText()
191189
}
192190
putExtra(LogActivity.FROM_DEPLOY, true)
193191
putExtra(LogActivity.DEPLOY_FAILURE_TRACE, log)
194192
}
195193
NotificationCompat
196-
.Builder(appContext, CHANNEL_ID)
194+
.Builder(ctx, CHANNEL_ID)
197195
.setSmallIcon(R.drawable.ic_baseline_warning_24)
198-
.setContentTitle(appContext.getString(R.string.rime_daemon))
199-
.setContentText(appContext.getString(R.string.view_deploy_failure_log))
196+
.setContentTitle(ctx.getString(R.string.rime_daemon))
197+
.setContentText(ctx.getString(R.string.view_deploy_failure_log))
200198
.setContentIntent(
201199
PendingIntent.getActivity(
202-
appContext,
200+
ctx,
203201
0,
204202
intent,
205203
PendingIntent.FLAG_ONE_SHOT or

app/src/main/java/com/osfans/trime/ime/core/TrimeInputMethodService.kt

+4-1
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,10 @@ open class TrimeInputMethodService : LifecycleInputMethodService() {
259259
}
260260
}
261261
}
262-
else -> {}
262+
else ->
263+
lifecycleScope.launch {
264+
RimeDaemon.onRimeMessage(this@TrimeInputMethodService, it)
265+
}
263266
}
264267
}
265268

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2015 - 2025 Rime community
3+
* SPDX-License-Identifier: GPL-3.0-or-later
4+
*/
5+
6+
package com.osfans.trime.util
7+
8+
import kotlinx.coroutines.Dispatchers
9+
import kotlinx.coroutines.flow.Flow
10+
import kotlinx.coroutines.flow.asFlow
11+
import kotlinx.coroutines.flow.cancellable
12+
import kotlinx.coroutines.flow.flowOn
13+
14+
fun Process.asFlow(): Flow<String> =
15+
inputStream
16+
.bufferedReader()
17+
.lineSequence()
18+
.asFlow()
19+
.flowOn(Dispatchers.IO)
20+
.cancellable()

app/src/main/java/com/osfans/trime/util/Logcat.kt

+41-19
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,7 @@ import kotlinx.coroutines.Job
1616
import kotlinx.coroutines.async
1717
import kotlinx.coroutines.flow.MutableSharedFlow
1818
import kotlinx.coroutines.flow.SharedFlow
19-
import kotlinx.coroutines.flow.asFlow
2019
import kotlinx.coroutines.flow.asSharedFlow
21-
import kotlinx.coroutines.flow.cancellable
22-
import kotlinx.coroutines.flow.flowOn
2320
import kotlinx.coroutines.launch
2421

2522
class Logcat(
@@ -42,12 +39,10 @@ class Logcat(
4239
fun getLogAsync(): Deferred<Result<List<String>>> =
4340
async {
4441
runCatching {
45-
Runtime
46-
.getRuntime()
47-
.exec(arrayOf("logcat", pid?.let { "--pid=$it" } ?: "", "-d"))
48-
.inputStream
49-
.bufferedReader()
50-
.readLines()
42+
logcat {
43+
pid?.let { pid(it) }
44+
dump()
45+
}.inputStream.bufferedReader().readLines()
5146
}
5247
}
5348

@@ -56,7 +51,7 @@ class Logcat(
5651
*/
5752
fun clearLog(): Job =
5853
launch {
59-
runCatching { Runtime.getRuntime().exec(arrayOf("logcat", "-c")) }
54+
runCatching { logcat { clear() } }
6055
}
6156

6257
/**
@@ -68,16 +63,11 @@ class Logcat(
6863
} else {
6964
launch {
7065
runCatching {
71-
Runtime
72-
.getRuntime()
73-
.exec(arrayOf("logcat", pid?.let { "--pid=$it" } ?: "", "-v", "time"))
74-
.also { process = it }
75-
.inputStream
76-
.bufferedReader()
77-
.lineSequence()
66+
logcat {
67+
pid?.let { pid(it) }
68+
format("time")
69+
}.also { process = it }
7870
.asFlow()
79-
.flowOn(Dispatchers.IO)
80-
.cancellable()
8171
.collect { flow.emit(it) }
8272
}
8373
}.also { emittingJob = it }
@@ -95,3 +85,35 @@ class Logcat(
9585
val default by lazy { Logcat() }
9686
}
9787
}
88+
89+
// DSL
90+
inline fun logcat(builderAction: LogcatCommandBuilder.() -> Unit): java.lang.Process =
91+
LogcatCommandBuilder().apply(builderAction).toProcess()
92+
93+
class LogcatCommandBuilder {
94+
private val cmdList = arrayListOf("logcat")
95+
96+
fun clear() = apply { cmdList.add("--clear") }
97+
98+
fun dump() = apply { cmdList.add("-d") }
99+
100+
fun pid(pid: Int) = apply { cmdList.add("--pid=$pid") }
101+
102+
fun format(format: String) = apply { cmdList.add("--format=$format") }
103+
104+
fun filterspec(
105+
tag: String,
106+
priority: String,
107+
) = apply {
108+
cmdList.add("-s")
109+
cmdList.add("$tag:$priority")
110+
}
111+
112+
fun filterspec(spec: String) =
113+
apply {
114+
cmdList.add("-s")
115+
cmdList.add(spec)
116+
}
117+
118+
fun toProcess(): java.lang.Process = Runtime.getRuntime().exec(cmdList.toTypedArray())
119+
}

0 commit comments

Comments
 (0)