You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Google Play Games Services创建新Snapshot的技术求助及代码疑问

How to Create a New Snapshot for Google Play Games Saved Games (Updated for Current API)

Hey there! I totally get how frustrating it is when official docs are vague and sample code is outdated (5 years is an eternity in Android development!). Let's walk through exactly how to create a new Snapshot using the current Google Play Games Services API, replacing that deprecated code.

First: Replace Deprecated onActivityResult with Activity Result API

The old onActivityResult method is no longer recommended—Android now uses the Activity Result Contracts API for handling activity results. Here's how to set up the launcher for Saved Games UI:

import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import com.google.android.gms.games.SnapshotsClient;
import com.google.android.gms.games.snapshot.SnapshotMetadata;

// Initialize this in your Activity/Fragment's onCreate
private final ActivityResultLauncher<Intent> savedGamesLauncher = registerForActivityResult(
    new ActivityResultContracts.StartActivityForResult(),
    result -> {
        if (result.getResultCode() == RESULT_OK && result.getData() != null) {
            Intent intent = result.getData();
            if (intent.hasExtra(SnapshotsClient.EXTRA_SNAPSHOT_NEW)) {
                // Trigger creation of a new snapshot
                createNewSnapshot();
            } else if (intent.hasExtra(SnapshotsClient.EXTRA_SNAPSHOT_METADATA)) {
                // Load existing snapshot (updated for current API)
                SnapshotMetadata metadata = intent.getParcelableExtra(SnapshotsClient.EXTRA_SNAPSHOT_METADATA);
                mCurrentSaveName = metadata.getUniqueName();
                loadExistingSnapshot(mCurrentSaveName);
            }
        }
    }
);

Step-by-Step: Creating a New Snapshot

Now, let's fill in the createNewSnapshot() method—this is what replaces that // Create the new snapshot comment in your old code:

import com.google.android.gms.games.Games;
import com.google.android.gms.games.snapshot.Snapshot;
import com.google.android.gms.games.snapshot.SnapshotConflict;
import com.google.android.gms.games.snapshot.SnapshotMetadataChange;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigInteger;
import java.util.Date;
import java.util.Random;

private void createNewSnapshot() {
    // 1. Generate a unique name for your new snapshot (same logic as your old code)
    String uniqueSnapshotName = "snapshotTemp-" + new BigInteger(281, new Random()).toString(13);
    
    // 2. Build metadata for the snapshot (display name, description, etc.)
    SnapshotMetadataChange metadataChange = new SnapshotMetadataChange.Builder()
        .setDisplayName("My Latest Save") // Name users will see in Saved Games UI
        .setDescription("Auto-saved on " + new Date())
        // Optional: Set a cover image with .setCoverImage(bitmap)
        .build();
    
    // 3. Get the SnapshotsClient (make sure user is signed in first!)
    SnapshotsClient snapshotsClient = Games.getSnapshotsClient(
        this, 
        GoogleSignIn.getLastSignedInAccount(this)
    );
    
    // 4. Open the snapshot (create it if it doesn't exist)
    snapshotsClient.open(
        uniqueSnapshotName,
        true, // Allow creating a new snapshot if it doesn't exist
        SnapshotsClient.RESOLUTION_POLICY_MOST_RECENTLY_MODIFIED // Handle conflicts automatically (or customize)
    ).addOnSuccessListener(snapshotOrConflict -> {
        if (snapshotOrConflict.isConflict()) {
            // Optional: Handle conflicts if multiple versions exist
            resolveSnapshotConflict(snapshotOrConflict);
        } else {
            // 5. Get the snapshot instance to write your game data
            Snapshot snapshot = snapshotOrConflict.getSnapshot();
            
            // 6. Write your game state to the snapshot
            // Use try-with-resources to auto-close the output stream
            try (OutputStream outputStream = snapshot.getContents().getOutputStream()) {
                // Example: Write a JSON string of your game state
                String gameState = "{\"score\": 150, \"currentLevel\": 7, \"unlockedItems\": [\"shield\", \"double_jump\"]}";
                outputStream.write(gameState.getBytes());
            } catch (IOException e) {
                Log.e("SavedGames", "Error writing game data to snapshot", e);
                return;
            }
            
            // 7. Commit the changes and close the snapshot
            snapshotsClient.commitAndClose(snapshot, metadataChange)
                .addOnSuccessListener(voidResult -> {
                    mCurrentSaveName = uniqueSnapshotName;
                    Log.d("SavedGames", "New snapshot created successfully: " + uniqueSnapshotName);
                    // Optional: Update UI to reflect the new save
                })
                .addOnFailureListener(e -> {
                    Log.e("SavedGames", "Failed to commit snapshot", e);
                });
        }
    }).addOnFailureListener(e -> {
        Log.e("SavedGames", "Failed to open new snapshot", e);
    });
}

// Optional: Handle snapshot conflicts (e.g., if user saved on multiple devices)
private void resolveSnapshotConflict(SnapshotConflict conflict) {
    // For simplicity, we'll choose the most recently modified snapshot
    Snapshot resolvedSnapshot = conflict.getSnapshot();
    SnapshotMetadataChange metadataChange = new SnapshotMetadataChange.Builder()
        .setDisplayName(resolvedSnapshot.getMetadata().getDisplayName())
        .build();
    
    SnapshotsClient snapshotsClient = Games.getSnapshotsClient(
        this, 
        GoogleSignIn.getLastSignedInAccount(this)
    );
    
    snapshotsClient.resolveConflict(conflict.getConflictId(), resolvedSnapshot, metadataChange)
        .addOnSuccessListener(voidResult -> {
            Log.d("SavedGames", "Snapshot conflict resolved successfully");
        })
        .addOnFailureListener(e -> {
            Log.e("SavedGames", "Failed to resolve snapshot conflict", e);
        });
}

Key Notes to Remember

  • Sign-In Check: Always ensure the user is signed into Google Play Games before accessing SnapshotsClient—add a check for GoogleSignIn.getLastSignedInAccount(this) != null to avoid crashes.
  • Data Format: You can write any data format (JSON, Protobuf, binary) to the snapshot—just make sure you can read it back consistently when loading.
  • Conflict Resolution: The example uses RESOLUTION_POLICY_MOST_RECENTLY_MODIFIED to auto-resolve conflicts, but you can implement custom logic if needed (e.g., let the user choose which save to keep).
  • Permissions: Make sure your app has the com.google.android.gms.games.permission.SAVE_GAMES permission in your AndroidManifest.xml.

内容的提问来源于stack exchange,提问作者Houcine

火山引擎 最新活动