mirror of
https://github.com/gkd-kit/gkd.git
synced 2024-11-16 11:42:22 +08:00
perf: log lifecycle
This commit is contained in:
parent
dc54864751
commit
724ff77c97
|
@ -10,6 +10,7 @@ import kotlinx.coroutines.launch
|
|||
import li.songe.gkd.util.OnChangeListen
|
||||
import li.songe.gkd.util.OnDestroy
|
||||
import li.songe.gkd.util.OnTileClick
|
||||
import li.songe.gkd.util.useLogLifecycle
|
||||
|
||||
class FloatingTileService : TileService(), OnDestroy, OnChangeListen, OnTileClick {
|
||||
override fun onStartListening() {
|
||||
|
@ -41,6 +42,7 @@ class FloatingTileService : TileService(), OnDestroy, OnChangeListen, OnTileClic
|
|||
}
|
||||
|
||||
init {
|
||||
useLogLifecycle()
|
||||
scope.launch {
|
||||
combine(
|
||||
FloatingService.isRunning,
|
||||
|
|
|
@ -45,6 +45,8 @@ import li.songe.gkd.notif.notifyService
|
|||
import li.songe.gkd.permission.notificationState
|
||||
import li.songe.gkd.service.A11yService
|
||||
import li.songe.gkd.util.LOCAL_HTTP_SUBS_ID
|
||||
import li.songe.gkd.util.OnCreate
|
||||
import li.songe.gkd.util.OnDestroy
|
||||
import li.songe.gkd.util.SERVER_SCRIPT_URL
|
||||
import li.songe.gkd.util.getIpAddressInLocalNetwork
|
||||
import li.songe.gkd.util.keepNullJson
|
||||
|
@ -54,46 +56,62 @@ import li.songe.gkd.util.storeFlow
|
|||
import li.songe.gkd.util.subsItemsFlow
|
||||
import li.songe.gkd.util.toast
|
||||
import li.songe.gkd.util.updateSubscription
|
||||
import li.songe.gkd.util.useAliveFlow
|
||||
import li.songe.gkd.util.useLogLifecycle
|
||||
import java.io.File
|
||||
|
||||
|
||||
class HttpService : Service() {
|
||||
private val scope = MainScope()
|
||||
class HttpService : Service(), OnCreate, OnDestroy {
|
||||
override fun onBind(intent: Intent?) = null
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
onCreated()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
onDestroyed()
|
||||
}
|
||||
|
||||
val scope = MainScope().apply { onDestroyed { cancel() } }
|
||||
|
||||
private val httpServerPortFlow = storeFlow.map(scope) { s -> s.httpServerPort }
|
||||
|
||||
private var server: EmbeddedServer<CIOApplicationEngine, CIOApplicationEngine.Configuration>? =
|
||||
null
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
isRunning.value = true
|
||||
localNetworkIpsFlow.value = getIpAddressInLocalNetwork()
|
||||
scope.launchTry(Dispatchers.IO) {
|
||||
httpServerPortFlow.collect { port ->
|
||||
server?.stop()
|
||||
server = try {
|
||||
scope.createServer(port).apply { start() }
|
||||
} catch (e: Exception) {
|
||||
LogUtils.d("HTTP服务启动失败", e)
|
||||
null
|
||||
}
|
||||
if (server == null) {
|
||||
toast("HTTP服务启动失败,您可以尝试切换端口后重新启动")
|
||||
stopSelf()
|
||||
return@collect
|
||||
}
|
||||
httpNotif.copy(text = "HTTP服务-$port").notifyService(this@HttpService)
|
||||
init {
|
||||
useLogLifecycle()
|
||||
useAliveFlow(isRunning)
|
||||
|
||||
onCreated { localNetworkIpsFlow.value = getIpAddressInLocalNetwork() }
|
||||
onDestroyed { localNetworkIpsFlow.value = emptyList() }
|
||||
|
||||
onDestroyed {
|
||||
if (storeFlow.value.autoClearMemorySubs) {
|
||||
deleteSubscription(LOCAL_HTTP_SUBS_ID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
scope.cancel()
|
||||
isRunning.value = false
|
||||
localNetworkIpsFlow.value = emptyList()
|
||||
if (storeFlow.value.autoClearMemorySubs) {
|
||||
deleteSubscription(LOCAL_HTTP_SUBS_ID)
|
||||
onCreated {
|
||||
scope.launchTry(Dispatchers.IO) {
|
||||
httpServerPortFlow.collect { port ->
|
||||
server?.stop()
|
||||
server = try {
|
||||
scope.createServer(port).apply { start() }
|
||||
} catch (e: Exception) {
|
||||
LogUtils.d("HTTP服务启动失败", e)
|
||||
null
|
||||
}
|
||||
if (server == null) {
|
||||
toast("HTTP服务启动失败,您可以尝试切换端口后重新启动")
|
||||
stopSelf()
|
||||
return@collect
|
||||
}
|
||||
httpNotif.copy(text = "HTTP服务-$port").notifyService(this@HttpService)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -109,8 +127,6 @@ class HttpService : Service() {
|
|||
app.startForegroundService(Intent(app, HttpService::class.java))
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBind(intent: Intent?) = null
|
||||
}
|
||||
|
||||
@Serializable
|
||||
|
|
|
@ -10,6 +10,7 @@ import kotlinx.coroutines.launch
|
|||
import li.songe.gkd.util.OnChangeListen
|
||||
import li.songe.gkd.util.OnDestroy
|
||||
import li.songe.gkd.util.OnTileClick
|
||||
import li.songe.gkd.util.useLogLifecycle
|
||||
|
||||
class HttpTileService : TileService(), OnDestroy, OnChangeListen, OnTileClick {
|
||||
override fun onStartListening() {
|
||||
|
@ -41,6 +42,7 @@ class HttpTileService : TileService(), OnDestroy, OnChangeListen, OnTileClick {
|
|||
}
|
||||
|
||||
init {
|
||||
useLogLifecycle()
|
||||
scope.launch {
|
||||
combine(
|
||||
HttpService.isRunning,
|
||||
|
|
|
@ -1,26 +1,29 @@
|
|||
package li.songe.gkd.debug
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Service
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import com.blankj.utilcode.util.LogUtils
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import li.songe.gkd.app
|
||||
import li.songe.gkd.notif.notifyService
|
||||
import li.songe.gkd.notif.screenshotNotif
|
||||
import li.songe.gkd.util.OnCreate
|
||||
import li.songe.gkd.util.OnDestroy
|
||||
import li.songe.gkd.util.ScreenshotUtil
|
||||
import li.songe.gkd.util.componentName
|
||||
import li.songe.gkd.util.useAliveFlow
|
||||
import li.songe.gkd.util.useLogLifecycle
|
||||
import java.lang.ref.WeakReference
|
||||
|
||||
class ScreenshotService : Service() {
|
||||
class ScreenshotService : Service(), OnCreate, OnDestroy {
|
||||
override fun onBind(intent: Intent?) = null
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
isRunning.value = true
|
||||
screenshotNotif.notifyService(this)
|
||||
onCreated()
|
||||
}
|
||||
|
||||
|
||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||
try {
|
||||
return super.onStartCommand(intent, flags, startId)
|
||||
|
@ -35,25 +38,31 @@ class ScreenshotService : Service() {
|
|||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
isRunning.value = false
|
||||
screenshotUtil?.destroy()
|
||||
screenshotUtil = null
|
||||
onDestroyed()
|
||||
}
|
||||
|
||||
private var screenshotUtil: ScreenshotUtil? = null
|
||||
|
||||
init {
|
||||
useLogLifecycle()
|
||||
useAliveFlow(isRunning)
|
||||
onCreated { screenshotNotif.notifyService(this) }
|
||||
onCreated { instance = WeakReference(this) }
|
||||
onDestroyed { instance = WeakReference(null) }
|
||||
onDestroyed { screenshotUtil?.destroy() }
|
||||
}
|
||||
|
||||
companion object {
|
||||
suspend fun screenshot() = screenshotUtil?.execute()
|
||||
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
private var screenshotUtil: ScreenshotUtil? = null
|
||||
|
||||
fun start(context: Context = app, intent: Intent) {
|
||||
private var instance = WeakReference<ScreenshotService>(null)
|
||||
val isRunning = MutableStateFlow(false)
|
||||
suspend fun screenshot() = instance.get()?.screenshotUtil?.execute()
|
||||
fun start(intent: Intent) {
|
||||
intent.component = ScreenshotService::class.componentName
|
||||
context.startForegroundService(intent)
|
||||
app.startForegroundService(intent)
|
||||
}
|
||||
|
||||
val isRunning = MutableStateFlow(false)
|
||||
fun stop(context: Context = app) {
|
||||
context.stopService(Intent(context, ScreenshotService::class.java))
|
||||
fun stop() {
|
||||
app.stopService(Intent(app, ScreenshotService::class.java))
|
||||
}
|
||||
}
|
||||
}
|
|
@ -56,6 +56,7 @@ import li.songe.gkd.util.map
|
|||
import li.songe.gkd.util.showActionToast
|
||||
import li.songe.gkd.util.storeFlow
|
||||
import li.songe.gkd.util.toast
|
||||
import li.songe.gkd.util.useLogLifecycle
|
||||
import li.songe.selector.MatchOption
|
||||
import li.songe.selector.Selector
|
||||
import java.lang.ref.WeakReference
|
||||
|
@ -89,6 +90,7 @@ class A11yService : AccessibilityService(), OnCreate, OnA11yConnected, OnA11yEve
|
|||
val scope = CoroutineScope(Dispatchers.Default).apply { onDestroyed { cancel() } }
|
||||
|
||||
init {
|
||||
useLogLifecycle()
|
||||
useRunningState()
|
||||
useAliveView()
|
||||
useCaptureVolume()
|
||||
|
@ -485,19 +487,19 @@ private fun A11yService.useRuleChangedLog() {
|
|||
}
|
||||
|
||||
private fun A11yService.useRunningState() {
|
||||
A11yService.weakInstance = WeakReference(this)
|
||||
A11yService.isRunning.value = true
|
||||
if (!storeFlow.value.enableService) {
|
||||
// https://github.com/gkd-kit/gkd/issues/754
|
||||
storeFlow.update { it.copy(enableService = true) }
|
||||
onCreated {
|
||||
A11yService.weakInstance = WeakReference(this)
|
||||
A11yService.isRunning.value = true
|
||||
if (!storeFlow.value.enableService) {
|
||||
// https://github.com/gkd-kit/gkd/issues/754
|
||||
storeFlow.update { it.copy(enableService = true) }
|
||||
}
|
||||
ManageService.autoStart()
|
||||
}
|
||||
onDestroyed {
|
||||
if (storeFlow.value.enableService) {
|
||||
storeFlow.update { it.copy(enableService = false) }
|
||||
}
|
||||
}
|
||||
ManageService.autoStart()
|
||||
onDestroyed {
|
||||
A11yService.weakInstance = WeakReference(null)
|
||||
A11yService.isRunning.value = false
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ import li.songe.gkd.util.componentName
|
|||
import li.songe.gkd.util.lastRestartA11yServiceTimeFlow
|
||||
import li.songe.gkd.util.storeFlow
|
||||
import li.songe.gkd.util.toast
|
||||
import li.songe.gkd.util.useLogLifecycle
|
||||
|
||||
class GkdTileService : TileService(), OnDestroy, OnChangeListen, OnTileClick {
|
||||
override fun onStartListening() {
|
||||
|
@ -50,6 +51,7 @@ class GkdTileService : TileService(), OnDestroy, OnChangeListen, OnTileClick {
|
|||
}
|
||||
|
||||
init {
|
||||
useLogLifecycle()
|
||||
scope.launch {
|
||||
combine(
|
||||
A11yService.isRunning,
|
||||
|
|
|
@ -2,8 +2,8 @@ package li.songe.gkd.service
|
|||
|
||||
import android.app.Service
|
||||
import android.content.Intent
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.MainScope
|
||||
import kotlinx.coroutines.cancel
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.combine
|
||||
|
@ -14,45 +14,32 @@ import li.songe.gkd.app
|
|||
import li.songe.gkd.notif.abNotif
|
||||
import li.songe.gkd.notif.notifyService
|
||||
import li.songe.gkd.permission.notificationState
|
||||
import li.songe.gkd.util.OnCreate
|
||||
import li.songe.gkd.util.OnDestroy
|
||||
import li.songe.gkd.util.actionCountFlow
|
||||
import li.songe.gkd.util.getSubsStatus
|
||||
import li.songe.gkd.util.ruleSummaryFlow
|
||||
import li.songe.gkd.util.storeFlow
|
||||
import li.songe.gkd.util.useAliveFlow
|
||||
|
||||
class ManageService : Service() {
|
||||
class ManageService : Service(), OnCreate, OnDestroy {
|
||||
override fun onBind(intent: Intent?) = null
|
||||
val scope = CoroutineScope(Dispatchers.Default)
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
isRunning.value = true
|
||||
abNotif.notifyService(this)
|
||||
scope.launch {
|
||||
combine(
|
||||
A11yService.isRunning,
|
||||
storeFlow,
|
||||
ruleSummaryFlow,
|
||||
actionCountFlow,
|
||||
) { abRunning, store, ruleSummary, count ->
|
||||
if (!abRunning) return@combine "无障碍未授权"
|
||||
if (!store.enableMatch) return@combine "暂停规则匹配"
|
||||
if (store.useCustomNotifText) {
|
||||
return@combine store.customNotifText
|
||||
.replace("\${i}", ruleSummary.globalGroups.size.toString())
|
||||
.replace("\${k}", ruleSummary.appSize.toString())
|
||||
.replace("\${u}", ruleSummary.appGroupSize.toString())
|
||||
.replace("\${n}", count.toString())
|
||||
}
|
||||
return@combine getSubsStatus(ruleSummary, count)
|
||||
}.debounce(500L).stateIn(scope, SharingStarted.Eagerly, "").collect { text ->
|
||||
abNotif.copy(text = text).notifyService(this@ManageService)
|
||||
}
|
||||
}
|
||||
onCreated()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
isRunning.value = false
|
||||
onDestroyed()
|
||||
}
|
||||
|
||||
val scope = MainScope().apply { onDestroyed { cancel() } }
|
||||
|
||||
init {
|
||||
useAliveFlow(isRunning)
|
||||
useNotif()
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
@ -79,3 +66,29 @@ class ManageService : Service() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun ManageService.useNotif() {
|
||||
onCreated {
|
||||
abNotif.notifyService(this)
|
||||
scope.launch {
|
||||
combine(
|
||||
A11yService.isRunning,
|
||||
storeFlow,
|
||||
ruleSummaryFlow,
|
||||
actionCountFlow,
|
||||
) { abRunning, store, ruleSummary, count ->
|
||||
if (!abRunning) return@combine "无障碍未授权"
|
||||
if (!store.enableMatch) return@combine "暂停规则匹配"
|
||||
if (store.useCustomNotifText) {
|
||||
return@combine store.customNotifText
|
||||
.replace("\${i}", ruleSummary.globalGroups.size.toString())
|
||||
.replace("\${k}", ruleSummary.appSize.toString())
|
||||
.replace("\${u}", ruleSummary.appGroupSize.toString())
|
||||
.replace("\${n}", count.toString())
|
||||
}
|
||||
return@combine getSubsStatus(ruleSummary, count)
|
||||
}.debounce(500L).stateIn(scope, SharingStarted.Eagerly, "").collect { text ->
|
||||
abNotif.copy(text = text).notifyService(this@useNotif)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@ package li.songe.gkd.util
|
|||
|
||||
|
||||
import android.view.accessibility.AccessibilityEvent
|
||||
import com.blankj.utilcode.util.LogUtils
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import java.util.WeakHashMap
|
||||
|
||||
private val callbacksMap by lazy { WeakHashMap<Any, HashMap<Int, MutableList<Any>>>() }
|
||||
|
@ -15,13 +17,13 @@ private fun <T> Any.getCallbacks(method: Int): MutableList<T> {
|
|||
interface CanOnCallback
|
||||
|
||||
interface OnCreate : CanOnCallback {
|
||||
fun onBeforeCreate(f: () -> Unit) {
|
||||
getCallbacks<() -> Unit>(1).add(f)
|
||||
}
|
||||
|
||||
fun onBeforeCreate() {
|
||||
getCallbacks<() -> Unit>(1).forEach { it() }
|
||||
}
|
||||
// fun onBeforeCreate(f: () -> Unit) {
|
||||
// getCallbacks<() -> Unit>(1).add(f)
|
||||
// }
|
||||
//
|
||||
// fun onBeforeCreate() {
|
||||
// getCallbacks<() -> Unit>(1).forEach { it() }
|
||||
// }
|
||||
|
||||
fun onCreated(f: () -> Unit) {
|
||||
getCallbacks<() -> Unit>(2).add(f)
|
||||
|
@ -83,7 +85,7 @@ interface OnChangeListen : CanOnCallback {
|
|||
}
|
||||
}
|
||||
|
||||
interface OnTileClick {
|
||||
interface OnTileClick : CanOnCallback {
|
||||
fun onTileClicked(f: () -> Unit) {
|
||||
getCallbacks<() -> Unit>(14).add(f)
|
||||
}
|
||||
|
@ -91,4 +93,33 @@ interface OnTileClick {
|
|||
fun onTileClicked() {
|
||||
getCallbacks<() -> Unit>(14).forEach { it() }
|
||||
}
|
||||
}
|
||||
|
||||
fun CanOnCallback.useAliveFlow(stateFlow: MutableStateFlow<Boolean>) {
|
||||
if (this is OnCreate) {
|
||||
onCreated { stateFlow.value = true }
|
||||
}
|
||||
if (this is OnDestroy) {
|
||||
onDestroyed { stateFlow.value = false }
|
||||
}
|
||||
}
|
||||
|
||||
fun CanOnCallback.useLogLifecycle() {
|
||||
LogUtils.d("useLogLifecycle", this)
|
||||
if (this is OnCreate) {
|
||||
onCreated { LogUtils.d("onCreated", this) }
|
||||
}
|
||||
if (this is OnDestroy) {
|
||||
onDestroyed { LogUtils.d("onDestroyed", this) }
|
||||
}
|
||||
if (this is OnA11yConnected) {
|
||||
onA11yConnected { LogUtils.d("onA11yConnected", this) }
|
||||
}
|
||||
if (this is OnChangeListen) {
|
||||
onStartListened { LogUtils.d("onStartListened", this) }
|
||||
onStopListened { LogUtils.d("onStopListened", this) }
|
||||
}
|
||||
if (this is OnTileClick) {
|
||||
onTileClicked { LogUtils.d("onTileClicked", this) }
|
||||
}
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
package li.songe.gkd.util
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.app.Activity.RESULT_OK
|
||||
import android.content.Context
|
||||
|
@ -22,8 +21,10 @@ import kotlin.coroutines.suspendCoroutine
|
|||
|
||||
// https://github.com/npes87184/ScreenShareTile/blob/master/app/src/main/java/com/npes87184/screenshottile/ScreenshotService.kt
|
||||
|
||||
@SuppressLint("WrongConstant")
|
||||
class ScreenshotUtil(private val context: Context, private val screenshotIntent: Intent) {
|
||||
class ScreenshotUtil(
|
||||
private val context: Context,
|
||||
private val screenshotIntent: Intent
|
||||
) {
|
||||
|
||||
private val handler by lazy { Handler(Looper.getMainLooper()) }
|
||||
private var virtualDisplay: VirtualDisplay? = null
|
||||
|
@ -37,6 +38,13 @@ class ScreenshotUtil(private val context: Context, private val screenshotIntent:
|
|||
) as MediaProjectionManager
|
||||
}
|
||||
|
||||
private val width: Int
|
||||
get() = ScreenUtils.getScreenWidth()
|
||||
private val height: Int
|
||||
get() = ScreenUtils.getScreenHeight()
|
||||
private val dpi: Int
|
||||
get() = ScreenUtils.getScreenDensityDpi()
|
||||
|
||||
fun destroy() {
|
||||
imageReader?.setOnImageAvailableListener(null, null)
|
||||
virtualDisplay?.release()
|
||||
|
@ -101,10 +109,4 @@ class ScreenshotUtil(private val context: Context, private val screenshotIntent:
|
|||
}
|
||||
}, handler)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val width by lazy { ScreenUtils.getScreenWidth() }
|
||||
private val height by lazy { ScreenUtils.getScreenHeight() }
|
||||
private val dpi by lazy { ScreenUtils.getScreenDensityDpi() }
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user