Skip to content

feat: Android SDK update for version 25.1.0#129

Merged
ChiragAgg5k merged 5 commits into
mainfrom
dev
Jun 8, 2026
Merged

feat: Android SDK update for version 25.1.0#129
ChiragAgg5k merged 5 commits into
mainfrom
dev

Conversation

@ChiragAgg5k
Copy link
Copy Markdown
Member

@ChiragAgg5k ChiragAgg5k commented Jun 8, 2026

This PR contains updates to the Android SDK for version 25.1.0.

@ChiragAgg5k ChiragAgg5k changed the title feat: Android SDK update for version 25.1.0 feat: SDK update for version 25.1.0 Jun 8, 2026
@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Jun 8, 2026

Greptile Summary

This PR updates the Android SDK to version 25.1.0, adding explicit accept and X-Appwrite-Project headers to every service endpoint where they were previously missing, and introducing new model fields for email metadata on User and access tracking on Membership.

  • Header consistency fix: All service methods (Account, Databases, TablesDB, Functions, Storage, Teams, Presences, Graphql, Locale, Messaging) now include \"X-Appwrite-Project\" and \"accept\" to \"application/json\" in their per-request header maps, correcting a gap that would have caused auth failures for any endpoint that was missing the project header before.
  • User model extension: Five nullable email metadata fields (emailCanonical, emailIsFree, emailIsDisposable, emailIsCorporate, emailIsCanonical) are added to User; they use safe casts in from() so absent server fields won't crash deserialization.
  • Membership model extension: A new userAccessedAt: String field is added to Membership; this field is privacy-gated on the server side ("Show this attribute by toggling membership privacy in the Console"), which means it may be absent from responses — the current non-nullable declaration and hard cast remain an unresolved crash risk flagged in earlier review rounds.

Confidence Score: 4/5

The PR is safe to merge for most endpoints, but Membership.kt contains an unresolved crash path where a privacy-gated field can be absent from the server response.

The header additions across all services are mechanically correct and consistent. The User email metadata fields are deserialized with safe casts and will handle absent server fields gracefully. However, Membership.userAccessedAt is declared non-nullable and deserialized with map["userAccessedAt"] as String — when membership privacy hides this field, the server omits it, map["userAccessedAt"] returns null, and the hard cast throws a ClassCastException at runtime. This was flagged in previous review rounds and has not been addressed.

library/src/main/java/io/appwrite/models/Membership.kt — the userAccessedAt field and its deserialization in from() need attention before this can be safely shipped.

Important Files Changed

Filename Overview
library/src/main/java/io/appwrite/Client.kt Added explicit X-Appwrite-Project header to the ping() method; no logic changes to request handling
library/src/main/java/io/appwrite/models/User.kt Added five new email metadata fields (emailCanonical, emailIsFree, emailIsDisposable, emailIsCorporate, emailIsCanonical); all declared as nullable and use safe-cast in from(), though they're declared as var instead of val
library/src/main/java/io/appwrite/models/Membership.kt Added new userAccessedAt field; field is declared non-nullable (String) and deserialized with a hard cast that will crash if the server omits the field when membership privacy is enabled
library/src/main/java/io/appwrite/services/Account.kt Added missing X-Appwrite-Project and accept headers consistently across all endpoints
library/src/main/java/io/appwrite/services/Databases.kt Added X-Appwrite-Project and accept headers to all endpoints; deprecated listDocuments methods point users to TablesDB.listRows
library/src/main/java/io/appwrite/services/Functions.kt Added accept header to listExecutions and getExecution; createExecution correctly uses client.call() directly with content-type application/json
library/src/main/java/io/appwrite/services/TablesDB.kt Added X-Appwrite-Project and accept headers consistently across all endpoints
library/src/main/java/io/appwrite/services/Presences.kt Added X-Appwrite-Project and accept headers to all endpoints; delete endpoint correctly omits accept header since it returns no body
library/src/main/java/io/appwrite/services/Storage.kt Added X-Appwrite-Project and accept headers to all file endpoints; header changes only
library/src/main/java/io/appwrite/services/Teams.kt Added X-Appwrite-Project and accept headers to all team and membership endpoints

Reviews (5): Last reviewed commit: "chore: update Android SDK to 25.1.0" | Re-trigger Greptile

Comment on lines +88 to +92
/**
* Most recent access date in ISO 8601 format. Show this attribute by toggling membership privacy in the Console.
*/
@SerializedName("userAccessedAt")
val userAccessedAt: String,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Declare the field as nullable and use safe casting to avoid a crash when the server omits this key.

Suggested change
/**
* Most recent access date in ISO 8601 format. Show this attribute by toggling membership privacy in the Console.
*/
@SerializedName("userAccessedAt")
val userAccessedAt: String,
/**
* Most recent access date in ISO 8601 format. Show this attribute by toggling membership privacy in the Console.
*/
@SerializedName("userAccessedAt")
val userAccessedAt: String?,

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!

joined = map["joined"] as String,
confirm = map["confirm"] as Boolean,
mfa = map["mfa"] as Boolean,
userAccessedAt = map["userAccessedAt"] as String,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Use safe cast to match the nullable type and avoid a TypeCastException when the key is absent from the response map.

Suggested change
userAccessedAt = map["userAccessedAt"] as String,
userAccessedAt = map["userAccessedAt"] as? String,

Comment on lines +94 to +108
/**
* Canonical form of the user email address.
*/
@SerializedName("emailCanonical")
var emailCanonical: String?,

/**
* Whether the user email is from a free email provider.
*/
@SerializedName("emailIsFree")
var emailIsFree: Boolean?,

/**
* Whether the user email is from a disposable email provider.
*/
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 var used for model fields that should be immutable

The five new email fields (emailCanonical, emailIsFree, emailIsDisposable, emailIsCorporate, emailIsCanonical) are declared as var while every other field in User is val. These are server-returned response values that should not be mutated after construction. The same inconsistency also appears in AppSecret.lastAccessedAt and AppSecretPlaintext.lastAccessedAt in this PR. Using var allows callers to silently overwrite deserialized state, which can lead to stale or incorrect data being observed.

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!

Comment thread library/src/main/java/io/appwrite/models/App.kt Outdated
@ChiragAgg5k ChiragAgg5k changed the title feat: SDK update for version 25.1.0 feat: Android SDK update for version 25.1.0 Jun 8, 2026
@ChiragAgg5k ChiragAgg5k changed the title feat: Android SDK update for version 25.1.0 feat: SDK update for version 25.1.0 Jun 8, 2026
@ChiragAgg5k ChiragAgg5k changed the title feat: SDK update for version 25.1.0 feat: Android SDK update for version 25.1.0 Jun 8, 2026
Comment on lines 100 to 110
val idParamName: String? = null
return client.chunkedUpload(
apiPath,
apiHeaders,
apiParams,
responseType = io.appwrite.models.Execution::class.java,
converter,
paramName,
idParamName,
onProgress,
)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P0 paramName is an unresolved reference — compilation will fail

paramName is never declared in createExecution; it exists only as a local variable in Storage.createFile (val paramName = "file"). Kotlin will reject this with an "unresolved reference" error, so the entire SDK will not build. Beyond the missing declaration, chunkedUpload immediately does params[paramName] as InputFile, but createExecution has no InputFile parameter — its payload is a body: String?. The function should continue using client.call("POST", …) as it did before this PR, with "content-type" to "application/json" restored.

@ChiragAgg5k ChiragAgg5k merged commit 77c77b1 into main Jun 8, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants