Skip to content

feat(android): support setting achievement steps - #245

Open
JoelFerrando wants to merge 2 commits into
Abedalkareem:developfrom
JoelFerrando:codex/android-achievement-set-steps
Open

feat(android): support setting achievement steps#245
JoelFerrando wants to merge 2 commits into
Abedalkareem:developfrom
JoelFerrando:codex/android-achievement-set-steps

Conversation

@JoelFerrando

@JoelFerrando JoelFerrando commented Jul 27, 2026

Copy link
Copy Markdown

Summary

  • add Achievements.setSteps and the backwards-compatible GamesServices.setSteps facade
  • carry the operation through the platform interface and Android method channel
  • call Google Play Games setStepsImmediate
  • validate a non-empty Android achievement ID and steps > 0 before crossing the channel
  • return a dedicated failed_to_set_achievement_steps native error
  • document the Android-only, monotonic semantics

Why

increment is not safe for reconciliation or retryable sync: replaying a delta can over-count progress. Google Play Games exposes setStepsImmediate specifically to set an incremental achievement to at least an absolute number of completed steps. If the stored progress is already higher, the call is a no-op.

Exposing that API lets Flutter apps perform idempotent achievement reconciliation without maintaining an app-specific Kotlin method channel. The implementation keeps the package's existing immediate/Future mutation behavior and success return contract.

This is intentionally Android-only. Calls on other platforms fail in Dart before invoking the native channel, so no GameKit behavior is changed.

API reference: https://developers.google.com/android/reference/com/google/android/gms/games/AchievementsClient#setStepsImmediate(java.lang.String,int)

Verification

  • four platform-interface tests cover the exact MethodChannel payload, blank achievement IDs, non-positive steps, and non-Android calls: all pass
  • authenticated physical V2310 / Android 15, using an isolated registered test credential:
    • starting server progress was 4/10
    • setSteps(1) returned Success and a forced reload remained 4/10, proving progress is not reduced
    • setSteps(5) returned Success and a forced reload returned 5/10, proving a real server-side mutation
    • both executions crossed Dart → MethodChannel → Kotlin → Play Games
  • the intentionally unregistered dev package returns the dedicated failed_to_set_achievement_steps code, covering the native failure path
  • dart analyze in games_services_platform_interface: clean
  • flutter analyze --no-fatal-warnings in games_services: only the existing development path dependency warning
  • Android debug APK compiles successfully through the consumer app

No Apple hardware or GameKit verification is required for this PR because the operation is Android-only and the Dart layer rejects other platforms before the native channel.

@JoelFerrando
JoelFerrando marked this pull request as ready for review July 27, 2026 19:11
@JoelFerrando

Copy link
Copy Markdown
Author

I was able to finish the missing authenticated device test. Starting from 4/10, setSteps(1) returned success and correctly stayed at 4/10; then setSteps(5) returned success and a forced reload reported 5/10. That covers both the monotonic no-op and a real server-side mutation through the full Dart → MethodChannel → Kotlin → Play Games path. Since this PR is Android-only and the remaining platform-specific evidence is complete, I have marked it ready for review.

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.

1 participant