perf: update ktor, kotlin

This commit is contained in:
lisonge 2024-10-11 12:00:00 +08:00
parent 8cca22d697
commit 2ae5698624
4 changed files with 96 additions and 99 deletions

View File

@ -5,10 +5,10 @@ import android.content.Intent
import com.blankj.utilcode.util.LogUtils import com.blankj.utilcode.util.LogUtils
import io.ktor.http.ContentType import io.ktor.http.ContentType
import io.ktor.serialization.kotlinx.json.json import io.ktor.serialization.kotlinx.json.json
import io.ktor.server.application.call
import io.ktor.server.application.install import io.ktor.server.application.install
import io.ktor.server.cio.CIO import io.ktor.server.cio.CIO
import io.ktor.server.cio.CIOApplicationEngine import io.ktor.server.cio.CIOApplicationEngine
import io.ktor.server.engine.EmbeddedServer
import io.ktor.server.engine.embeddedServer import io.ktor.server.engine.embeddedServer
import io.ktor.server.plugins.contentnegotiation.ContentNegotiation import io.ktor.server.plugins.contentnegotiation.ContentNegotiation
import io.ktor.server.request.receive import io.ktor.server.request.receive
@ -22,6 +22,7 @@ import io.ktor.server.routing.route
import io.ktor.server.routing.routing import io.ktor.server.routing.routing
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.cancel import kotlinx.coroutines.cancel
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
@ -57,19 +58,21 @@ import java.io.File
class HttpService : Service() { class HttpService : Service() {
private val scope = CoroutineScope(Dispatchers.Default) private val scope = MainScope()
private val httpServerPortFlow = storeFlow.map(scope) { s -> s.httpServerPort }
private var server: EmbeddedServer<CIOApplicationEngine, CIOApplicationEngine.Configuration>? =
null
private var server: CIOApplicationEngine? = null
override fun onCreate() { override fun onCreate() {
super.onCreate() super.onCreate()
isRunning.value = true isRunning.value = true
localNetworkIpsFlow.value = getIpAddressInLocalNetwork() localNetworkIpsFlow.value = getIpAddressInLocalNetwork()
val httpServerPortFlow = storeFlow.map(scope) { s -> s.httpServerPort }
scope.launchTry(Dispatchers.IO) { scope.launchTry(Dispatchers.IO) {
httpServerPortFlow.collect { port -> httpServerPortFlow.collect { port ->
server?.stop() server?.stop()
server = try { server = try {
createServer(port).apply { start() } scope.createServer(port).apply { start() }
} catch (e: Exception) { } catch (e: Exception) {
LogUtils.d("HTTP服务启动失败", e) LogUtils.d("HTTP服务启动失败", e)
null null
@ -86,16 +89,11 @@ class HttpService : Service() {
override fun onDestroy() { override fun onDestroy() {
super.onDestroy() super.onDestroy()
scope.cancel()
isRunning.value = false isRunning.value = false
localNetworkIpsFlow.value = emptyList() localNetworkIpsFlow.value = emptyList()
if (storeFlow.value.autoClearMemorySubs) {
scope.launchTry(Dispatchers.IO) { deleteSubscription(LOCAL_HTTP_SUBS_ID)
server?.stop()
if (storeFlow.value.autoClearMemorySubs) {
deleteSubscription(LOCAL_HTTP_SUBS_ID)
}
delay(3000)
scope.cancel()
} }
} }
@ -150,95 +148,93 @@ private val httpSubsItem by lazy {
) )
} }
private fun createServer(port: Int): CIOApplicationEngine { private fun CoroutineScope.createServer(port: Int) = embeddedServer(CIO, port) {
return embeddedServer(CIO, port) { install(KtorCorsPlugin)
install(KtorCorsPlugin) install(KtorErrorPlugin)
install(KtorErrorPlugin) install(ContentNegotiation) { json(keepNullJson) }
install(ContentNegotiation) { json(keepNullJson) } routing {
routing { get("/") { call.respondText(ContentType.Text.Html) { "<script type='module' src='$SERVER_SCRIPT_URL'></script>" } }
get("/") { call.respondText(ContentType.Text.Html) { "<script type='module' src='$SERVER_SCRIPT_URL'></script>" } } route("/api") {
route("/api") { // Deprecated
// Deprecated get("/device") { call.respond(DeviceInfo.instance) }
get("/device") { call.respond(DeviceInfo.instance) }
post("/getServerInfo") { call.respond(ServerInfo()) } post("/getServerInfo") { call.respond(ServerInfo()) }
// Deprecated // Deprecated
get("/snapshot") { get("/snapshot") {
val id = call.request.queryParameters["id"]?.toLongOrNull() val id = call.request.queryParameters["id"]?.toLongOrNull()
?: throw RpcError("miss id") ?: throw RpcError("miss id")
val fp = File(SnapshotExt.getSnapshotPath(id)) val fp = File(SnapshotExt.getSnapshotPath(id))
if (!fp.exists()) { if (!fp.exists()) {
throw RpcError("对应快照不存在") throw RpcError("对应快照不存在")
}
call.respondFile(fp)
} }
post("/getSnapshot") { call.respondFile(fp)
val data = call.receive<ReqId>() }
val fp = File(SnapshotExt.getSnapshotPath(data.id)) post("/getSnapshot") {
if (!fp.exists()) { val data = call.receive<ReqId>()
throw RpcError("对应快照不存在") val fp = File(SnapshotExt.getSnapshotPath(data.id))
} if (!fp.exists()) {
call.respond(fp) throw RpcError("对应快照不存在")
} }
call.respond(fp)
}
// Deprecated // Deprecated
get("/screenshot") { get("/screenshot") {
val id = call.request.queryParameters["id"]?.toLongOrNull() val id = call.request.queryParameters["id"]?.toLongOrNull()
?: throw RpcError("miss id") ?: throw RpcError("miss id")
val fp = File(SnapshotExt.getScreenshotPath(id)) val fp = File(SnapshotExt.getScreenshotPath(id))
if (!fp.exists()) { if (!fp.exists()) {
throw RpcError("对应截图不存在") throw RpcError("对应截图不存在")
}
call.respondFile(fp)
} }
post("/getScreenshot") { call.respondFile(fp)
val data = call.receive<ReqId>() }
val fp = File(SnapshotExt.getScreenshotPath(data.id)) post("/getScreenshot") {
if (!fp.exists()) { val data = call.receive<ReqId>()
throw RpcError("对应截图不存在") val fp = File(SnapshotExt.getScreenshotPath(data.id))
} if (!fp.exists()) {
call.respondFile(fp) throw RpcError("对应截图不存在")
} }
call.respondFile(fp)
}
// Deprecated // Deprecated
get("/captureSnapshot") { get("/captureSnapshot") {
call.respond(captureSnapshot()) call.respond(captureSnapshot())
} }
post("/captureSnapshot") { post("/captureSnapshot") {
call.respond(captureSnapshot()) call.respond(captureSnapshot())
} }
// Deprecated // Deprecated
get("/snapshots") { get("/snapshots") {
call.respond(DbSet.snapshotDao.query().first()) call.respond(DbSet.snapshotDao.query().first())
} }
post("/getSnapshots") { post("/getSnapshots") {
call.respond(DbSet.snapshotDao.query().first()) call.respond(DbSet.snapshotDao.query().first())
} }
post("/updateSubscription") { post("/updateSubscription") {
val subscription = val subscription =
RawSubscription.parse(call.receiveText(), json5 = false) RawSubscription.parse(call.receiveText(), json5 = false)
.copy( .copy(
id = LOCAL_HTTP_SUBS_ID, id = LOCAL_HTTP_SUBS_ID,
name = "内存订阅", name = "内存订阅",
version = 0, version = 0,
author = "@gkd-kit/inspect" author = "@gkd-kit/inspect"
) )
updateSubscription(subscription) updateSubscription(subscription)
DbSet.subsItemDao.insert((subsItemsFlow.value.find { s -> s.id == httpSubsItem.id } DbSet.subsItemDao.insert((subsItemsFlow.value.find { s -> s.id == httpSubsItem.id }
?: httpSubsItem).copy(mtime = System.currentTimeMillis())) ?: httpSubsItem).copy(mtime = System.currentTimeMillis()))
call.respond(RpcOk()) call.respond(RpcOk())
} }
post("/execSelector") { post("/execSelector") {
if (!A11yService.isRunning.value) { if (!A11yService.isRunning.value) {
throw RpcError("无障碍没有运行") throw RpcError("无障碍没有运行")
}
val gkdAction = call.receive<GkdAction>()
call.respond(A11yService.execAction(gkdAction))
} }
val gkdAction = call.receive<GkdAction>()
call.respond(A11yService.execAction(gkdAction))
} }
} }
} }
} }

View File

@ -84,6 +84,7 @@ suspend fun uploadFileToGithub(
})) }))
}.body<UploadPoliciesAssetsResponse>() }.body<UploadPoliciesAssetsResponse>()
val byteArray = file.readBytes()
// upload to s3 // upload to s3
client.post(policiesResp.upload_url) { client.post(policiesResp.upload_url) {
setCommonHeaders(cookie) setCommonHeaders(cookie)
@ -91,13 +92,13 @@ suspend fun uploadFileToGithub(
policiesResp.form.forEach { (key, value) -> policiesResp.form.forEach { (key, value) ->
append(key, value) append(key, value)
} }
append("file", file.readBytes(), Headers.build { append("file", byteArray, Headers.build {
append(HttpHeaders.ContentType, "application/x-zip-compressed") append(HttpHeaders.ContentType, "application/x-zip-compressed")
append(HttpHeaders.ContentDisposition, "filename=\"file.zip\"") append(HttpHeaders.ContentDisposition, "filename=\"file.zip\"")
}) })
})) }))
onUpload { bytesSentTotal, contentLength -> onUpload { bytesSentTotal, contentLength ->
listener(bytesSentTotal / contentLength.toFloat()) listener(bytesSentTotal / (contentLength ?: byteArray.size).toFloat())
} }
} }

