feat: Android SDK update for version 24.1.0#123
Conversation
Greptile SummaryThis PR delivers the Android SDK 24.1.0 update, adding the
Confidence Score: 4/5The new Insight and Report models will throw NullPointerException from toMap() whenever their optional fields are null — a common state — which needs to be fixed before shipping. Two new model classes (Insight and Report) have a runtime crash in toMap(): nullable fields are cast with library/src/main/java/io/appwrite/models/Insight.kt and library/src/main/java/io/appwrite/models/Report.kt both have the toMap() null-cast issue. Important Files Changed
Reviews (2): Last reviewed commit: "chore: update Android SDK to 24.1.0" | Re-trigger Greptile |
| if (cookie.persistent) { | ||
| if (cookie.expiresAt == Long.MIN_VALUE) { | ||
| append("; Max-Age=0") | ||
| } else { | ||
| append("; Expires=").append(formatHttpDate(cookie.expiresAt)) | ||
| } | ||
| } |
There was a problem hiding this comment.
Long.MIN_VALUE sentinel branch is dead code
OkHttp 5.x only sets expiresAt = Long.MIN_VALUE when the incoming Max-Age value is negative or overflows MAX_AGE_CAP. A Max-Age=0 cookie gets expiresAt ≈ System.currentTimeMillis() — not Long.MIN_VALUE. The branch never fires in practice and the cookie is serialised with Expires=<past-timestamp> instead of Max-Age=0. Both forms expire the cookie correctly in java.net.CookieHandler, but the intent of the guard should be documented so future reviewers can verify correctness if OkHttp internals change.
| if (cookie.persistent) { | |
| if (cookie.expiresAt == Long.MIN_VALUE) { | |
| append("; Max-Age=0") | |
| } else { | |
| append("; Expires=").append(formatHttpDate(cookie.expiresAt)) | |
| } | |
| } | |
| if (cookie.persistent) { | |
| // OkHttp sets expiresAt=Long.MIN_VALUE only for negative/overflow Max-Age; | |
| // Max-Age=0 produces expiresAt≈currentTimeMillis(), which serialises | |
| // as a past Expires= date — both cause CookieHandler to delete the entry. | |
| if (cookie.expiresAt == Long.MIN_VALUE) { | |
| append("; Max-Age=0") | |
| } else { | |
| append("; Expires=").append(formatHttpDate(cookie.expiresAt)) | |
| } | |
| } |
| @SerializedName("status") | ||
| var status: String?, | ||
|
|
||
| /** | ||
| * Presence source. | ||
| */ | ||
| @SerializedName("source") | ||
| val source: String, | ||
|
|
||
| /** | ||
| * Presence expiry date in ISO 8601 format. | ||
| */ | ||
| @SerializedName("expiresAt") | ||
| var expiresAt: String?, |
There was a problem hiding this comment.
status and expiresAt are var while every other field is val
Mutable fields in a data class break structural equality (equals/hashCode), make the class unsafe as a map key, and are inconsistent with every other model in this PR. Unless the SDK intentionally mutates these fields after construction, they should be val.
| @SerializedName("status") | |
| var status: String?, | |
| /** | |
| * Presence source. | |
| */ | |
| @SerializedName("source") | |
| val source: String, | |
| /** | |
| * Presence expiry date in ISO 8601 format. | |
| */ | |
| @SerializedName("expiresAt") | |
| var expiresAt: String?, | |
| @SerializedName("status") | |
| val status: String?, | |
| /** | |
| * Presence source. | |
| */ | |
| @SerializedName("source") | |
| val source: String, | |
| /** | |
| * Presence expiry date in ISO 8601 format. | |
| */ | |
| @SerializedName("expiresAt") | |
| val expiresAt: String?, |
| * | ||
| * The user cookie to authenticate with. Used by SDKs that forward an incoming Cookie header in server-side runtimes. | ||
| * | ||
| * @param {string} cookie |
There was a problem hiding this comment.
JSDoc-style
{string} type annotation in KDoc comment
The @param {string} cookie uses JSDoc syntax rather than KDoc/Javadoc style, which is inconsistent with every other KDoc block in Client.kt.
| * @param {string} cookie | |
| * @param cookie |
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
| "analyzedAt" to analyzedAt as Any, | ||
| "dismissedAt" to dismissedAt as Any, | ||
| "dismissedBy" to dismissedBy as Any, |
There was a problem hiding this comment.
In Kotlin, casting a nullable value to a non-nullable type with
as Any throws NullPointerException at runtime when the value is null. Since analyzedAt, dismissedAt, and dismissedBy are all String? and will be null for any insight that hasn't been analyzed or dismissed, every call to toMap() on such an instance crashes. The same bug exists in Report.toMap() for its analyzedAt field. Change these three entries to as Any? (and update the return type to Map<String, Any?>), or omit null entries from the map.
| "analyzedAt" to analyzedAt as Any, | |
| "dismissedAt" to dismissedAt as Any, | |
| "dismissedBy" to dismissedBy as Any, | |
| "analyzedAt" to analyzedAt as Any?, | |
| "dismissedAt" to dismissedAt as Any?, | |
| "dismissedBy" to dismissedBy as Any?, |
This PR contains updates to the Android SDK for version 24.1.0.
What's Changed
presenceschannel andRealtimePresencetypes for presence subscriptionsAdvisorandPresencesservicesInsight,Presence, andReportmodels with list variantsfusionauth,keycloak, andkickproviders toOAuthProviderenumbuild.gradle.kts)X-Appwrite-Response-Formatheader to1.9.5