A client to interact with Snapshots.
Nested Class Summary
class | SnapshotsClient.DataOrConflict<T> | Represents the result of attempting to open a snapshot or resolve a conflict from a previous attempt. | |
@interface | SnapshotsClient.ResolutionPolicy | Conflict resolution policy. | |
class | SnapshotsClient.SnapshotConflict | Result delivered when a conflict was detected
during
SnapshotsClient.open(SnapshotMetadata) or
SnapshotsClient.resolveConflict(String, Snapshot) . |
|
class | SnapshotsClient.SnapshotContentUnavailableApiException | Indicates that the snapshot contents are
unavailable at the moment, but the SnapshotMetadata is available through
getSnapshotMetadata() . |
Constant Summary
int | DISPLAY_LIMIT_NONE | Constant passed to
getSelectSnapshotIntent(String, boolean, boolean, int) indicating that the
UI should not cap the number of displayed snapshots. |
String | EXTRA_SNAPSHOT_METADATA | Intent extra used to pass a SnapshotMetadata . |
String | EXTRA_SNAPSHOT_NEW | Intent extra used to indicate the user wants to create a new snapshot. |
int | RESOLUTION_POLICY_HIGHEST_PROGRESS | In the case of a conflict, the snapshot with the highest progress value will be used. |
int | RESOLUTION_POLICY_LAST_KNOWN_GOOD | In the case of a conflict, the last known good version of this snapshot will be used. |
int | RESOLUTION_POLICY_LONGEST_PLAYTIME | In the case of a conflict, the snapshot with the longest played time will be used. |
int | RESOLUTION_POLICY_MANUAL | In the case of a conflict, the result will be returned to the app for resolution. |
int | RESOLUTION_POLICY_MOST_RECENTLY_MODIFIED | In the case of a conflict, the most recently modified version of this snapshot will be used. |
Public Method Summary
abstract Task<SnapshotMetadata> |
commitAndClose(Snapshot
snapshot,
SnapshotMetadataChange metadataChange)
Returns a
Task
which asynchronously commits any modifications in
SnapshotMetadataChange made to the Snapshot
and loads a
SnapshotMetadata .
|
abstract Task<String> |
delete(SnapshotMetadata
metadata)
Returns a
Task
which asynchronously deletes the specified by
SnapshotMetadata snapshot and loads the deleted snapshot ID.
|
abstract Task<Void> |
discardAndClose(Snapshot
snapshot)
|
abstract Task<Integer> |
getMaxCoverImageSize()
Returns a
Task
which asynchronously loads the maximum data size per snapshot cover image in
bytes.
|
abstract Task<Integer> |
getMaxDataSize()
Returns a
Task
which asynchronously loads the maximum data size per snapshot in bytes.
|
abstract Task<Intent> |
getSelectSnapshotIntent(String title,
boolean allowAddButton, boolean allowDelete, int maxSnapshots)
|
static SnapshotMetadata |
getSnapshotFromBundle(Bundle extras)
|
abstract Task<AnnotatedData<SnapshotMetadataBuffer>> |
load(boolean forceReload)
Returns a
Task
which asynchronously loads an annotated
SnapshotMetadataBuffer that represents the snapshot data for the
currently signed-in player.
|
abstract Task<DataOrConflict<Snapshot>> |
open(SnapshotMetadata
metadata)
Returns a
Task
which asynchronously opens a snapshot with the given
SnapshotMetadata (usually returned from
load(boolean) .
|
abstract Task<DataOrConflict<Snapshot>> |
open(SnapshotMetadata
metadata, int conflictPolicy)
Returns a
Task
which asynchronously opens a snapshot with the given
SnapshotMetadata (usually returned from
load(boolean) .
|
abstract Task<DataOrConflict<Snapshot>> | |
abstract Task<DataOrConflict<Snapshot>> | |
abstract Task<DataOrConflict<Snapshot>> |
resolveConflict(String conflictId,
String
snapshotId,
SnapshotMetadataChange metadataChange, SnapshotContents
snapshotContents)
Returns a
Task
which asynchronously resolves a conflict using the provided data.
|
abstract Task<DataOrConflict<Snapshot>> |
Constants
public static final int DISPLAY_LIMIT_NONE
Constant passed to
getSelectSnapshotIntent(String, boolean, boolean, int)
indicating that the
UI should not cap the number of displayed snapshots.
public static final String EXTRA_SNAPSHOT_METADATA
Intent extra used to pass a SnapshotMetadata
.
public static final String EXTRA_SNAPSHOT_NEW
Intent extra used to indicate the user wants to create a new snapshot.
public static final int RESOLUTION_POLICY_HIGHEST_PROGRESS
In the case of a conflict, the snapshot with the highest progress value will be used. In the case of a tie, the last known good snapshot will be chosen instead.
This policy is a good choice if your game uses the progress value of the snapshot to
determine the best saved game. Note that you must use
SnapshotMetadataChange.Builder.setProgressValue(long)
when saving games for
this policy to be meaningful.
public static final int RESOLUTION_POLICY_LAST_KNOWN_GOOD
In the case of a conflict, the last known good version of this snapshot will be
used. This corresponds to the data that would be returned from
SnapshotsClient.SnapshotConflict.getSnapshot()
in a custom merge.
This policy is a reasonable choice if your game requires stability from the snapshot data. This policy ensures that only writes which are not contested are seen by the player, which guarantees that all clients converge.
public static final int RESOLUTION_POLICY_LONGEST_PLAYTIME
In the case of a conflict, the snapshot with the longest played time will be used. In the case of a tie, the last known good snapshot will be chosen instead.
This policy is a good choice if the length of play time is a reasonable proxy for
the "best" save game. Note that you must use
SnapshotMetadataChange.Builder.setPlayedTimeMillis(long)
when saving games
for this policy to be meaningful.
public static final int RESOLUTION_POLICY_MANUAL
In the case of a conflict, the result will be returned to the app for resolution. No automatic resolution will be performed.
This policy ensures that no user changes to the state of the save game will ever be lost.
public static final int RESOLUTION_POLICY_MOST_RECENTLY_MODIFIED
In the case of a conflict, the most recently modified version of this snapshot will
be used. This corresponds to the data that would be returned from
SnapshotsClient.SnapshotConflict.getConflictingSnapshot()
in a custom
merge.
This policy is a reasonable choice if your game can tolerate players on multiple devices clobbering their own changes. Because this policy blindly chooses the most recent data, it is possible that a player's changes may get lost.
Public Methods
public abstract Task<SnapshotMetadata> commitAndClose (Snapshot snapshot, SnapshotMetadataChange metadataChange)
Returns a Task
which
asynchronously commits any modifications in SnapshotMetadataChange
made to the Snapshot
and loads a SnapshotMetadata
.
The Task
returned by this method is complete once the changes are synced
locally and the background sync request for this data has been requested.
This method fails a Task
with an exception when called with a snapshot
that was not opened or has already been committed/discarded.
Note that the total size of the contents of snapshot
may not exceed the
size provided by
getMaxDataSize()
.
Parameters
snapshot | The snapshot to commit the data for. |
---|---|
metadataChange | The set of changes to apply to the metadata for the snapshot. Use
SnapshotMetadataChange.EMPTY_CHANGE to preserve the existing
metadata. |
public abstract Task<String> delete (SnapshotMetadata metadata)
Returns a Task
which
asynchronously deletes the specified by SnapshotMetadata
snapshot and loads the deleted snapshot ID. This will delete the data of the snapshot
locally and on the server.
Parameters
metadata | The metadata of the snapshot to delete. |
---|
public abstract Task<Void> discardAndClose (Snapshot snapshot)
Returns a Task
which
asynchronously discards the contents of the Snapshot
and closes it. This will discard all changes made to the file, and close the snapshot
to future changes until it is re-opened. The file will not be modified on the
server.
This method fails a Task
with an exception when called with a snapshot
that was not opened or has already been committed/discarded.
Parameters
snapshot | The snapshot to discard the data for. |
---|
public abstract Task<Integer> getMaxCoverImageSize ()
Returns a Task
which
asynchronously loads the maximum data size per snapshot cover image in bytes.
Guaranteed to be at least 800 KB. May increase in the future.
The returned Task
can fail with a RemoteException
.
public abstract Task<Integer> getMaxDataSize ()
Returns a Task
which
asynchronously loads the maximum data size per snapshot in bytes. Guaranteed to be at
least 3 MB. May increase in the future.
The returned Task
can fail with a RemoteException
.
public abstract Task<Intent> getSelectSnapshotIntent (String title, boolean allowAddButton, boolean allowDelete, int maxSnapshots)
Returns a Task
which
asynchronously loads an Intent
that
will let the user select a snapshot. Note that the Intent
returned from
the Task
must be invoked with
Activity.startActivityForResult(Intent, int)
, so that the identity of the
calling package can be established.
The returned Task
can fail with a RemoteException
.
If the user canceled without selecting a snapshot, the result will be Activity.RESULT_CANCELED
.
If the user selected a snapshot from the list, the result will be Activity.RESULT_OK
and the data intent will contain the selected Snapshot as a parcelable object in
EXTRA_SNAPSHOT_METADATA
. If the user pressed the add button, the result will
be Activity.RESULT_OK
and the data intent will contain a true
boolean value in
EXTRA_SNAPSHOT_NEW
.
Note that if you have modified an open snapshot, the changes will not appear in this
UI until you call
commitAndClose(Snapshot, SnapshotMetadataChange)
on the snapshot.
Parameters
title | The title to display in the action bar of the returned Activity. |
---|---|
allowAddButton | Whether or not to display a "create new snapshot" option in the selection UI. |
allowDelete | Whether or not to provide a delete overflow menu option for each snapshot in the selection UI. |
maxSnapshots | The maximum number of snapshots to display in the UI. Use
DISPLAY_LIMIT_NONE to display all snapshots. |
public static SnapshotMetadata getSnapshotFromBundle (Bundle extras)
public abstract Task<AnnotatedData<SnapshotMetadataBuffer>> load (boolean forceReload)
Returns a Task
which
asynchronously loads an annotated SnapshotMetadataBuffer
that represents the snapshot data for the currently signed-in player.
AbstractDataBuffer.release()
should be called to release resources after
usage.
Parameters
forceReload | If true , this call will clear any locally cached data and attempt
to fetch the latest data from the server. This would commonly be used for something
like a user-initiated refresh. Normally, this should be set to false
to gain advantages of data caching. |
---|
public abstract Task<DataOrConflict<Snapshot>> open (SnapshotMetadata metadata)
Returns a Task
which
asynchronously opens a snapshot with the given SnapshotMetadata
(usually returned from load(boolean)
.
To succeed, the snapshot must exist; i.e. this call will fail if the snapshot was
deleted between the load and open calls.
This will open the snapshot using
RESOLUTION_POLICY_MANUAL
as a conflict policy. If a conflict occurred, the
result's
SnapshotsClient.DataOrConflict.isConflict()
will return true
,
and the conflict will need to be resolved using
resolveConflict(String, Snapshot)
to continue with opening the snapshot.
If the snapshot's contents are unavailable, the Task
will fail with
SnapshotsClient.SnapshotContentUnavailableApiException
.
Parameters
metadata | The metadata of the existing snapshot to load. |
---|
public abstract Task<DataOrConflict<Snapshot>> open (SnapshotMetadata metadata, int conflictPolicy)
Returns a Task
which
asynchronously opens a snapshot with the given SnapshotMetadata
(usually returned from load(boolean)
.
To succeed, the snapshot must exist; i.e. this call will fail if the snapshot was
deleted between the load and open calls.
If a conflict occurred, the result's
SnapshotsClient.DataOrConflict.isConflict()
will return true
,
and the conflict will need to be resolved using
resolveConflict(String, Snapshot)
to continue with opening the snapshot.
If the snapshot's contents are unavailable, the Task
will fail with
SnapshotsClient.SnapshotContentUnavailableApiException
.
Parameters
metadata | The metadata of the existing snapshot to load. |
---|---|
conflictPolicy | The conflict resolution policy to use for this snapshot. |
public abstract Task<DataOrConflict<Snapshot>> open (String fileName, boolean createIfNotFound, int conflictPolicy)
Returns a Task
which
asynchronously opens a snapshot with the given fileName
. If
createIfNotFound
is set to true
, the specified snapshot will
be created if it does not already exist.
If a conflict occurred, the result's
SnapshotsClient.DataOrConflict.isConflict()
will return true
,
and the conflict will need to be resolved using
resolveConflict(String, Snapshot)
to continue with opening the snapshot.
If the snapshot's contents are unavailable, the Task
will fail with
SnapshotsClient.SnapshotContentUnavailableApiException
.
Parameters
fileName | The name of the snapshot file to open. Must be between 1 and 100 non-URL-reserved characters (a-z, A-Z, 0-9, or the symbols "-", ".", "_", or "~"). |
---|---|
createIfNotFound | If true , the snapshot will be created if one cannot be found. |
conflictPolicy | The conflict resolution policy to use for this snapshot. |
public abstract Task<DataOrConflict<Snapshot>> open (String fileName, boolean createIfNotFound)
Returns a Task
which
asynchronously opens a snapshot with the given fileName
. If
createIfNotFound
is set to true
, the specified snapshot will
be created if it does not already exist.
This will open the snapshot using
RESOLUTION_POLICY_MANUAL
as a conflict policy. If a conflict occurred, the
result's
SnapshotsClient.DataOrConflict.isConflict()
will return true
,
and the conflict will need to be resolved using
resolveConflict(String, Snapshot)
to continue with opening the snapshot.
If the snapshot's contents are unavailable, the Task
will fail with
SnapshotsClient.SnapshotContentUnavailableApiException
.
Parameters
fileName | The name of the snapshot file to open. Must be between 1 and 100 non-URL-reserved characters (a-z, A-Z, 0-9, or the symbols "-", ".", "_", or "~"). |
---|---|
createIfNotFound | If true , the snapshot will be created if one cannot be found. |
public abstract Task<DataOrConflict<Snapshot>> resolveConflict (String conflictId, String snapshotId, SnapshotMetadataChange metadataChange, SnapshotContents snapshotContents)
Returns a Task
which
asynchronously resolves a conflict using the provided data. This will replace the data
on the server with the specified SnapshotMetadataChange
and SnapshotContents
.
Note that it is possible for this operation to result in a conflict itself, in which
case resolution should be repeated.
Values which are not included in the metadata change will be resolved to the version currently on the server.
If a conflict occurred, the result's
SnapshotsClient.DataOrConflict.isConflict()
will return true
,
and the conflict will need to be resolved again using
resolveConflict(String, Snapshot)
to continue with opening the snapshot.
Note that the total size of contents
may not exceed the size provided
by
getMaxDataSize()
.
Calling this method with a snapshot that has already been committed or that was not
opened via
open(SnapshotMetadata)
will throw an exception.
If the resolved snapshot's contents are unavailable, the Task
will fail
with
SnapshotsClient.SnapshotContentUnavailableApiException
.
Parameters
conflictId | The ID of the conflict to resolve. Must come from
SnapshotsClient.SnapshotConflict.getConflictId() . |
---|---|
snapshotId | The ID of the snapshot to resolve the conflict for. |
metadataChange | The set of changes to apply to the metadata for the snapshot. |
snapshotContents | The SnapshotContents
to replace the snapshot data with. |
public abstract Task<DataOrConflict<Snapshot>> resolveConflict (String conflictId, Snapshot snapshot)
Returns a Task
which
asynchronously resolves a conflict using the data from the provided Snapshot
.
This will replace the data on the server with the specified Snapshot
. Note
that it is possible for this operation to result in a conflict itself, in which case
resolution should be repeated.
If a conflict occurred, the result's
SnapshotsClient.DataOrConflict.isConflict()
will return true
,
and the conflict will need to be resolved again using
resolveConflict(String, Snapshot)
to continue with opening the snapshot.
Note that the total size of the contents of snapshot
may not exceed the
size provided by
getMaxDataSize()
.
This method fails a Task
with an exception when called with a snapshot
that was not opened or has already been committed/discarded.
If the resolved snapshot's contents are unavailable, the Task
will fail
with
SnapshotsClient.SnapshotContentUnavailableApiException
.
Parameters
conflictId | The ID of the conflict to resolve. Must come from
SnapshotsClient.SnapshotConflict.getConflictId() . |
---|---|
snapshot | The snapshot to use to resolve the conflict. |