View File

@ -44,8 +44,8 @@ data class NewVersion(
val versionName: String, val versionName: String,
val changelog: String, val changelog: String,
val downloadUrl: String, val downloadUrl: String,
val fileSize: Long,
val versionLogs: List<VersionLog> = emptyList(), val versionLogs: List<VersionLog> = emptyList(),
val fileSize: Long? = null,
) )
@Serializable @Serializable
@ -97,12 +97,12 @@ private fun UpdateStatus.startDownload(viewModel: MainViewModel, newVersion: New
job = viewModel.viewModelScope.launch(Dispatchers.IO) { job = viewModel.viewModelScope.launch(Dispatchers.IO) {
try { try {
val channel = client.get(URI(UPDATE_URL).resolve(newVersion.downloadUrl).toString()) { val channel = client.get(URI(UPDATE_URL).resolve(newVersion.downloadUrl).toString()) {
onDownload { bytesSentTotal, contentLength -> onDownload { bytesSentTotal, _ ->
// contentLength 在某些机型上概率错误 // contentLength 在某些机型上概率错误
val downloadStatus = downloadStatusFlow.value val downloadStatus = downloadStatusFlow.value
if (downloadStatus is LoadStatus.Loading) { if (downloadStatus is LoadStatus.Loading) {
downloadStatusFlow.value = LoadStatus.Loading( downloadStatusFlow.value = LoadStatus.Loading(
bytesSentTotal.toFloat() / (newVersion.fileSize ?: contentLength) bytesSentTotal.toFloat() / (newVersion.fileSize)
) )
} else if (downloadStatus is LoadStatus.Failure) { } else if (downloadStatus is LoadStatus.Failure) {
// 提前终止下载 // 提前终止下载

View File

@ -1,12 +1,12 @@
[versions] [versions]
kotlin = "2.0.20" kotlin = "2.0.21"
ksp = "2.0.20-1.0.25" ksp = "2.0.21-RC-1.0.25"
android = "8.7.0" android = "8.7.0"
compose = "1.7.3" compose = "1.7.3"
rikka = "4.4.0" rikka = "4.4.0"
room = "2.6.1" room = "2.6.1"
paging = "3.3.2" paging = "3.3.2"
ktor = "2.3.12" ktor = "3.0.0"
destinations = "2.1.0-beta12" destinations = "2.1.0-beta12"
coil = "2.7.0" coil = "2.7.0"
shizuku = "13.1.5" shizuku = "13.1.5"