mirror of
https://github.com/karasevm/PrivateDNSAndroid.git
synced 2025-06-28 12:19:57 +00:00
Replace gson with kotlinx-serialization
This commit is contained in:
parent
fa9d259a21
commit
6a5f405211
7 changed files with 50 additions and 53 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -67,3 +67,6 @@ fastlane/Preview.html
|
|||
fastlane/screenshots
|
||||
fastlane/test_output
|
||||
fastlane/readme.md
|
||||
|
||||
# kotlin
|
||||
.kotlin/
|
||||
|
|
2
.idea/kotlinc.xml
generated
2
.idea/kotlinc.xml
generated
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="KotlinJpsPluginSettings">
|
||||
<option name="version" value="1.9.10" />
|
||||
<option name="version" value="2.0.20" />
|
||||
</component>
|
||||
</project>
|
|
@ -2,6 +2,7 @@ plugins {
|
|||
id 'com.android.application'
|
||||
id 'kotlin-android'
|
||||
id 'com.google.devtools.ksp'
|
||||
id 'org.jetbrains.kotlin.plugin.serialization'
|
||||
}
|
||||
|
||||
android {
|
||||
|
@ -51,11 +52,12 @@ dependencies {
|
|||
implementation 'androidx.appcompat:appcompat:1.7.0'
|
||||
implementation 'androidx.recyclerview:recyclerview:1.3.2'
|
||||
implementation 'androidx.activity:activity-ktx:1.9.2'
|
||||
implementation 'androidx.fragment:fragment-ktx:1.8.3'
|
||||
implementation 'androidx.fragment:fragment-ktx:1.8.4'
|
||||
implementation 'com.google.android.material:material:1.12.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
|
||||
implementation 'com.google.guava:guava:33.1.0-android'
|
||||
implementation 'com.google.code.gson:gson:2.11.0'
|
||||
implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.3'
|
||||
|
||||
|
||||
def shizuku_version = '13.1.5'
|
||||
implementation "dev.rikka.shizuku:api:$shizuku_version"
|
||||
|
@ -71,7 +73,7 @@ dependencies {
|
|||
androidTestImplementation "androidx.room:room-testing:$roomVersion"
|
||||
|
||||
// Lifecycle components
|
||||
def lifecycleVersion = '2.8.5'
|
||||
def lifecycleVersion = '2.8.6'
|
||||
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycleVersion"
|
||||
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycleVersion"
|
||||
implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycleVersion"
|
||||
|
|
|
@ -3,19 +3,21 @@ package ru.karasevm.privatednstoggle.model
|
|||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
// All fields must have default values for proper deserialization
|
||||
@Serializable
|
||||
@Entity(tableName = "dns_servers")
|
||||
data class DnsServer(
|
||||
@SerializedName("id")
|
||||
@SerialName("id")
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
val id: Int = 0,
|
||||
@SerializedName("server")
|
||||
@SerialName("server")
|
||||
val server: String = "",
|
||||
@SerializedName("label")
|
||||
@SerialName("label")
|
||||
val label: String = "",
|
||||
@SerializedName("enabled")
|
||||
@SerialName("enabled")
|
||||
@ColumnInfo(defaultValue = "1")
|
||||
val enabled: Boolean = true,
|
||||
val sortOrder: Int? = null
|
||||
|
|
|
@ -27,12 +27,9 @@ import androidx.recyclerview.widget.ItemTouchHelper.DOWN
|
|||
import androidx.recyclerview.widget.ItemTouchHelper.UP
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.GsonBuilder
|
||||
import com.google.gson.JsonSyntaxException
|
||||
import com.google.gson.ToNumberPolicy
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.serialization.encodeToString
|
||||
import kotlinx.serialization.json.Json
|
||||
import org.lsposed.hiddenapibypass.HiddenApiBypass
|
||||
import rikka.shizuku.Shizuku
|
||||
import rikka.shizuku.ShizukuBinderWrapper
|
||||
|
@ -58,7 +55,6 @@ class MainActivity : AppCompatActivity(), AddServerDialogFragment.NoticeDialogLi
|
|||
private lateinit var sharedPrefs: SharedPreferences
|
||||
private lateinit var adapter: ServerListRecyclerAdapter
|
||||
private lateinit var clipboard: ClipboardManager
|
||||
private lateinit var gson: Gson
|
||||
private val dnsServerViewModel: DnsServerViewModel by viewModels { DnsServerViewModelFactory((application as PrivateDNSApp).repository) }
|
||||
|
||||
private val itemTouchHelper by lazy {
|
||||
|
@ -126,7 +122,7 @@ class MainActivity : AppCompatActivity(), AddServerDialogFragment.NoticeDialogLi
|
|||
|
||||
private fun importSettings(json: String) {
|
||||
runCatching {
|
||||
val data: BackupUtils.Backup = gson.fromJson(json, BackupUtils.Backup::class.java)
|
||||
val data: BackupUtils.Backup = Json.decodeFromString<BackupUtils.Backup>(json)
|
||||
BackupUtils.import(data, dnsServerViewModel, sharedPrefs)
|
||||
}.onSuccess {
|
||||
Toast.makeText(
|
||||
|
@ -134,28 +130,18 @@ class MainActivity : AppCompatActivity(), AddServerDialogFragment.NoticeDialogLi
|
|||
).show()
|
||||
}.onFailure { exception ->
|
||||
runCatching {
|
||||
val objectType = object : TypeToken<Map<String, Any>>() {}.type
|
||||
val data: Map<String, Any> = gson.fromJson(json, objectType)
|
||||
Log.e("IMPORT", "Malformed json, falling back to legacy", exception)
|
||||
val data = Json.decodeFromString<BackupUtils.LegacyBackup>(json)
|
||||
BackupUtils.importLegacy(data, dnsServerViewModel, sharedPrefs)
|
||||
}.onSuccess {
|
||||
Toast.makeText(
|
||||
this, getString(R.string.import_success), Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}.onFailure {
|
||||
}.onFailure { exception ->
|
||||
Log.e("IMPORT", "Import failed", exception)
|
||||
when (exception) {
|
||||
is JsonSyntaxException -> {
|
||||
Toast.makeText(
|
||||
this, getString(R.string.import_failure_json), Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
|
||||
else -> {
|
||||
Toast.makeText(
|
||||
this, getString(R.string.import_failure), Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
}
|
||||
Toast.makeText(
|
||||
this, getString(R.string.import_failure), Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -193,7 +179,6 @@ class MainActivity : AppCompatActivity(), AddServerDialogFragment.NoticeDialogLi
|
|||
|
||||
sharedPrefs = PreferenceHelper.defaultPreference(this)
|
||||
clipboard = getSystemService(CLIPBOARD_SERVICE) as ClipboardManager
|
||||
gson = GsonBuilder().setObjectToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE).create()
|
||||
|
||||
migrateServerList()
|
||||
|
||||
|
@ -249,7 +234,7 @@ class MainActivity : AppCompatActivity(), AddServerDialogFragment.NoticeDialogLi
|
|||
R.id.export_settings_clipboard -> {
|
||||
dnsServerViewModel.viewModelScope.launch {
|
||||
val data = BackupUtils.export(dnsServerViewModel, sharedPrefs)
|
||||
val jsonData = gson.toJson(data)
|
||||
val jsonData = Json.encodeToString(data)
|
||||
clipboard.setPrimaryClip(ClipData.newPlainText("", jsonData))
|
||||
// Only show a toast for Android 12 and lower.
|
||||
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.S_V2) Toast.makeText(
|
||||
|
@ -263,7 +248,7 @@ class MainActivity : AppCompatActivity(), AddServerDialogFragment.NoticeDialogLi
|
|||
val activityContext = this
|
||||
dnsServerViewModel.viewModelScope.launch {
|
||||
val data = BackupUtils.export(dnsServerViewModel, sharedPrefs)
|
||||
val jsonData = gson.toJson(data)
|
||||
val jsonData = Json.encodeToString(data)
|
||||
ShareCompat.IntentBuilder(activityContext).setText(jsonData)
|
||||
.setType("text/plain")
|
||||
.startChooser()
|
||||
|
@ -319,7 +304,7 @@ class MainActivity : AppCompatActivity(), AddServerDialogFragment.NoticeDialogLi
|
|||
if (result.resultCode == RESULT_OK) {
|
||||
val data: Intent? = result.data
|
||||
data?.data?.also { uri ->
|
||||
val jsonData = gson.toJson(BackupUtils.export(dnsServerViewModel, sharedPrefs))
|
||||
val jsonData = Json.encodeToString(BackupUtils.export(dnsServerViewModel, sharedPrefs))
|
||||
val contentResolver = applicationContext.contentResolver
|
||||
runCatching {
|
||||
contentResolver.openOutputStream(uri)?.use { outputStream ->
|
||||
|
|
|
@ -1,20 +1,26 @@
|
|||
package ru.karasevm.privatednstoggle.util
|
||||
|
||||
import android.content.SharedPreferences
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
import ru.karasevm.privatednstoggle.data.DnsServerViewModel
|
||||
import ru.karasevm.privatednstoggle.model.DnsServer
|
||||
import ru.karasevm.privatednstoggle.util.PreferenceHelper.AUTO_MODE
|
||||
import ru.karasevm.privatednstoggle.util.PreferenceHelper.DNS_SERVERS
|
||||
import ru.karasevm.privatednstoggle.util.PreferenceHelper.REQUIRE_UNLOCK
|
||||
import ru.karasevm.privatednstoggle.util.PreferenceHelper.autoMode
|
||||
import ru.karasevm.privatednstoggle.util.PreferenceHelper.requireUnlock
|
||||
|
||||
object BackupUtils {
|
||||
@Serializable
|
||||
data class Backup(
|
||||
@SerializedName("dns_servers") val dnsServers: List<DnsServer>,
|
||||
@SerializedName("auto_mode") val autoMode: Int?,
|
||||
@SerializedName("require_unlock") val requireUnlock: Boolean?,
|
||||
@SerialName("dns_servers") val dnsServers: List<DnsServer>,
|
||||
@SerialName("auto_mode") val autoMode: Int?,
|
||||
@SerialName("require_unlock") val requireUnlock: Boolean?,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class LegacyBackup(
|
||||
@SerialName("dns_servers") val dnsServers: String,
|
||||
@SerialName("auto_mode") val autoMode: Int?,
|
||||
@SerialName("require_unlock") val requireUnlock: Boolean?,
|
||||
)
|
||||
|
||||
/**
|
||||
|
@ -47,17 +53,16 @@ object BackupUtils {
|
|||
|
||||
/**
|
||||
* Imports old server list
|
||||
* @param map Deserialized backup
|
||||
* @param legacyBackup Deserialized backup
|
||||
* @param viewModel View model
|
||||
* @param sharedPreferences Shared preferences
|
||||
*/
|
||||
fun importLegacy(
|
||||
map: Map<String, Any>,
|
||||
legacyBackup: LegacyBackup,
|
||||
viewModel: DnsServerViewModel,
|
||||
sharedPreferences: SharedPreferences
|
||||
) {
|
||||
map[DNS_SERVERS]?.let { servers ->
|
||||
if (servers is String) {
|
||||
legacyBackup.dnsServers.let { servers ->
|
||||
val serverList = servers.split(",")
|
||||
serverList.forEach { server ->
|
||||
val parts = server.split(" : ")
|
||||
|
@ -67,9 +72,8 @@ object BackupUtils {
|
|||
viewModel.insert(DnsServer(0, server, ""))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
sharedPreferences.autoMode = map[AUTO_MODE] as? Int ?: 0
|
||||
sharedPreferences.requireUnlock = map[REQUIRE_UNLOCK] as? Boolean ?: false
|
||||
sharedPreferences.autoMode = legacyBackup.autoMode?: 0
|
||||
sharedPreferences.requireUnlock = legacyBackup.requireUnlock?: false
|
||||
}
|
||||
}
|
|
@ -6,15 +6,16 @@ buildscript {
|
|||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:8.5.2'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.10"
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:2.0.20"
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
}
|
||||
}
|
||||
plugins {
|
||||
id 'org.jetbrains.kotlin.android' version '1.9.10' apply false
|
||||
id "com.google.devtools.ksp" version "1.9.10-1.0.13" apply false
|
||||
id 'org.jetbrains.kotlin.android' version '2.0.20' apply false
|
||||
id 'org.jetbrains.kotlin.plugin.serialization' version '2.0.20'
|
||||
id "com.google.devtools.ksp" version "2.0.20-1.0.25" apply false
|
||||
}
|
||||
|
||||
tasks.register('clean', Delete) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue