public void ChooseMetadata(ISavedGameMetadata chosenMetadata) { AndroidSnapshotMetadata convertedMetadata = chosenMetadata as AndroidSnapshotMetadata; if (convertedMetadata != mOriginal && convertedMetadata != mUnmerged) { OurUtils.Logger.e("Caller attempted to choose a version of the metadata that was not part " + "of the conflict"); mCompleteCallback(SavedGameRequestStatus.BadInputError, null); return; } using (var task = mSnapshotsClient.Call <AndroidJavaObject>( "resolveConflict", mConflict.Call <string>("getConflictId"), convertedMetadata.JavaSnapshot)) { AndroidTaskUtils.AddOnSuccessListener <AndroidJavaObject>( task, dataOrConflict => mRetryFileOpen()); mAndroidSavedGameClient.AddOnFailureListenerWithSignOut( task, exception => { OurUtils.Logger.d("ChooseMetadata failed: " + exception.Call <string>("toString")); var status = mAndroidSavedGameClient.mAndroidClient.IsAuthenticated() ? SavedGameRequestStatus.InternalError : SavedGameRequestStatus.AuthenticationError; mCompleteCallback(status, null); } ); } }
public void ReadBinaryData(ISavedGameMetadata metadata, Action <SavedGameRequestStatus, byte[]> completedCallback) { Misc.CheckNotNull(metadata); Misc.CheckNotNull(completedCallback); completedCallback = ToOnGameThread(completedCallback); AndroidSnapshotMetadata convertedMetadata = metadata as AndroidSnapshotMetadata; if (convertedMetadata == null) { OurUtils.Logger.e("Encountered metadata that was not generated by this ISavedGameClient"); completedCallback(SavedGameRequestStatus.BadInputError, null); return; } if (!convertedMetadata.IsOpen) { OurUtils.Logger.e("This method requires an open ISavedGameMetadata."); completedCallback(SavedGameRequestStatus.BadInputError, null); return; } byte[] data = convertedMetadata.JavaContents.Call <byte[]>("readFully"); if (data == null) { completedCallback(SavedGameRequestStatus.BadInputError, null); } else { completedCallback(SavedGameRequestStatus.Success, data); } }
public void Delete(ISavedGameMetadata metadata) { AndroidSnapshotMetadata androidMetadata = metadata as AndroidSnapshotMetadata; Misc.CheckNotNull(androidMetadata); using (mSnapshotsClient.Call <AndroidJavaObject>("delete", androidMetadata.JavaMetadata)); }
public static void ShowSelectSnapshotUI(bool showCreateSaveUI, bool showDeleteSaveUI, int maxDisplayedSavedGames, string uiTitle, Action <SelectUIStatus, ISavedGameMetadata> cb) { using (var helperFragment = new AndroidJavaClass(HelperFragmentClass)) using (var task = helperFragment.CallStatic <AndroidJavaObject>("showSelectSnapshotUi", AndroidHelperFragment.GetActivity(), uiTitle, showCreateSaveUI, showDeleteSaveUI, maxDisplayedSavedGames)) { AndroidTaskUtils.AddOnSuccessListener <AndroidJavaObject>( task, result => { SelectUIStatus status = (SelectUIStatus)result.Get <int>("status"); Debug.Log("ShowSelectSnapshotUI result " + status); AndroidJavaObject javaMetadata = result.Get <AndroidJavaObject>("metadata"); AndroidSnapshotMetadata metadata = javaMetadata == null ? null : new AndroidSnapshotMetadata(javaMetadata, /* contents= */ null); cb.Invoke(status, metadata); }); AndroidTaskUtils.AddOnFailureListener( task, exception => { Debug.Log("ShowSelectSnapshotUI failed with exception"); cb.Invoke(SelectUIStatus.InternalError, null); }); } }
public void CommitUpdate(ISavedGameMetadata metadata, SavedGameMetadataUpdate updateForMetadata, byte[] updatedBinaryData, Action <SavedGameRequestStatus, ISavedGameMetadata> callback) { Misc.CheckNotNull(metadata); Misc.CheckNotNull(updatedBinaryData); Misc.CheckNotNull(callback); callback = ToOnGameThread(callback); AndroidSnapshotMetadata convertedMetadata = metadata as AndroidSnapshotMetadata; if (convertedMetadata == null) { OurUtils.Logger.e("Encountered metadata that was not generated by this ISavedGameClient"); callback(SavedGameRequestStatus.BadInputError, null); return; } if (!convertedMetadata.IsOpen) { OurUtils.Logger.e("This method requires an open ISavedGameMetadata."); callback(SavedGameRequestStatus.BadInputError, null); return; } if (!convertedMetadata.JavaContents.Call <bool>("writeBytes", updatedBinaryData)) { OurUtils.Logger.e("This method requires an open ISavedGameMetadata."); callback(SavedGameRequestStatus.BadInputError, null); } using (var convertedMetadataChange = AsMetadataChange(updateForMetadata)) using (var task = mSnapshotsClient.Call <AndroidJavaObject>("commitAndClose", convertedMetadata.JavaSnapshot, convertedMetadataChange)) { AndroidTaskUtils.AddOnSuccessListener <AndroidJavaObject>( task, /* disposeResult= */ false, snapshotMetadata => { Debug.Log("commitAndClose.succeed"); callback(SavedGameRequestStatus.Success, new AndroidSnapshotMetadata(snapshotMetadata, /* contents= */ null)); }); AddOnFailureListenerWithSignOut( task, exception => { Debug.Log("commitAndClose.failed: " + exception.Call <string>("toString")); var status = mAndroidClient.IsAuthenticated() ? SavedGameRequestStatus.InternalError : SavedGameRequestStatus.AuthenticationError; callback(status, null); }); } }
internal AndroidConflictResolver(AndroidJavaObject snapshotClient, AndroidJavaObject conflict, AndroidSnapshotMetadata original, AndroidSnapshotMetadata unmerged, Action <SavedGameRequestStatus, ISavedGameMetadata> completeCallback, Action retryOpen) { this.mSnapshotsClient = Misc.CheckNotNull(snapshotClient); this.mConflict = Misc.CheckNotNull(conflict); this.mOriginal = Misc.CheckNotNull(original); this.mUnmerged = Misc.CheckNotNull(unmerged); this.mCompleteCallback = Misc.CheckNotNull(completeCallback); this.mRetryFileOpen = Misc.CheckNotNull(retryOpen); }
public void ResolveConflict(ISavedGameMetadata chosenMetadata, SavedGameMetadataUpdate metadataUpdate, byte[] updatedData) { AndroidSnapshotMetadata convertedMetadata = chosenMetadata as AndroidSnapshotMetadata; if (convertedMetadata != mOriginal && convertedMetadata != mUnmerged) { OurUtils.Logger.e("Caller attempted to choose a version of the metadata that was not part " + "of the conflict"); mCompleteCallback(SavedGameRequestStatus.BadInputError, null); return; } using (var contentUpdate = mConflict.Call <AndroidJavaObject>("getResolutionSnapshotContents")) { if (!contentUpdate.Call <bool>("writeBytes", updatedData)) { OurUtils.Logger.e("Can't update snapshot contents during conflict resolution."); mCompleteCallback(SavedGameRequestStatus.BadInputError, null); } using (var convertedMetadataChange = AsMetadataChange(metadataUpdate)) using (var task = mSnapshotsClient.Call <AndroidJavaObject>( "resolveConflict", mConflict.Call <string>("getConflictId"), convertedMetadata.JavaMetadata.Call <string>("getSnapshotId"), convertedMetadataChange, contentUpdate)) { AndroidTaskUtils.AddOnSuccessListener <AndroidJavaObject>( task, dataOrConflict => mRetryFileOpen()); mAndroidSavedGameClient.AddOnFailureListenerWithSignOut( task, exception => { OurUtils.Logger.d("ResolveConflict failed: " + exception.Call <string>("toString")); var status = mAndroidSavedGameClient.mAndroidClient.IsAuthenticated() ? SavedGameRequestStatus.InternalError : SavedGameRequestStatus.AuthenticationError; mCompleteCallback(status, null); } ); } } }
private void InternalOpen(string filename, DataSource source, ConflictResolutionStrategy resolutionStrategy, bool prefetchDataOnConflict, ConflictCallback conflictCallback, Action <SavedGameRequestStatus, ISavedGameMetadata> completedCallback) { int conflictPolicy; // SnapshotsClient.java#RetentionPolicy switch (resolutionStrategy) { case ConflictResolutionStrategy.UseLastKnownGood: conflictPolicy = 2 /* RESOLUTION_POLICY_LAST_KNOWN_GOOD */; break; case ConflictResolutionStrategy.UseMostRecentlySaved: conflictPolicy = 3 /* RESOLUTION_POLICY_MOST_RECENTLY_MODIFIED */; break; case ConflictResolutionStrategy.UseLongestPlaytime: conflictPolicy = 1 /* RESOLUTION_POLICY_LONGEST_PLAYTIME*/; break; case ConflictResolutionStrategy.UseManual: conflictPolicy = -1 /* RESOLUTION_POLICY_MANUAL */; break; default: conflictPolicy = 3 /* RESOLUTION_POLICY_MOST_RECENTLY_MODIFIED */; break; } using (var task = mSnapshotsClient.Call <AndroidJavaObject>("open", filename, /* createIfNotFound= */ true, conflictPolicy)) { AndroidTaskUtils.AddOnSuccessListener <AndroidJavaObject>( task, dataOrConflict => { if (dataOrConflict.Call <bool>("isConflict")) { var conflict = dataOrConflict.Call <AndroidJavaObject>("getConflict"); AndroidSnapshotMetadata original = new AndroidSnapshotMetadata(conflict.Call <AndroidJavaObject>("getSnapshot")); AndroidSnapshotMetadata unmerged = new AndroidSnapshotMetadata( conflict.Call <AndroidJavaObject>("getConflictingSnapshot")); // Instantiate the conflict resolver. Note that the retry callback closes over // all the parameters we need to retry the open attempt. Once the conflict is // resolved by invoking the appropriate resolution method on // AndroidConflictResolver, the resolver will invoke this callback, which will // result in this method being re-executed. This recursion will continue until // all conflicts are resolved or an error occurs. AndroidConflictResolver resolver = new AndroidConflictResolver( this, mSnapshotsClient, conflict, original, unmerged, completedCallback, () => InternalOpen(filename, source, resolutionStrategy, prefetchDataOnConflict, conflictCallback, completedCallback)); var originalBytes = original.JavaContents.Call <byte[]>("readFully"); var unmergedBytes = unmerged.JavaContents.Call <byte[]>("readFully"); conflictCallback(resolver, original, originalBytes, unmerged, unmergedBytes); } else { using (var snapshot = dataOrConflict.Call <AndroidJavaObject>("getData")) { AndroidJavaObject metadata = snapshot.Call <AndroidJavaObject>("freeze"); completedCallback(SavedGameRequestStatus.Success, new AndroidSnapshotMetadata(metadata)); } } }); AddOnFailureListenerWithSignOut( task, exception => { OurUtils.Logger.d("InternalOpen has failed: " + exception.Call <string>("toString")); var status = mAndroidClient.IsAuthenticated() ? SavedGameRequestStatus.InternalError : SavedGameRequestStatus.AuthenticationError; completedCallback(status, null); } ); } }