Android SDK Game State Sync

The SDK can save the player's progress to Magify and restore it on another device or after a reinstall. Restoration happens automatically, and you can also save and restore manually.

Prerequisites

State sync requires isSyncStateEnabled = true and a user identity. Authorize the user with an external provider token:

magify.isSyncStateEnabled = true
magify.authorizeUser(provider = "google", token = idToken)

authorizeUser cancels pending sync operations and starts authorization once any restore file commit already in progress finishes. While it waits, saveState and restoreState return Error.

To check the identity used for sync:

val commonClientId: String? = magify.commonClientId     // null if unknown
val hasAuth: Boolean = magify.hasSocialAuthorizationData // data is stored; expiry is not validated

Automatic restore

The SDK restores state automatically when needed. Automatic restore is enabled by default and the setting is persisted across restarts.

magify.isAutoRestoreStateEnabled = false // disable
magify.isAutoRestoreStateEnabled = true  // allow future automatic restores
  • Disabling cancels an active automatic restore, including retry delays.
  • Enabling permits future triggers. It does not start a restore immediately.
  • Manual save and restore stay available in both cases.

Observing status

Read the current status or subscribe to changes. The observable emits the current status immediately.

val info: AutoRestoreStateInfo = magify.autoRestoreStateInfo

val subscription = magify.observeAutoRestoreStateInfo().subscribe { info ->
    when (info.kind) {
        AutoRestoreStateInfo.StateKind.NotStarted -> {}
        AutoRestoreStateInfo.StateKind.InProgress -> {} // includes retry delays
        AutoRestoreStateInfo.StateKind.Success -> {}
        AutoRestoreStateInfo.StateKind.NothingToRestore -> {}
        AutoRestoreStateInfo.StateKind.Failed -> Log.w("App", info.errorMessage ?: "")
        AutoRestoreStateInfo.StateKind.Cancelled -> {}
    }
}

The status is local to the current session.

Applying restored data

Subscribe to observeRestoredStateEvent() to reload your game data after a restore. It emits Success and NothingToRestore; errors and cancellations are delivered to the operation's callback.

magify.observeRestoredStateEvent()
    .filter { it.kind == SyncStateResult.ResultKind.Success }
    .subscribe {
        // Reload game data from storage.
    }

Manual save and restore

Both methods return a SyncOperation that you can cancel independently. The callback receives a SyncStateResult once, on the main thread.

var saveOperation: SyncOperation? = null
var restoreOperation: SyncOperation? = null

saveOperation = magify.saveState(weight = progressWeight) { result ->
    // handle result
}

restoreOperation = magify.restoreState(weight = progressWeight) { result ->
    // handle result
}

// Cancel when no longer needed.
saveOperation?.cancel()
restoreOperation?.cancel()

Weight

weight expresses the player's progress (for example, a combination of level and achievements). It must not be negative, otherwise IllegalArgumentException is thrown.

A manual restore without a weight takes over from an automatic restore.

Result

data class SyncStateResult(
    val kind: ResultKind,
    val weight: Int?,
    val error: Throwable? = null
)

isSuccess is true only for Success.

Next step

To learn about SDK privacy controls, see the Privacy & Consent section.

Related articles

IInAppStore

Unity SDK Releases

InfoProduct

Android SDK Releases

InternalLinkProduct

UnityPurchasing