Skip to content

Commit ad4961a

Browse files
runningcodeclaude
andcommitted
feat(android-distribution): Add build_configuration support and fix response parsing
- Add required buildConfiguration parameter to UpdateCheckParams - Update checkForUpdates to include build_configuration query parameter - Add debug logging to print full URL for debugging - Fix response parser to use correct backend format (update object instead of updateAvailable boolean) - Fix response parser to use snake_case field names to match backend API - Add toString methods to UpdateInfo and UpdateStatus classes for better debugging - Update all tests to match new response format 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent 9fbb112 commit ad4961a

File tree

8 files changed

+147
-44
lines changed

8 files changed

+147
-44
lines changed

sentry-android-distribution/src/main/java/io/sentry/android/distribution/DistributionHttpClient.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ internal class DistributionHttpClient(private val options: SentryOptions) {
2626
val platform: String = "android",
2727
val versionCode: Long,
2828
val versionName: String,
29+
val buildConfiguration: String,
2930
)
3031

3132
/**
@@ -56,9 +57,12 @@ internal class DistributionHttpClient(private val options: SentryOptions) {
5657
append("&platform=${URLEncoder.encode(params.platform, "UTF-8")}")
5758
append("&build_number=${URLEncoder.encode(params.versionCode.toString(), "UTF-8")}")
5859
append("&build_version=${URLEncoder.encode(params.versionName, "UTF-8")}")
60+
append("&build_configuration=${URLEncoder.encode(params.buildConfiguration, "UTF-8")}")
5961
}
6062
val url = URL(urlString)
6163

64+
options.logger.log(SentryLevel.DEBUG, "Distribution API URL: $urlString")
65+
6266
return try {
6367
makeRequest(url, authToken)
6468
} catch (e: IOException) {

sentry-android-distribution/src/main/java/io/sentry/android/distribution/DistributionIntegration.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,11 +132,16 @@ public class DistributionIntegration(context: Context) : Integration, IDistribut
132132
}
133133
val appId = context.applicationInfo.packageName
134134

135+
val buildConfiguration =
136+
sentryOptions.distribution.buildConfiguration
137+
?: throw IllegalStateException("buildConfiguration must be set in distribution options")
138+
135139
DistributionHttpClient.UpdateCheckParams(
136140
appId = appId,
137141
platform = "android",
138142
versionCode = versionCode,
139143
versionName = versionName,
144+
buildConfiguration = buildConfiguration,
140145
)
141146
} catch (e: PackageManager.NameNotFoundException) {
142147
sentryOptions.logger.log(SentryLevel.ERROR, e, "Failed to get package info")

sentry-android-distribution/src/main/java/io/sentry/android/distribution/UpdateResponseParser.kt

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,11 @@ internal class UpdateResponseParser(private val options: SentryOptions) {
3232

3333
options.logger.log(SentryLevel.DEBUG, "Parsing distribution API response")
3434

35-
// Check if there's a new release available
36-
val updateAvailable = json.optBoolean("updateAvailable", false)
35+
// Check if there's an update object in the response
36+
val updateJson = json.optJSONObject("update")
3737

38-
if (updateAvailable) {
39-
val updateInfo = parseUpdateInfo(json)
38+
if (updateJson != null) {
39+
val updateInfo = parseUpdateInfo(updateJson)
4040
UpdateStatus.NewRelease(updateInfo)
4141
} else {
4242
UpdateStatus.UpToDate.getInstance()
@@ -52,11 +52,11 @@ internal class UpdateResponseParser(private val options: SentryOptions) {
5252

5353
private fun parseUpdateInfo(json: JSONObject): UpdateInfo {
5454
val id = json.optString("id", "")
55-
val buildVersion = json.optString("buildVersion", "")
56-
val buildNumber = json.optInt("buildNumber", 0)
57-
val downloadUrl = json.optString("downloadUrl", "")
58-
val appName = json.optString("appName", "")
59-
val createdDate = json.optString("createdDate", "")
55+
val buildVersion = json.optString("build_version", "")
56+
val buildNumber = json.optInt("build_number", 0)
57+
val downloadUrl = json.optString("download_url", "")
58+
val appName = json.optString("app_name", "")
59+
val createdDate = json.optString("created_date", "")
6060

6161
// Validate required fields (optString returns "null" for null values)
6262
val missingFields = mutableListOf<String>()

sentry-android-distribution/src/test/java/io/sentry/android/distribution/DistributionHttpClientTest.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ class DistributionHttpClientTest {
3737
appId = "com.emergetools.hackernews",
3838
versionName = "1.0.0",
3939
versionCode = 5L,
40+
buildConfiguration = "release",
4041
)
4142

4243
val response = httpClient.checkForUpdates(params)

sentry-android-distribution/src/test/java/io/sentry/android/distribution/UpdateResponseParserTest.kt

Lines changed: 80 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,15 @@ class UpdateResponseParserTest {
2626
val responseBody =
2727
"""
2828
{
29-
"updateAvailable": true,
30-
"id": "update-123",
31-
"buildVersion": "2.0.0",
32-
"buildNumber": 42,
33-
"downloadUrl": "https://example.com/download",
34-
"appName": "Test App",
35-
"createdDate": "2023-10-01T00:00:00Z"
29+
"update": {
30+
"id": "update-123",
31+
"build_version": "2.0.0",
32+
"build_number": 42,
33+
"download_url": "https://example.com/download",
34+
"app_name": "Test App",
35+
"created_date": "2023-10-01T00:00:00Z"
36+
},
37+
"current": null
3638
}
3739
"""
3840
.trimIndent()
@@ -54,7 +56,15 @@ class UpdateResponseParserTest {
5456
val responseBody =
5557
"""
5658
{
57-
"updateAvailable": false
59+
"update": null,
60+
"current": {
61+
"id": "current-123",
62+
"build_version": "1.0.0",
63+
"build_number": 10,
64+
"download_url": "https://example.com/download",
65+
"app_name": "Test App",
66+
"created_date": "2023-09-01T00:00:00Z"
67+
}
5868
}
5969
"""
6070
.trimIndent()
@@ -65,11 +75,18 @@ class UpdateResponseParserTest {
6575
}
6676

6777
@Test
68-
fun `parseResponse returns UpToDate when updateAvailable is missing`() {
78+
fun `parseResponse returns UpToDate when update is missing`() {
6979
val responseBody =
7080
"""
7181
{
72-
"someOtherField": "value"
82+
"current": {
83+
"id": "current-123",
84+
"build_version": "1.0.0",
85+
"build_number": 10,
86+
"download_url": "https://example.com/download",
87+
"app_name": "Test App",
88+
"created_date": "2023-09-01T00:00:00Z"
89+
}
7390
}
7491
"""
7592
.trimIndent()
@@ -123,8 +140,9 @@ class UpdateResponseParserTest {
123140
val responseBody =
124141
"""
125142
{
126-
"updateAvailable": true,
127-
"buildVersion": "2.0.0"
143+
"update": {
144+
"build_version": "2.0.0"
145+
}
128146
}
129147
"""
130148
.trimIndent()
@@ -144,10 +162,14 @@ class UpdateResponseParserTest {
144162
val responseBody =
145163
"""
146164
{
147-
"updateAvailable": true,
148-
"id": "update-123",
149-
"buildVersion": "2.0.0",
150-
"downloadUrl": "https://example.com/download"
165+
"update": {
166+
"id": "update-123",
167+
"build_version": "2.0.0",
168+
"build_number": 0,
169+
"download_url": "https://example.com/download",
170+
"app_name": "",
171+
"created_date": ""
172+
}
151173
}
152174
"""
153175
.trimIndent()
@@ -181,10 +203,14 @@ class UpdateResponseParserTest {
181203
val responseBody =
182204
"""
183205
{
184-
"updateAvailable": true,
185-
"id": null,
186-
"buildVersion": "2.0.0",
187-
"downloadUrl": "https://example.com/download"
206+
"update": {
207+
"id": null,
208+
"build_version": "2.0.0",
209+
"build_number": 10,
210+
"download_url": "https://example.com/download",
211+
"app_name": "Test App",
212+
"created_date": "2023-10-01T00:00:00Z"
213+
}
188214
}
189215
"""
190216
.trimIndent()
@@ -204,9 +230,13 @@ class UpdateResponseParserTest {
204230
val responseBody =
205231
"""
206232
{
207-
"updateAvailable": true,
208-
"buildVersion": "2.0.0",
209-
"downloadUrl": "https://example.com/download"
233+
"update": {
234+
"build_version": "2.0.0",
235+
"build_number": 10,
236+
"download_url": "https://example.com/download",
237+
"app_name": "Test App",
238+
"created_date": "2023-10-01T00:00:00Z"
239+
}
210240
}
211241
"""
212242
.trimIndent()
@@ -226,9 +256,13 @@ class UpdateResponseParserTest {
226256
val responseBody =
227257
"""
228258
{
229-
"updateAvailable": true,
230-
"id": "update-123",
231-
"downloadUrl": "https://example.com/download"
259+
"update": {
260+
"id": "update-123",
261+
"build_number": 10,
262+
"download_url": "https://example.com/download",
263+
"app_name": "Test App",
264+
"created_date": "2023-10-01T00:00:00Z"
265+
}
232266
}
233267
"""
234268
.trimIndent()
@@ -248,9 +282,13 @@ class UpdateResponseParserTest {
248282
val responseBody =
249283
"""
250284
{
251-
"updateAvailable": true,
252-
"id": "update-123",
253-
"buildVersion": "2.0.0"
285+
"update": {
286+
"id": "update-123",
287+
"build_version": "2.0.0",
288+
"build_number": 10,
289+
"app_name": "Test App",
290+
"created_date": "2023-10-01T00:00:00Z"
291+
}
254292
}
255293
"""
256294
.trimIndent()
@@ -270,8 +308,11 @@ class UpdateResponseParserTest {
270308
val responseBody =
271309
"""
272310
{
273-
"updateAvailable": true,
274-
"buildNumber": 42
311+
"update": {
312+
"build_number": 42,
313+
"app_name": "Test App",
314+
"created_date": "2023-10-01T00:00:00Z"
315+
}
275316
}
276317
"""
277318
.trimIndent()
@@ -293,10 +334,14 @@ class UpdateResponseParserTest {
293334
val responseBody =
294335
"""
295336
{
296-
"updateAvailable": true,
297-
"id": "null",
298-
"buildVersion": "2.0.0",
299-
"downloadUrl": "https://example.com/download"
337+
"update": {
338+
"id": "null",
339+
"build_version": "2.0.0",
340+
"build_number": 10,
341+
"download_url": "https://example.com/download",
342+
"app_name": "Test App",
343+
"created_date": "2023-10-01T00:00:00Z"
344+
}
300345
}
301346
"""
302347
.trimIndent()

sentry/api/sentry.api

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4354,6 +4354,7 @@ public final class io/sentry/UpdateInfo {
43544354
public fun getCreatedDate ()Ljava/lang/String;
43554355
public fun getDownloadUrl ()Ljava/lang/String;
43564356
public fun getId ()Ljava/lang/String;
4357+
public fun toString ()Ljava/lang/String;
43574358
}
43584359

43594360
public abstract class io/sentry/UpdateStatus {
@@ -4363,20 +4364,24 @@ public abstract class io/sentry/UpdateStatus {
43634364
public final class io/sentry/UpdateStatus$NewRelease : io/sentry/UpdateStatus {
43644365
public fun <init> (Lio/sentry/UpdateInfo;)V
43654366
public fun getInfo ()Lio/sentry/UpdateInfo;
4367+
public fun toString ()Ljava/lang/String;
43664368
}
43674369

43684370
public final class io/sentry/UpdateStatus$NoNetwork : io/sentry/UpdateStatus {
43694371
public fun <init> (Ljava/lang/String;)V
43704372
public fun getMessage ()Ljava/lang/String;
4373+
public fun toString ()Ljava/lang/String;
43714374
}
43724375

43734376
public final class io/sentry/UpdateStatus$UpToDate : io/sentry/UpdateStatus {
43744377
public static fun getInstance ()Lio/sentry/UpdateStatus$UpToDate;
4378+
public fun toString ()Ljava/lang/String;
43754379
}
43764380

43774381
public final class io/sentry/UpdateStatus$UpdateError : io/sentry/UpdateStatus {
43784382
public fun <init> (Ljava/lang/String;)V
43794383
public fun getMessage ()Ljava/lang/String;
4384+
public fun toString ()Ljava/lang/String;
43804385
}
43814386

43824387
public final class io/sentry/UserFeedback : io/sentry/JsonSerializable, io/sentry/JsonUnknown {

sentry/src/main/java/io/sentry/UpdateInfo.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,4 +52,27 @@ public int getBuildNumber() {
5252
public @Nullable String getCreatedDate() {
5353
return createdDate;
5454
}
55+
56+
@Override
57+
public String toString() {
58+
return "UpdateInfo{"
59+
+ "id='"
60+
+ id
61+
+ '\''
62+
+ ", buildVersion='"
63+
+ buildVersion
64+
+ '\''
65+
+ ", buildNumber="
66+
+ buildNumber
67+
+ ", downloadUrl='"
68+
+ downloadUrl
69+
+ '\''
70+
+ ", appName='"
71+
+ appName
72+
+ '\''
73+
+ ", createdDate='"
74+
+ createdDate
75+
+ '\''
76+
+ '}';
77+
}
5578
}

sentry/src/main/java/io/sentry/UpdateStatus.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ private UpToDate() {}
1616
public static UpToDate getInstance() {
1717
return INSTANCE;
1818
}
19+
20+
@Override
21+
public String toString() {
22+
return "UpdateStatus.UpToDate{}";
23+
}
1924
}
2025

2126
/** A new release is available for download. */
@@ -29,6 +34,11 @@ public NewRelease(final @NotNull UpdateInfo info) {
2934
public @NotNull UpdateInfo getInfo() {
3035
return info;
3136
}
37+
38+
@Override
39+
public String toString() {
40+
return "UpdateStatus.NewRelease{" + "info=" + info + '}';
41+
}
3242
}
3343

3444
/** An error occurred during the update check. */
@@ -42,6 +52,11 @@ public UpdateError(final @NotNull String message) {
4252
public @NotNull String getMessage() {
4353
return message;
4454
}
55+
56+
@Override
57+
public String toString() {
58+
return "UpdateStatus.UpdateError{" + "message='" + message + '\'' + '}';
59+
}
4560
}
4661

4762
/** No network connection is available to check for updates. */
@@ -55,5 +70,10 @@ public NoNetwork(final @NotNull String message) {
5570
public @NotNull String getMessage() {
5671
return message;
5772
}
73+
74+
@Override
75+
public String toString() {
76+
return "UpdateStatus.NoNetwork{" + "message='" + message + '\'' + '}';
77+
}
5878
}
5979
}

0 commit comments

Comments
 (0)