Skip to content

Commit e787d2a

Browse files
committed
fix gson npe when deserializing older preset versions
Although, I am fairly certain that R8 is causing this issue by mistakenly removing a critical member of PresetV* classes. After extensive debugging, I couldn't figure out what exactly it removes, but it seemingly concerns parameterized list type and player state class. Either adding `@Keep` annotation or replacing List types with Array resolves the issue.
1 parent 303cdea commit e787d2a

File tree

2 files changed

+66
-13
lines changed

2 files changed

+66
-13
lines changed

app/src/main/java/com/github/ashutoshgngwr/noice/models/Preset.kt

Lines changed: 65 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,10 @@ fun Preset.toRoomDto(gson: Gson): PresetDto {
5656
data class PresetV2(
5757
val id: String,
5858
val name: String,
59-
val playerStates: List<PlayerState>,
60-
) : Serializable {
59+
val playerStates: Array<PlayerState>,
60+
) {
6161

62-
constructor(name: String, playerStates: List<PlayerState>)
62+
constructor(name: String, playerStates: Array<PlayerState>)
6363
: this(UUID.randomUUID().toString(), name, playerStates)
6464

6565
/**
@@ -70,13 +70,27 @@ data class PresetV2(
7070
return Preset(id = id, name = name, soundStates = soundsV3)
7171
}
7272

73-
companion object {
74-
val GSON_TYPE_PLAYER_STATES: Type = TypeToken
75-
.getParameterized(List::class.java, PlayerState::class.java)
76-
.type
73+
override fun equals(other: Any?): Boolean {
74+
if (this === other) return true
75+
if (javaClass != other?.javaClass) return false
76+
77+
other as PresetV2
78+
79+
if (id != other.id) return false
80+
if (name != other.name) return false
81+
if (!playerStates.contentEquals(other.playerStates)) return false
82+
83+
return true
84+
}
85+
86+
override fun hashCode(): Int {
87+
var result = id.hashCode()
88+
result = 31 * result + name.hashCode()
89+
result = 31 * result + playerStates.contentHashCode()
90+
return result
7791
}
7892

79-
data class PlayerState(val soundId: String, val volume: Int) : Serializable
93+
data class PlayerState(val soundId: String, val volume: Int)
8094
}
8195

8296
/**
@@ -95,7 +109,7 @@ data class PresetV2(
95109
data class PresetV1(
96110
val id: String,
97111
val name: String,
98-
val playerStates: List<PlayerState>,
112+
val playerStates: Array<PlayerState>,
99113
) {
100114

101115
/**
@@ -113,7 +127,27 @@ data class PresetV1(
113127
}
114128

115129
playerStatesV2.sortBy { it.soundId }
116-
return PresetV2(id = id, name = name, playerStates = playerStatesV2)
130+
return PresetV2(id = id, name = name, playerStates = playerStatesV2.toTypedArray())
131+
}
132+
133+
override fun equals(other: Any?): Boolean {
134+
if (this === other) return true
135+
if (javaClass != other?.javaClass) return false
136+
137+
other as PresetV1
138+
139+
if (id != other.id) return false
140+
if (name != other.name) return false
141+
if (!playerStates.contentEquals(other.playerStates)) return false
142+
143+
return true
144+
}
145+
146+
override fun hashCode(): Int {
147+
var result = id.hashCode()
148+
result = 31 * result + name.hashCode()
149+
result = 31 * result + playerStates.contentHashCode()
150+
return result
117151
}
118152

119153
companion object {
@@ -176,7 +210,7 @@ data class PresetV1(
176210
*/
177211
data class PresetV0(
178212
@SerializedName("a") val name: String,
179-
@SerializedName("b") val playerStates: List<PlayerState>,
213+
@SerializedName("b") val playerStates: Array<PlayerState>,
180214
) {
181215

182216
/**
@@ -194,10 +228,29 @@ data class PresetV0(
194228
volume = (it.volume * 25).roundToInt(),
195229
timePeriod = it.timePeriod + 30,
196230
)
197-
},
231+
}
232+
.toTypedArray(),
198233
)
199234
}
200235

236+
override fun equals(other: Any?): Boolean {
237+
if (this === other) return true
238+
if (javaClass != other?.javaClass) return false
239+
240+
other as PresetV0
241+
242+
if (name != other.name) return false
243+
if (!playerStates.contentEquals(other.playerStates)) return false
244+
245+
return true
246+
}
247+
248+
override fun hashCode(): Int {
249+
var result = name.hashCode()
250+
result = 31 * result + playerStates.contentHashCode()
251+
return result
252+
}
253+
201254
data class PlayerState(
202255
@SerializedName("a") val soundKey: String,
203256
@SerializedName("b") val volume: Double,

app/src/main/java/com/github/ashutoshgngwr/noice/repository/PresetRepository.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ class PresetRepository @Inject constructor(
242242
URI_VERSION_0 -> {
243243
val playerStatesJson = uri.getQueryParameter(URI_PARAM_PLAYER_STATES) ?: return null
244244
return try {
245-
PresetV2(name, gson.fromJson(playerStatesJson, PresetV2.GSON_TYPE_PLAYER_STATES))
245+
PresetV2(name, gson.fromJson(playerStatesJson, Array<PresetV2.PlayerState>::class.java))
246246
.toPresetV3()
247247
} catch (e: JsonSyntaxException) {
248248
null

0 commit comments

Comments
 (0)