From 6fe89ef6add5add9f5f1be8117e470ac5f9a5028 Mon Sep 17 00:00:00 2001 From: qwq233 Date: Tue, 2 Aug 2022 03:54:30 +0800 Subject: [PATCH] feat: replace gson with kotlinx-serialization Signed-off-by: qwq233 --- app/build.gradle.kts | 25 ++++++++ app/proguard-rules.pro | 27 ++++++++ .../github/qauxv/remote/TransactionHelper.kt | 41 ++++++------ .../singleneuron/base/bridge/CardMsgList.kt | 15 +++-- .../me/singleneuron/data/MiniAppArkData.kt | 64 +++++++++---------- .../me/singleneuron/data/StructMsgData.kt | 50 ++++++--------- .../java/me/singleneuron/util/KotlinUtils.kt | 20 +++--- build.gradle.kts | 23 +++++++ 8 files changed, 164 insertions(+), 101 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index e6c316d8..e5e34da7 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,3 +1,25 @@ +/* + * QAuxiliary - An Xposed module for QQ/TIM + * Copyright (C) 2019-2022 qwq233@qwq2333.top + * https://github.com/cinit/QAuxiliary + * + * This software is non-free but opensource software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation; either + * version 3 of the License, or any later version and our eula as published + * by QAuxiliary contributors. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * and eula along with this software. If not, see + * + * . + */ + import com.android.build.gradle.internal.tasks.factory.dependsOn import java.util.UUID @@ -5,6 +27,7 @@ plugins { id("com.android.application") id("org.jetbrains.kotlin.android") id("com.google.devtools.ksp") version "${Version.kotlin}-${Version.ksp}" + kotlin("plugin.serialization") version Version.kotlin } val currentBuildUuid = UUID.randomUUID().toString() @@ -157,6 +180,8 @@ dependencies { val appCenterSdkVersion = "4.4.5" implementation("com.microsoft.appcenter:appcenter-analytics:${appCenterSdkVersion}") implementation("com.microsoft.appcenter:appcenter-crashes:${appCenterSdkVersion}") + + implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.0-RC") } val adb: String = androidComponents.sdkComponents.adb.get().asFile.absolutePath diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 6141b0c1..e0ca1744 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -36,3 +36,30 @@ -dontwarn org.apache.bsf.util.BSFEngineImpl -dontwarn java.applet.Applet -dontwarn org.apache.bsf.* + +# Keep `Companion` object fields of serializable classes. +# This avoids serializer lookup through `getDeclaredClasses` as done for named companion objects. +-if @kotlinx.serialization.Serializable class ** +-keepclassmembers class <1> { + static <1>$Companion Companion; +} + +# Keep `serializer()` on companion objects (both default and named) of serializable classes. +-if @kotlinx.serialization.Serializable class ** { + static **$* *; +} +-keepclassmembers class <2>$<3> { + kotlinx.serialization.KSerializer serializer(...); +} + +# Keep `INSTANCE.serializer()` of serializable objects. +-if @kotlinx.serialization.Serializable class ** { + public static ** INSTANCE; +} +-keepclassmembers class <1> { + public static <1> INSTANCE; + kotlinx.serialization.KSerializer serializer(...); +} + +# @Serializable and @Polymorphic are used at runtime for polymorphic serialization. +-keepattributes RuntimeVisibleAnnotations,AnnotationDefault diff --git a/app/src/main/java/io/github/qauxv/remote/TransactionHelper.kt b/app/src/main/java/io/github/qauxv/remote/TransactionHelper.kt index 30506923..05993eae 100644 --- a/app/src/main/java/io/github/qauxv/remote/TransactionHelper.kt +++ b/app/src/main/java/io/github/qauxv/remote/TransactionHelper.kt @@ -22,16 +22,15 @@ package io.github.qauxv.remote -import com.google.gson.Gson -import com.google.gson.annotations.SerializedName -import com.google.gson.reflect.TypeToken import io.github.qauxv.BuildConfig import io.github.qauxv.SyncUtils import io.github.qauxv.config.ConfigManager import io.github.qauxv.util.LicenseStatus import io.github.qauxv.util.Log import io.github.qauxv.util.data.UserStatusConst -import org.json.JSONArray +import kotlinx.serialization.Serializable +import kotlinx.serialization.builtins.ListSerializer +import kotlinx.serialization.json.Json import org.json.JSONException import org.json.JSONObject import java.io.BufferedReader @@ -175,9 +174,9 @@ object TransactionHelper { val json = cfg.getString(KEY_MSG_SYNC_LIST, null) items = if (json.isNullOrEmpty()) { ArrayList() - } else { + } else ({ deserializeCardMsgSendRecordListFromJson(json) - } + }) as ArrayList items.removeIf { it.uuid == uuid } cfg.putString(KEY_MSG_SYNC_LIST, serializeCardMsgSendRecordListToJson(items)) } @@ -207,13 +206,15 @@ object TransactionHelper { os.writeBytes(request.toString()) os.flush() os.close() - val resp = JSONObject(convertInputStreamToString( - if (conn.responseCode >= 400) { - conn.errorStream - } else { - conn.inputStream - } - )!!) + val resp = JSONObject( + convertInputStreamToString( + if (conn.responseCode >= 400) { + conn.errorStream + } else { + conn.inputStream + } + )!! + ) if (resp.getInt("code") == 200) { if (BuildConfig.DEBUG) { Log.d("syncCardMsgHistory/requestSyncCardMsgHistory: ${r.uuid} $resp") @@ -246,11 +247,13 @@ object TransactionHelper { /** * [time] in ms */ + @Serializable data class CardMsgSendRecord( - @SerializedName("uin") val uin: Long, - @SerializedName("msg") val msg: String, - @SerializedName("time") val time: Long = System.currentTimeMillis(), - @SerializedName("uuid") val uuid: String = UUID.randomUUID().toString()) { + val uin: Long, + val msg: String, + val time: Long = System.currentTimeMillis(), + val uuid: String = UUID.randomUUID().toString() + ) { override fun toString(): String { return "CardMsgSendRecord(uin=$uin, msg='$msg', time=$time, uuid='$uuid')" @@ -267,11 +270,11 @@ object TransactionHelper { } else { list } - return Gson().toJsonTree(items, object : TypeToken?>() {}.type).asJsonArray.toString() + return Json.encodeToString(ListSerializer(CardMsgSendRecord.serializer()), list) } @Throws(JSONException::class) fun deserializeCardMsgSendRecordListFromJson(json: String): ArrayList = - Gson().fromJson(json, object : TypeToken?>() {}.type) + Json.decodeFromString(ListSerializer(CardMsgSendRecord.serializer()), json) as ArrayList } diff --git a/app/src/main/java/me/singleneuron/base/bridge/CardMsgList.kt b/app/src/main/java/me/singleneuron/base/bridge/CardMsgList.kt index 54a75eb7..24c153ce 100644 --- a/app/src/main/java/me/singleneuron/base/bridge/CardMsgList.kt +++ b/app/src/main/java/me/singleneuron/base/bridge/CardMsgList.kt @@ -1,13 +1,13 @@ /* - * QNotified - An Xposed module for QQ/TIM - * Copyright (C) 2019-2022 dmca@ioctl.cc - * https://github.com/ferredoxin/QNotified + * QAuxiliary - An Xposed module for QQ/TIM + * Copyright (C) 2019-2022 qwq233@qwq2333.top + * https://github.com/cinit/QAuxiliary * * This software is non-free but opensource software: you can redistribute it * and/or modify it under the terms of the GNU Affero General Public License * as published by the Free Software Foundation; either * version 3 of the License, or any later version and our eula as published - * by ferredoxin. + * by QAuxiliary contributors. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -17,15 +17,16 @@ * You should have received a copy of the GNU Affero General Public License * and eula along with this software. If not, see * - * . + * . */ package me.singleneuron.base.bridge import androidx.annotation.NonNull -import com.google.gson.Gson import io.github.qauxv.SyncUtils import io.github.qauxv.config.ConfigManager import io.github.qauxv.util.LicenseStatus +import kotlinx.serialization.encodeToString +import kotlinx.serialization.json.Json import java.net.URL const val apiAddress = "https://2fa.qwq2333.top/card/BlackList" @@ -55,7 +56,7 @@ fun getBuiltInRule(): String { "禁止音视频通话" to """ti\.qq\.com""", "禁止自动回复类卡片" to """com\.tencent\.autoreply""" ) - return Gson().toJson(map) + return Json.encodeToString(map) } fun getBlackList(): String { diff --git a/app/src/main/java/me/singleneuron/data/MiniAppArkData.kt b/app/src/main/java/me/singleneuron/data/MiniAppArkData.kt index 32d11cd8..46bbd8a6 100644 --- a/app/src/main/java/me/singleneuron/data/MiniAppArkData.kt +++ b/app/src/main/java/me/singleneuron/data/MiniAppArkData.kt @@ -1,13 +1,13 @@ /* - * QNotified - An Xposed module for QQ/TIM - * Copyright (C) 2019-2022 dmca@ioctl.cc - * https://github.com/ferredoxin/QNotified + * QAuxiliary - An Xposed module for QQ/TIM + * Copyright (C) 2019-2022 qwq233@qwq2333.top + * https://github.com/cinit/QAuxiliary * * This software is non-free but opensource software: you can redistribute it * and/or modify it under the terms of the GNU Affero General Public License * as published by the Free Software Foundation; either * version 3 of the License, or any later version and our eula as published - * by ferredoxin. + * by QAuxiliary contributors. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -17,43 +17,43 @@ * You should have received a copy of the GNU Affero General Public License * and eula along with this software. If not, see * - * . + * . */ package me.singleneuron.data -import com.google.gson.Gson -import com.google.gson.reflect.TypeToken -import java.lang.reflect.Type - -class MiniAppArkData { - - lateinit var desc: String - lateinit var prompt: String - lateinit var meta: Map - lateinit var config: ArkMsgConfigData - lateinit var extra: String +import kotlinx.serialization.Serializable +import kotlinx.serialization.decodeFromString +import kotlinx.serialization.json.Json +@Serializable +data class MiniAppArkData( + val desc: String, + val prompt: String, + val meta: Map, + val config: ArkMsgConfigData, + val extra: String, +) { companion object { @JvmStatic - fun fromJson(json: String): MiniAppArkData { - val type: Type = object : TypeToken() {}.type - return Gson().fromJson(json, type) - } + fun fromJson(json: String): MiniAppArkData = + Json.decodeFromString(json) + } - override fun toString(): String { - return Gson().toJson(this) - } + override fun toString(): String = + Json.encodeToString(serializer(), this) } -class MiniAppArkDetailData { - lateinit var desc: String - lateinit var preview: String - lateinit var qqdocurl: String - lateinit var title: String -} +@Serializable +class MiniAppArkDetailData( + val desc: String, + val preview: String, + val qqdocurl: String, + val title: String +) -class ArkMsgConfigData { - var ctime: Long = System.currentTimeMillis() / 1000 -} +@Serializable +data class ArkMsgConfigData( + val ctime: Long = System.currentTimeMillis() / 1000 +) diff --git a/app/src/main/java/me/singleneuron/data/StructMsgData.kt b/app/src/main/java/me/singleneuron/data/StructMsgData.kt index 9c41a580..b73118be 100644 --- a/app/src/main/java/me/singleneuron/data/StructMsgData.kt +++ b/app/src/main/java/me/singleneuron/data/StructMsgData.kt @@ -1,13 +1,13 @@ /* - * QNotified - An Xposed module for QQ/TIM - * Copyright (C) 2019-2022 dmca@ioctl.cc - * https://github.com/ferredoxin/QNotified + * QAuxiliary - An Xposed module for QQ/TIM + * Copyright (C) 2019-2022 qwq233@qwq2333.top + * https://github.com/cinit/QAuxiliary * * This software is non-free but opensource software: you can redistribute it * and/or modify it under the terms of the GNU Affero General Public License * as published by the Free Software Foundation; either * version 3 of the License, or any later version and our eula as published - * by ferredoxin. + * by QAuxiliary contributors. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -17,20 +17,19 @@ * You should have received a copy of the GNU Affero General Public License * and eula along with this software. If not, see * - * . + * . */ package me.singleneuron.data -import com.google.gson.Gson import io.github.qauxv.util.Log +import kotlinx.serialization.Serializable +import kotlinx.serialization.json.Json import org.json.JSONObject +@Serializable data class StructMsgData( - var prompt: String, - @Transient var news: StructMsgNewsData, - var config: StructMsgConfigData, - var extra: String + var prompt: String, var news: StructMsgNewsData, var config: StructMsgConfigData, var extra: String ) { val app: String = "com.tencent.structmsg" @@ -55,34 +54,23 @@ data class StructMsgData( fun fromMiniApp(miniApp: MiniAppArkData): StructMsgData { val detail_1 = miniApp.meta["detail_1"]!! return StructMsgData( - miniApp.prompt, - StructMsgNewsData( - detail_1.desc, - detail_1.qqdocurl, - detail_1.preview, - detail_1.title, - detail_1.title - ), - StructMsgConfigData( + miniApp.prompt, StructMsgNewsData( + detail_1.desc, detail_1.qqdocurl, detail_1.preview, detail_1.title, detail_1.title + ), StructMsgConfigData( miniApp.config.ctime - ), - miniApp.extra + ), miniApp.extra ) } } - override fun toString(): String { - return Gson().toJson(this) - } + override fun toString(): String = + Json.encodeToString(serializer(), this) } +@Serializable data class StructMsgNewsData( - var desc: String, - var jumpUrl: String, - var preview: String, - var tag: String, - var title: String + var desc: String, var jumpUrl: String, var preview: String, var tag: String, var title: String ) { val app_type: Int = 1 @@ -90,10 +78,10 @@ data class StructMsgNewsData( } +@Serializable data class StructMsgConfigData( var ctime: Long, - - ) { +) { val autosize: Boolean = true val forward: Boolean = true diff --git a/app/src/main/java/me/singleneuron/util/KotlinUtils.kt b/app/src/main/java/me/singleneuron/util/KotlinUtils.kt index b341cb08..cc252886 100644 --- a/app/src/main/java/me/singleneuron/util/KotlinUtils.kt +++ b/app/src/main/java/me/singleneuron/util/KotlinUtils.kt @@ -1,13 +1,13 @@ /* - * QNotified - An Xposed module for QQ/TIM - * Copyright (C) 2019-2022 dmca@ioctl.cc - * https://github.com/ferredoxin/QNotified + * QAuxiliary - An Xposed module for QQ/TIM + * Copyright (C) 2019-2022 qwq233@qwq2333.top + * https://github.com/cinit/QAuxiliary * * This software is non-free but opensource software: you can redistribute it * and/or modify it under the terms of the GNU Affero General Public License * as published by the Free Software Foundation; either * version 3 of the License, or any later version and our eula as published - * by ferredoxin. + * by QAuxiliary contributors. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -17,16 +17,16 @@ * You should have received a copy of the GNU Affero General Public License * and eula along with this software. If not, see * - * . + * . */ package me.singleneuron.util import android.content.Intent import android.view.View import android.view.ViewGroup -import com.google.gson.Gson -import com.google.gson.reflect.TypeToken import io.github.qauxv.util.Log +import kotlinx.serialization.decodeFromString +import kotlinx.serialization.json.Json import me.singleneuron.base.bridge.CardMsgList import me.singleneuron.data.CardMsgCheckResult import java.io.BufferedReader @@ -65,11 +65,7 @@ fun checkCardMsg(originString: String): CardMsgCheckResult { val string = decodePercent(originString) Log.d("decode string: $string") val blackListString = CardMsgList.getInstance().invoke() - val blackList = Gson().fromJson>( - blackListString, - object : TypeToken>() {}.type - ) - Log.d(Gson().toJson(blackList)) + val blackList = Json.decodeFromString>(blackListString) for (rule in blackList) { if (Regex( rule.value, diff --git a/build.gradle.kts b/build.gradle.kts index b97b6005..b61fd4d0 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,9 +1,32 @@ +/* + * QAuxiliary - An Xposed module for QQ/TIM + * Copyright (C) 2019-2022 qwq233@qwq2333.top + * https://github.com/cinit/QAuxiliary + * + * This software is non-free but opensource software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation; either + * version 3 of the License, or any later version and our eula as published + * by QAuxiliary contributors. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * and eula along with this software. If not, see + * + * . + */ + import com.android.build.gradle.BaseExtension plugins { id("com.android.application") version "7.2.1" apply false id("com.android.library") version "7.2.1" apply false id("org.jetbrains.kotlin.android") version Version.kotlin apply false + kotlin("plugin.serialization") version Version.kotlin apply false } tasks.register("clean").configure {