คู่มือนี้จะแสดงวิธีใช้เกมเกมที่บันทึกไว้โดยใช้
Snapshot API จากบริการเกมของ Google Play API จะอยู่ใน
com.google.android.gms.games.snapshot
และแพ็กเกจ com.google.android.gms.games
แพ็กเกจ
ก่อนเริ่มต้น
ซึ่งหากคุณยังไม่ได้อ่าน อาจเป็นประโยชน์ในการตรวจสอบ แนวคิดเกมที่บันทึกไว้
- ตรวจสอบว่าได้เปิดใช้การรองรับเกมที่บันทึกไว้แล้ว สำหรับเกมของคุณใน Google Play Console แล้ว
- ดาวน์โหลดและตรวจสอบตัวอย่างโค้ดเกมที่บันทึกไว้ใน หน้าตัวอย่างสำหรับ Android
- ทําความคุ้นเคยกับคําแนะนําที่อธิบายไว้ใน รายการตรวจสอบคุณภาพ
การรับไคลเอ็นต์สแนปชอต
ในการเริ่มใช้ Snapshot API เกมของคุณจะต้องรับ
SnapshotsClient
โดยการเรียกใช้
Games.getSnapshotsClient()
และการส่งใน
กิจกรรมและ GoogleSignInAccount
สำหรับโปรแกรมเล่นปัจจุบัน ดูวิธีการ
เรียกดูข้อมูลบัญชีของผู้เล่น โปรดดู
ลงชื่อเข้าใช้ใน Android Games
การระบุขอบเขตไดรฟ์
Snapshot API อาศัย Google Drive API สำหรับพื้นที่เก็บข้อมูลเกมที่บันทึกไว้ ถึง
เข้าถึง Drive API แอปของคุณต้องระบุ
Drive.SCOPE_APPFOLDER
เมื่อสร้างไคลเอ็นต์ Google Sign-In
ตัวอย่างวิธีดำเนินการใน
onResume()
สำหรับกิจกรรมการลงชื่อเข้าใช้
private GoogleSignInClient mGoogleSignInClient; @Override protected void onResume() { super.onResume(); signInSilently(); } private void signInSilently() { GoogleSignInOptions signInOption = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN) // Add the APPFOLDER scope for Snapshot support. .requestScopes(Drive.SCOPE_APPFOLDER) .build(); GoogleSignInClient signInClient = GoogleSignIn.getClient(this, signInOption); signInClient.silentSignIn().addOnCompleteListener(this, new OnCompleteListener<GoogleSignInAccount>() { @Override public void onComplete(@NonNull Task<GoogleSignInAccount> task) { if (task.isSuccessful()) { onConnected(task.getResult()); } else { // Player will need to sign-in explicitly using via UI } } }); }
กำลังแสดงเกมที่บันทึกไว้
คุณสามารถผสานรวม Snapshot API ได้ทุกที่ที่เกมของคุณมอบให้ผู้เล่น ตัวเลือกในการบันทึกหรือคืนค่าความคืบหน้า เกมของคุณอาจแสดง ที่จุดบันทึก/กู้คืนที่กำหนดไว้ หรือให้ผู้เล่นบันทึกหรือคืนค่าได้ ความคืบหน้าได้ตลอดเวลา
เมื่อผู้เล่นเลือกตัวเลือกบันทึก/คืนค่าในเกมแล้ว เกมของคุณสามารถ เลือกเปิดหน้าจอที่แจ้งให้ผู้เล่นป้อนข้อมูล หรือเลือกเกมที่บันทึกไว้ที่มีอยู่แล้วเพื่อคืนค่า
Snapshot API จะระบุผู้ใช้สำหรับเลือกเกมที่บันทึกไว้ตามค่าเริ่มต้นเพื่อให้การพัฒนาของคุณง่ายขึ้น อินเทอร์เฟซ (UI) แบบพร้อมใช้งานได้ทันที UI การเลือกเกมที่บันทึกไว้ช่วยให้ผู้เล่น สร้างเกมใหม่ที่บันทึกไว้ ดูรายละเอียดเกี่ยวกับเกมที่บันทึกไว้ที่มีอยู่ และโหลดเกมที่บันทึกไว้ก่อนหน้านี้
หากต้องการเปิดใช้งาน UI เริ่มต้นของ "เกมที่บันทึกไว้" ให้ทำดังนี้
- โทรติดต่อ
SnapshotsClient.getSelectSnapshotIntent()
เพื่อรับIntent
สำหรับการเปิดใช้ค่าเริ่มต้น UI การเลือกเกมที่บันทึกไว้ - โทร
startActivityForResult()
แล้วส่งIntent
นั้น หากการเรียกใช้สำเร็จ เกมจะแสดง UI การเลือกเกมที่บันทึกไว้พร้อมกับ ตามตัวเลือกที่คุณระบุไว้
ตัวอย่างวิธีเปิด UI การเลือกเกมที่บันทึกไว้ตามค่าเริ่มต้นมีดังนี้
private static final int RC_SAVED_GAMES = 9009; private void showSavedGamesUI() { SnapshotsClient snapshotsClient = Games.getSnapshotsClient(this, GoogleSignIn.getLastSignedInAccount(this)); int maxNumberOfSavedGamesToShow = 5; Task<Intent> intentTask = snapshotsClient.getSelectSnapshotIntent( "See My Saves", true, true, maxNumberOfSavedGamesToShow); intentTask.addOnSuccessListener(new OnSuccessListener<Intent>() { @Override public void onSuccess(Intent intent) { startActivityForResult(intent, RC_SAVED_GAMES); } }); }
หากผู้เล่นเลือกที่จะสร้างเกมใหม่ที่บันทึกไว้หรือโหลดเกมที่บันทึกไว้ที่มีอยู่
UI ส่งคำขอไปยังบริการเกมของ Google Play หากคำขอประสบความสำเร็จ
บริการเกมของ Google Play ส่งคืนข้อมูลเพื่อสร้างหรือกู้คืนเกมที่บันทึกไว้ผ่าน
onActivityResult()
Callback เกมของคุณจะลบล้าง Callback นี้เพื่อตรวจสอบว่าเกิดข้อผิดพลาดระหว่างคำขอหรือไม่
ข้อมูลโค้ดต่อไปนี้แสดงตัวอย่างการใช้งาน
onActivityResult()
:
private String mCurrentSaveName = "snapshotTemp"; /** * This callback will be triggered after you call startActivityForResult from the * showSavedGamesUI method. */ @Override protected void onActivityResult(int requestCode, int resultCode, Intent intent) { if (intent != null) { if (intent.hasExtra(SnapshotsClient.EXTRA_SNAPSHOT_METADATA)) { // Load a snapshot. SnapshotMetadata snapshotMetadata = intent.getParcelableExtra(SnapshotsClient.EXTRA_SNAPSHOT_METADATA); mCurrentSaveName = snapshotMetadata.getUniqueName(); // Load the game data from the Snapshot // ... } else if (intent.hasExtra(SnapshotsClient.EXTRA_SNAPSHOT_NEW)) { // Create a new snapshot named with a unique string String unique = new BigInteger(281, new Random()).toString(13); mCurrentSaveName = "snapshotTemp-" + unique; // Create the new snapshot // ... } } }
การเขียนเกมที่บันทึกไว้
วิธีจัดเก็บเนื้อหาไปยังเกมที่บันทึกไว้
- เปิดสแนปชอตผ่าน
SnapshotsClient.open()
แบบไม่พร้อมกัน จากนั้น เรียกออบเจ็กต์Snapshot
จากผลลัพธ์ของงานโดยเรียกใช้SnapshotsClient.DataOrConflict.getData()
- ดึงข้อมูลอินสแตนซ์
SnapshotContents
ผ่านSnapshotsClient.SnapshotConflict
- เรียกใช้
SnapshotContents.writeBytes()
เพื่อจัดเก็บข้อมูลโปรแกรมเล่นในรูปแบบไบต์ - เมื่อเขียนการเปลี่ยนแปลงทั้งหมดแล้ว ให้เรียก
SnapshotsClient.commitAndClose()
เพื่อส่งการเปลี่ยนแปลงไปยังเซิร์ฟเวอร์ของ Google ในการเรียกใช้เมธอด เกมของคุณเลือกที่จะให้ข้อมูลเพิ่มเติมเพื่อบอกบริการเกมของ Google Play ได้ นำเสนอเกมที่บันทึกไว้นี้แก่ผู้เล่น ข้อมูลนี้จะแสดงในSnapshotMetaDataChange
ซึ่งเกมของคุณสร้างโดยใช้SnapshotMetadataChange.Builder
ตัวอย่างต่อไปนี้แสดงวิธีที่เกมของคุณอาจทำการเปลี่ยนแปลงกับเกมที่บันทึกไว้
private Task<SnapshotMetadata> writeSnapshot(Snapshot snapshot, byte[] data, Bitmap coverImage, String desc) { // Set the data payload for the snapshot snapshot.getSnapshotContents().writeBytes(data); // Create the change operation SnapshotMetadataChange metadataChange = new SnapshotMetadataChange.Builder() .setCoverImage(coverImage) .setDescription(desc) .build(); SnapshotsClient snapshotsClient = Games.getSnapshotsClient(this, GoogleSignIn.getLastSignedInAccount(this)); // Commit the operation return snapshotsClient.commitAndClose(snapshot, metadataChange); }
หากอุปกรณ์ของโปรแกรมเล่นไม่ได้เชื่อมต่อกับเครือข่ายเมื่อแอปเรียกใช้
SnapshotsClient.commitAndClose()
บริการเกมของ Google Play จะจัดเก็บข้อมูลเกมที่บันทึกไว้ในเครื่อง
อุปกรณ์ เมื่อเชื่อมต่ออุปกรณ์อีกครั้ง บริการเกมของ Google Play จะซิงค์เกมที่บันทึกไว้ในเครื่องและจัดเก็บไว้ในเครื่อง
เปลี่ยนแปลงไปยังเซิร์ฟเวอร์ของ Google
กำลังโหลดเกมที่บันทึกไว้
หากต้องการเรียกดูเกมที่บันทึกไว้สำหรับโปรแกรมเล่นที่ลงชื่อเข้าใช้ในปัจจุบัน ให้ทำดังนี้
- เปิดสแนปชอตผ่าน
SnapshotsClient.open()
แบบไม่พร้อมกัน จากนั้น เรียกออบเจ็กต์Snapshot
จากผลลัพธ์ของงานโดยเรียกใช้SnapshotsClient.DataOrConflict.getData()
อีกวิธีหนึ่งคือ เกมยังสามารถเรียกภาพรวมที่เฉพาะเจาะจงผ่าน UI การเลือกเกมที่บันทึกไว้ ดังที่อธิบายไว้ใน การแสดงเกมที่บันทึกไว้ - ดึงข้อมูลอินสแตนซ์
SnapshotContents
ผ่านSnapshotsClient.SnapshotConflict
- เรียกใช้
SnapshotContents.readFully()
เพื่ออ่านเนื้อหาของสแนปชอต
ตัวอย่างต่อไปนี้แสดงวิธีโหลดเกมบางเกมที่บันทึกไว้
Task<byte[]> loadSnapshot() { // Display a progress dialog // ... // Get the SnapshotsClient from the signed in account. SnapshotsClient snapshotsClient = Games.getSnapshotsClient(this, GoogleSignIn.getLastSignedInAccount(this)); // In the case of a conflict, the most recently modified version of this snapshot will be used. int conflictResolutionPolicy = SnapshotsClient.RESOLUTION_POLICY_MOST_RECENTLY_MODIFIED; // Open the saved game using its name. return snapshotsClient.open(mCurrentSaveName, true, conflictResolutionPolicy) .addOnFailureListener(new OnFailureListener() { @Override public void onFailure(@NonNull Exception e) { Log.e(TAG, "Error while opening Snapshot.", e); } }).continueWith(new Continuation<SnapshotsClient.DataOrConflict<Snapshot>, byte[]>() { @Override public byte[] then(@NonNull Task<SnapshotsClient.DataOrConflict<Snapshot>> task) throws Exception { Snapshot snapshot = task.getResult().getData(); // Opening the snapshot was a success and any conflicts have been resolved. try { // Extract the raw data from the snapshot. return snapshot.getSnapshotContents().readFully(); } catch (IOException e) { Log.e(TAG, "Error while reading Snapshot.", e); } return null; } }).addOnCompleteListener(new OnCompleteListener<byte[]>() { @Override public void onComplete(@NonNull Task<byte[]> task) { // Dismiss progress dialog and reflect the changes in the UI when complete. // ... } }); }
การจัดการความขัดแย้งของเกมที่บันทึกไว้
เมื่อใช้ API สแนปชอตในเกม อาจมี เพื่ออ่านและเขียนในเกมเดียวกันที่บันทึกไว้ ในกรณีที่ อุปกรณ์ขาดการเชื่อมต่อเครือข่ายชั่วคราวและมีการเชื่อมต่ออีกครั้งในภายหลัง ก่อให้เกิดความขัดแย้งของข้อมูลซึ่งเกมที่บันทึกไว้ซึ่งจัดเก็บไว้ในอุปกรณ์ภายในของผู้เล่น ไม่ซิงค์กับเวอร์ชันระยะไกลที่จัดเก็บไว้ในเซิร์ฟเวอร์ของ Google
Snapshot API มีกลไกการแก้ไขข้อขัดแย้งที่แสดงทั้ง ชุดเกมที่บันทึกไว้ที่ขัดแย้งกันในเวลาที่อ่าน และช่วยให้คุณแก้ไขปัญหา กลยุทธ์ที่เหมาะกับเกมของคุณ
เมื่อบริการเกมของ Google Play ตรวจพบความขัดแย้งของข้อมูล
เมธอด SnapshotsClient.DataOrConflict.isConflict()
จะแสดงผลค่า true
ในเหตุการณ์นี้
ชั้นเรียน SnapshotsClient.SnapshotConflict
มีเกมที่บันทึกไว้ 2 เวอร์ชัน ได้แก่
- เวอร์ชันของเซิร์ฟเวอร์: เวอร์ชันล่าสุดที่บริการเกมของ Google Play ทราบว่ามีความแม่นยำ สำหรับอุปกรณ์ของโปรแกรมเล่น และ
- เวอร์ชันในเครื่อง: เวอร์ชันที่แก้ไขแล้วซึ่งตรวจพบในอุปกรณ์ของโปรแกรมเล่นหนึ่งที่มี เนื้อหาหรือข้อมูลเมตาที่ขัดแย้งกัน ซึ่งอาจไม่ใช่เวอร์ชันที่คุณพยายามบันทึก
เกมของคุณต้องตัดสินใจว่าจะแก้ไขความขัดแย้งอย่างไรด้วยการเลือกหนึ่งใน เวอร์ชันที่มีให้ หรือรวมข้อมูลของเกมเวอร์ชันที่บันทึกไว้ 2 เวอร์ชัน
วิธีตรวจหาและแก้ไขความขัดแย้งของเกมที่บันทึกไว้
- โทร
SnapshotsClient.open()
ผลลัพธ์ของงานมีคลาสSnapshotsClient.DataOrConflict
- เรียกใช้เมธอด
SnapshotsClient.DataOrConflict.isConflict()
หากผลลัพธ์เป็น "จริง" คุณมี ความขัดแย้งที่ต้องแก้ไข - โทรหา
SnapshotsClient.DataOrConflict.getConflict()
เพื่อเรียกข้อมูลSnaphotsClient.snapshotConflict
อินสแตนซ์ - เรียกใช้
SnapshotsClient.SnapshotConflict.getConflictId()
เพื่อเรียกข้อมูลรหัสความขัดแย้งที่ไม่ซ้ำกัน ระบุความขัดแย้งที่ตรวจพบ เกมของคุณต้องใช้ค่านี้เพื่อส่งคำขอแก้ไขข้อขัดแย้ง ในภายหลัง - โทรติดต่อ
SnapshotsClient.SnapshotConflict.getConflictingSnapshot()
เพื่อขอรับเวอร์ชันในเครื่อง - เรียกใช้
SnapshotsClient.SnapshotConflict.getSnapshot()
เพื่อรับเวอร์ชันของเซิร์ฟเวอร์ - หากต้องการแก้ไขความขัดแย้งของเกมที่บันทึกไว้ ให้เลือกเวอร์ชันที่คุณต้องการบันทึกไปยังเซิร์ฟเวอร์เป็น
เวอร์ชันสุดท้าย และส่งไปยังเมธอด
SnapshotsClient.resolveConflict()
ตัวอย่างต่อไปนี้แสดงและตัวอย่างวิธีที่เกมของคุณอาจจัดการกับความขัดแย้งของเกมที่บันทึกไว้โดย การเลือกเกมที่บันทึกไว้ที่ได้รับการแก้ไขล่าสุดเป็นเวอร์ชันสุดท้ายที่จะบันทึก:
private static final int MAX_SNAPSHOT_RESOLVE_RETRIES = 10; TaskS<napshot >processSnapshotOpenResult(SnapshotsClient.DataOrConflictS<napshot >result, final int retryCount) { if (!result.isConflict()) { // There was no conflict, so return the result of the source. TaskCompletionSourceS<napshot >source = new TaskCompletionSource(<>); source.setResult(result.getData()); return source.getTask(); } // There was a conflict. Try resolving it by selecting the newest of the conflicting snapshots. // This is the same as using RESOLUTION_POLICY_MOST_RECENTLY_MODIFIED as a conflict resolution // policy, but we are implementing it as an example of a manual resolution. // One option is to present a UI to the user to choose which snapshot to resolve. SnapshotsClient.SnapshotConflict conflict = result.getConflict(); Snapshot snapshot = conflict.getSnapshot(); Snapshot conflictSnapshot = conflict.getConflictingSnapshot(); // Resolve between conflicts by selecting the newest of the conflicting snapshots. Snapshot resolvedSnapshot = snapshot; if (snapshot.getMetadata().getLastModifiedTimestamp() < conflictSnapshot.getMetadata().getLastModifiedTimestamp()) { resolvedSnapshot = conflictSnapshot; } return Games.getSnapshotsClient(theActivity, GoogleSignIn.getLastSignedInAccount(this)) .resolveConflict(conflict.getConflictId(), resolvedSnapshot) .continueWithTask( new Continuation < SnapshotsClient.DataOrConflictS<napshot,> TaskS<napshot(>>) { @Override public TaskS<napshot >then( @NonNull TaskS<napshotsClient.DataOrConflictS<napshot >>task) throws Exception { // Resolving the conflict may cause another conflict, // so recurse and try another resolution. if (retryCount <MAX_SNAPSHOT_RESOLVE_RETRIES) { return processSnapshotOpenResult(task.getResult(), retryCount + 1); } else { throw new Exception(C"ould not resolve snapshot conflicts)"; } } }); }
การแก้ไขเกมที่บันทึกไว้เพื่อแก้ไขความขัดแย้ง
หากต้องการรวมข้อมูลจากเกมที่บันทึกไว้หลายเกมหรือแก้ไข Snapshot
ที่มีอยู่
หากต้องการบันทึกไปยังเซิร์ฟเวอร์เป็นเวอร์ชันสุดท้ายที่แก้ไขแล้ว ให้ทำตามขั้นตอนต่อไปนี้
- โทรหา
SnapshotsClient.open()
- โทรหา
SnapshotsClient.SnapshotConflict.getResolutionSnapshotsContent()
เพื่อรับ ออบเจ็กต์SnapshotContents
- รวมข้อมูลจาก
SnapshotsClient.SnapshotConflict.getConflictingSnapshot()
และSnapshotsClient.SnapshotConflict.getSnapshot()
ลงในออบเจ็กต์SnapshotContents
จาก ขั้นตอนก่อนหน้า - (ไม่บังคับ) สร้างอินสแตนซ์
SnapshotMetadataChange
หากมีการเปลี่ยนแปลงกับข้อมูลเมตา ด้วย - โทร
SnapshotsClient.resolveConflict()
ในการเรียกใช้เมธอด ให้ส่งในSnapshotsClient.SnapshotConflict.getConflictId()
เป็นอาร์กิวเมนต์แรก และSnapshotMetadataChange
และSnapshotContents
ออบเจ็กต์ที่คุณแก้ไขก่อนหน้านี้เป็นรายการที่ 2 และ อาร์กิวเมนต์ที่ 3 ตามลำดับ - หากการเรียก
SnapshotsClient.resolveConflict()
สำเร็จ API จะจัดเก็บSnapshot
ไปยังเซิร์ฟเวอร์และพยายามเปิดออบเจ็กต์ Snapshot ในอุปกรณ์ของคุณเอง- หากมีข้อขัดแย้ง
SnapshotsClient.DataOrConflict.isConflict()
จะแสดงผลtrue
ด้วยวิธีนี้ เกมของคุณควรกลับไปยังขั้นตอนที่ 2 และทำตามขั้นตอนซ้ำเพื่อแก้ไขภาพรวมจนกว่า ความขัดแย้งจะได้รับการแก้ไข - หากไม่มีข้อขัดแย้ง
SnapshotsClient.DataOrConflict.isConflict()
จะแสดงผลfalse
และ ออบเจ็กต์Snapshot
เปิดให้เกมแก้ไขแล้ว
- หากมีข้อขัดแย้ง