Я интегрировал Google Play Game Services в свое приложение Android, вход работает нормально, и теперь я пытаюсь сохранить свою игру, но когда я пытаюсь сделать, я получаю ошибку, говоря java.lang.illegalstateexception: не могу использовать снимки без включения Функция «Сохраняемой игры» в консоли Play , я включил «Сохраненную игру» в Google Play Console, см. Ниже скриншот
Когда я Проходил через документ, я заметил, что ему требуется GoogleSignInclient , прежде чем использовать сохраненные игры, теперь, учитывая, что GoogleSignInclient снижается, я использую диспетчер учетных данных, пожалуйста, не путайте это с Services Google Play Services Services в котором я уже делаю, как только приложение открывается, следуя этому документу < /p>
, поэтому я решил использовать диспетчер учетных данных с Google Drive Access, вот пример кода для это < /p>
private fun signInSilently() {
val credentialManager = CredentialManager.create(this)
val rawNonce = UUID.randomUUID().toString()
val bytes = rawNonce.toByteArray()
val md = MessageDigest.getInstance("SHA-256")
val digest = md.digest(bytes)
val hashedNonce = digest.fold("") { str, it -> str + "%02x".format(it) }
val googleIdOption = GetGoogleIdOption.Builder()
.setFilterByAuthorizedAccounts(false) //IMP Part
.setServerClientId("MY_WEB_CLIENT_ID")
.setAutoSelectEnabled(true)
.setNonce(hashedNonce)
.build()
val request: GetCredentialRequest = GetCredentialRequest.Builder()
.addCredentialOption(googleIdOption)
.build()
lifecycleScope.launch {
try {
val result = credentialManager.getCredential(
request = request,
context = this@MainActivity,
)
handleSignIn(result)
} catch (e: GetCredentialException) {
Log.e("Erroris", "Error getting credential", e)
}
}
}
private fun handleSignIn(result: GetCredentialResponse) {
// Handle the successfully returned credential.
when (val credential = result.credential) {
// Passkey credential
is PublicKeyCredential -> {
// Share responseJson such as a GetCredentialResponse on your server to
// validate and authenticate
val responseJson = credential.authenticationResponseJson
}
// Password credential
is PasswordCredential -> {
// Send ID and password to your server to validate and authenticate.
val username = credential.id
val password = credential.password
}
// GoogleIdToken credential
is CustomCredential -> {
if (credential.type == GoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL) {
try {
// Use googleIdTokenCredential and extract id to validate and
// authenticate on your server.
val googleIdTokenCredential = GoogleIdTokenCredential
.createFrom(credential.data)
val googleIdToken = googleIdTokenCredential.idToken
Log.i("answer", googleIdToken)
val personId = googleIdTokenCredential.id
Log.i("answer", personId) //email
val displayName = googleIdTokenCredential.displayName
Log.i("answer", displayName.toString())
val personPhoto = googleIdTokenCredential.profilePictureUri
Log.i("answer", personPhoto.toString())
val requestedScopes = listOf(Scope(DriveScopes.DRIVE_APPDATA))
val authorizationRequest =
AuthorizationRequest.builder()
.setRequestedScopes(requestedScopes)
.build()
Identity.getAuthorizationClient(this@MainActivity)
.authorize(authorizationRequest)
.addOnSuccessListener {
if (it.hasResolution()) {
val pendingIntent = it.pendingIntent
val intentSenderRequest = pendingIntent?.intentSender?.let { it1 ->
IntentSenderRequest.Builder(
it1
).build()
}
intentSenderRequest?.let { it1 -> authorizationLauncher.launch(it1) }
} else {
Toast.makeText(
this@MainActivity,
"Access already granted ",
Toast.LENGTH_LONG
).show()
}
}.addOnFailureListener {
Toast.makeText(this@MainActivity, "Failure ${it.message}", Toast.LENGTH_LONG)
.show()
}
} catch (e: GoogleIdTokenParsingException) {
Log.e("Erroris", "Received an invalid google id token response", e)
}
} else {
// Catch any unrecognized custom credential type here.
Log.e("Erroris", "Unexpected type of credential")
}
}
else -> {
// Catch any unrecognized credential type here.
Log.e("Erroris", "Unexpected type of credential")
}
}
}
< /code>
Как только это будет успешным, я позвоню ниже кода, чтобы сохранить мою игру < /p>
val snapshotsClient =
PlayGames.getSnapshotsClient(this)
val maxNumberOfSavedGamesToShow = 5
val intentTask = snapshotsClient.getSelectSnapshotIntent(
"See My Saves", true, true, maxNumberOfSavedGamesToShow
)
intentTask.addOnCompleteListener {
if (intentTask.isSuccessful) {
savedGameLauncher.launch(intentTask.result)
} else {
Log.i("here123","${it.exception}")
Toast.makeText(this, "Fail to get snapshot", Toast.LENGTH_LONG).show()
}
}
private val savedGameLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
val intent = result.data
if(intent != null){
val snapshotsClient =
PlayGames.getSnapshotsClient(this)
if (intent.hasExtra(SnapshotsClient.EXTRA_SNAPSHOT_METADATA)) {
// Load a snapshot.
//TODO display progress bar
val snapshotMetadata = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
intent.getParcelableExtra(SnapshotsClient.EXTRA_SNAPSHOT_METADATA, SnapshotMetadata::class.java)
} else {
intent.getParcelableExtra(SnapshotsClient.EXTRA_SNAPSHOT_METADATA)
}
val mCurrentSaveName = snapshotMetadata!!.uniqueName
val conflictResolutionPolicy =
SnapshotsClient.RESOLUTION_POLICY_MOST_RECENTLY_MODIFIED
snapshotsClient.open(mCurrentSaveName,true,conflictResolutionPolicy)
.addOnFailureListener {
Toast.makeText(this, "Save Game Fail", Toast.LENGTH_LONG).show()
}
.continueWith {
val snapshot = it.result.data
if(snapshot != null){
val byteArray = snapshot.snapshotContents.readFully()
val stringData = String(byteArray)
Log.i("datais",stringData)
Toast.makeText(this, stringData, Toast.LENGTH_LONG).show()
}
}
.addOnCompleteListener{
//TODO dismiss progress bar
}
} else if (intent.hasExtra(SnapshotsClient.EXTRA_SNAPSHOT_NEW)) {
// Create a new snapshot named with a unique string
val unique: String = BigInteger(281, Random()).toString(13)
val mCurrentSaveName = "snapshotTemp-$unique"
snapshotsClient.open(mCurrentSaveName,true).addOnCompleteListener{
if(it.isSuccessful){
val snapshot = it.result.data
val stringData = "Level 100"
if(snapshot != null){
snapshot.snapshotContents.writeBytes(stringData.toByteArray())
val metadataChange = SnapshotMetadataChange.Builder().setDescription("$stringData reached").build()
snapshotsClient.commitAndClose(snapshot, metadataChange).addOnCompleteListener{ finalResult ->
if(finalResult.isSuccessful){
Toast.makeText(this, "Save Game Success", Toast.LENGTH_LONG).show()
}
}
} else {
Toast.makeText(this, "Snapshot is null", Toast.LENGTH_LONG).show()
}
} else {
Toast.makeText(this, "Save Game Fail", Toast.LENGTH_LONG).show()
}
}
}
}
}
Но я продолжаю видеть ошибку, говоря, что java.lang.illegalstateexception: не может использовать снимки, не включая функцию «Сохраненная игра» в консоли Play , я даже ждал дня, думая Может потребоваться некоторое время, чтобы распространить изменения на стороне сервера Google, но, к сожалению, ожидание не работает
Я интегрировал Google Play Game Services в свое приложение Android, вход работает нормально, и теперь я пытаюсь сохранить свою игру, но когда я пытаюсь сделать, я получаю ошибку, говоря java.lang.illegalstateexception: не могу использовать снимки без включения Функция «Сохраняемой игры» в консоли Play , я включил «Сохраненную игру» в Google Play Console, см. Ниже скриншот
Когда я Проходил через документ, я заметил, что ему требуется GoogleSignInclient , прежде чем использовать сохраненные игры, теперь, учитывая, что GoogleSignInclient снижается, я использую диспетчер учетных данных, пожалуйста, не путайте это с Services Google Play Services Services в котором я уже делаю, как только приложение открывается, следуя этому документу < /p> , поэтому я решил использовать диспетчер учетных данных с Google Drive Access, вот пример кода для это < /p> [code]private fun signInSilently() {
val credentialManager = CredentialManager.create(this)
val rawNonce = UUID.randomUUID().toString() val bytes = rawNonce.toByteArray() val md = MessageDigest.getInstance("SHA-256") val digest = md.digest(bytes) val hashedNonce = digest.fold("") { str, it -> str + "%02x".format(it) }
val googleIdOption = GetGoogleIdOption.Builder() .setFilterByAuthorizedAccounts(false) //IMP Part .setServerClientId("MY_WEB_CLIENT_ID") .setAutoSelectEnabled(true) .setNonce(hashedNonce) .build()
val request: GetCredentialRequest = GetCredentialRequest.Builder() .addCredentialOption(googleIdOption) .build()
lifecycleScope.launch { try { val result = credentialManager.getCredential( request = request, context = this@MainActivity, )
private fun handleSignIn(result: GetCredentialResponse) { // Handle the successfully returned credential. when (val credential = result.credential) {
// Passkey credential is PublicKeyCredential -> { // Share responseJson such as a GetCredentialResponse on your server to // validate and authenticate val responseJson = credential.authenticationResponseJson }
// Password credential is PasswordCredential -> { // Send ID and password to your server to validate and authenticate. val username = credential.id val password = credential.password }
// GoogleIdToken credential is CustomCredential -> { if (credential.type == GoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL) { try { // Use googleIdTokenCredential and extract id to validate and // authenticate on your server. val googleIdTokenCredential = GoogleIdTokenCredential .createFrom(credential.data) val googleIdToken = googleIdTokenCredential.idToken Log.i("answer", googleIdToken) val personId = googleIdTokenCredential.id Log.i("answer", personId) //email val displayName = googleIdTokenCredential.displayName Log.i("answer", displayName.toString()) val personPhoto = googleIdTokenCredential.profilePictureUri Log.i("answer", personPhoto.toString())
val requestedScopes = listOf(Scope(DriveScopes.DRIVE_APPDATA)) val authorizationRequest = AuthorizationRequest.builder() .setRequestedScopes(requestedScopes) .build()
} catch (e: GoogleIdTokenParsingException) { Log.e("Erroris", "Received an invalid google id token response", e) } } else { // Catch any unrecognized custom credential type here. Log.e("Erroris", "Unexpected type of credential") } }
else -> { // Catch any unrecognized credential type here. Log.e("Erroris", "Unexpected type of credential") } } } < /code> Как только это будет успешным, я позвоню ниже кода, чтобы сохранить мою игру < /p> val snapshotsClient = PlayGames.getSnapshotsClient(this) val maxNumberOfSavedGamesToShow = 5
val intentTask = snapshotsClient.getSelectSnapshotIntent( "See My Saves", true, true, maxNumberOfSavedGamesToShow ) intentTask.addOnCompleteListener { if (intentTask.isSuccessful) { savedGameLauncher.launch(intentTask.result) } else { Log.i("here123","${it.exception}") Toast.makeText(this, "Fail to get snapshot", Toast.LENGTH_LONG).show() } }
private val savedGameLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> val intent = result.data
if(intent != null){
val snapshotsClient = PlayGames.getSnapshotsClient(this)
if (intent.hasExtra(SnapshotsClient.EXTRA_SNAPSHOT_METADATA)) { // Load a snapshot. //TODO display progress bar val snapshotMetadata = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { intent.getParcelableExtra(SnapshotsClient.EXTRA_SNAPSHOT_METADATA, SnapshotMetadata::class.java) } else { intent.getParcelableExtra(SnapshotsClient.EXTRA_SNAPSHOT_METADATA) }
val mCurrentSaveName = snapshotMetadata!!.uniqueName val conflictResolutionPolicy = SnapshotsClient.RESOLUTION_POLICY_MOST_RECENTLY_MODIFIED
snapshotsClient.open(mCurrentSaveName,true,conflictResolutionPolicy) .addOnFailureListener { Toast.makeText(this, "Save Game Fail", Toast.LENGTH_LONG).show() } .continueWith { val snapshot = it.result.data if(snapshot != null){ val byteArray = snapshot.snapshotContents.readFully() val stringData = String(byteArray) Log.i("datais",stringData) Toast.makeText(this, stringData, Toast.LENGTH_LONG).show() } } .addOnCompleteListener{ //TODO dismiss progress bar }
} else if (intent.hasExtra(SnapshotsClient.EXTRA_SNAPSHOT_NEW)) { // Create a new snapshot named with a unique string val unique: String = BigInteger(281, Random()).toString(13) val mCurrentSaveName = "snapshotTemp-$unique"
snapshotsClient.open(mCurrentSaveName,true).addOnCompleteListener{ if(it.isSuccessful){ val snapshot = it.result.data val stringData = "Level 100"
} else { Toast.makeText(this, "Save Game Fail", Toast.LENGTH_LONG).show() } }
} }
} [/code] Но я продолжаю видеть ошибку, говоря, что java.lang.illegalstateexception: не может использовать снимки, не включая функцию «Сохраненная игра» в консоли Play , я даже ждал дня, думая Может потребоваться некоторое время, чтобы распространить изменения на стороне сервера Google, но, к сожалению, ожидание не работает