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));
        }
Example #4
0
        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);
                }
                    );
            }
        }