I am using google play services signInSilently()
, but I got the error signInSilently()
Failed com.google.android.gms.common.api.ApiException: 4: 4: , but I am a test user in my application. I already added SHA-1, client ID, client secret and enable sign in with google, google play game service on my firebase project. My code is below,
class SignInGGPlayBan2 : AppCompatActivity() {
private lateinit var googleSignInClient: GoogleSignInClient
private lateinit var auth: FirebaseAuth
companion object {
private val TAG = "SignInGGPlayBan2"
private const val RC_SIGN_IN = 9001
}
private var btnSignIn: SignInButton? = null
private var btnGGPlayGameSignOut: Button? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_ggplay)
val gso = GoogleSignInOptions
.Builder(GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN)
.requestServerAuthCode(getString(R.string.default_web_client_id))
.build()
googleSignInClient = GoogleSignIn.getClient(this, gso)
auth = FirebaseAuth.getInstance()
btnSignIn = findViewById(R.id.btnGGPlayGame)
btnGGPlayGameSignOut = findViewById(R.id.btnGGPlayGameSignOut)
btnSignIn!!.setOnClickListener {
startSignInIntent()
}
}
override fun onStart() {
super.onStart()
val currentUser = auth.currentUser
updateUI(currentUser)
}
private fun startSignInIntent() {
val intent = googleSignInClient.signInIntent
startActivityForResult(intent, RC_SIGN_IN)
}
private fun signInSilently() {
googleSignInClient.silentSignIn().addOnCompleteListener(this) { task ->
if (task.isSuccessful) {
Toast.makeText(this@SignInGGPlayBan2, "Successful", Toast.LENGTH_SHORT).show()
firebaseAuthWithPlayGames(task.result!!)
} else {
Log.d(TAG, "signInSilently() Failed", task.getException())
Toast.makeText(this@SignInGGPlayBan2, "Failed", Toast.LENGTH_SHORT).show()
}
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == RC_SIGN_IN) {
val result = Auth.GoogleSignInApi.getSignInResultFromIntent(data)
if (result!!.isSuccess) {
firebaseAuthWithPlayGames(result.signInAccount!!)
Toast.makeText(this@SignInGGPlayBan2, "Successful Activity", Toast.LENGTH_SHORT).show()
} else {
Toast.makeText(this@SignInGGPlayBan2, "Failed Activity", Toast.LENGTH_SHORT).show()
}
}
private fun firebaseAuthWithPlayGames(acct: GoogleSignInAccount) {
Log.d(TAG, "firebaseAuthWithPlayGames:" + acct.id!!)
val auth = FirebaseAuth.getInstance()
val credential = PlayGamesAuthProvider.getCredential(acct.serverAuthCode!!)
auth.signInWithCredential(credential)
.addOnCompleteListener(this) { task ->
if (task.isSuccessful) {
Log.d(TAG, "signInWithCredential:success")
val user = auth.currentUser
updateUI(user)
} else {
Log.w(TAG, "signInWithCredential:failure", task.exception)
Toast.makeText(baseContext, "Authentication failed.", Toast.LENGTH_SHORT).show()
updateUI(null)
}
}
}
override fun onResume() {
super.onResume()
signInSilently()
}
private fun updateUI(currentUser: FirebaseUser?) {
if (currentUser != null) {
btnGGPlayGameSignOut!!.visibility = View.VISIBLE
} else {
btnGGPlayGameSignOut!!.visibility = View.INVISIBLE
}
}
}
error
signInSilently() Failed
com.google.android.gms.common.api.ApiException: 4: 4:
at com.google.android.gms.common.internal.ApiExceptionUtil.fromStatus(com.google.android.gms:play-services-base@@17.1.0:4)
at com.google.android.gms.common.internal.zai.zaf(com.google.android.gms:play-services-base@@17.1.0:2)
at com.google.android.gms.common.internal.zak.onComplete(com.google.android.gms:play-services-base@@17.1.0:6)
at com.google.android.gms.common.api.internal.BasePendingResult.zaa(com.google.android.gms:play-services-base@@17.1.0:176)
at com.google.android.gms.common.api.internal.BasePendingResult.setResult(com.google.android.gms:play-services-base@@17.1.0:135)
at com.google.android.gms.auth.api.signin.internal.zzi.zzc(com.google.android.gms:play-services-auth@@18.0.0:5)
at com.google.android.gms.auth.api.signin.internal.zzs.dispatchTransaction(com.google.android.gms:play-services-auth@@18.0.0:6)
at com.google.android.gms.internal.auth-api.zzc.onTransact(com.google.android.gms:play-services-auth@@18.0.0:13)
at android.os.Binder.execTransact(Binder.java:565)
Manifest file
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myprojecttest">
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".SignInGGPlayBan2">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Please give me a solution for this problem.
I have been suffering from this for a few days. And today finally I figured it out.
Three Consoles are useful here: Firebase Console / Project Settings: https://console.firebase.google.com
Google Developer Console / Credentials: https://console.developers.google.com/apis/credentials
Linked Apps: https://play.google.com/apps/publish/
Looks like you are using firebase and the same here. And of course, we will follow the guide: https://firebase.google.com/docs/auth/android/play-games?authuser=0 . In my case, we are using Play Games Sign-in.
To fix those GMS ApiExceptions like DEVELOPER_ERROR (10) / INTERNAL_ERROR (8) / API_NOT_CONNECTED (17) / SIGN_IN_REQUIRED (4), follow this checklist below:
signingReport
, this is important, or it'll create an OAuth 2.0 Client ID automatically with your.package.name
and SHA1 from ~/.android/debug.keystore
which is error-prone.keytool -exportcert -alias YOUR_ALIAS -keystore debug.jks -list -v
, paste your debug SHA1 to your Firebase Console.google-service.json
to your Android Studio properly. Watch out, you only set the debug SHA1 but not the release one. Then Run your App, this process will create an OAuth 2.0 Client ID automatically with the debug SHA1. You can refresh the Google Developer Console / Credentials to check what you have done.Android client for your.package.name (auto created by Google Service)
and Web client (auto created by Google Service)
Check you google-service.json
file, it'll contain two client_id
, both must be exactly the same as Google Developer Console / Credentials. Run 'YOUR_PROJECT'
at debug mode will sign the APK with ~/.android/debug.keystore
which SHA1 is not the one you are using to create client id. The Google Developer Console / Credentials should looks like this figure:
The Linked Apps should look like this figure:
Thank you GOOGLE and my fallen hair, good luck to you.
Relative Answers:
How to sign your app using the upload key
Test Google Play Games on app signed with upload key
Testing Games Services using upload key instead of Google Play App signing key
First of all, you should put this on your AndroidManifest.xml
<meta-data android:name="com.google.android.gms.games.APP_ID"
android:value="@string/app_id" />
<meta-data android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version"/>
If you're using Play Games Services v2 SDK,
implementation 'com.google.android.gms:play-services-games-v2:17.0.0'
I got this error when I tried to sign-in with GoogleSignIn API and Play Games Services v2 SDK.
With v2 SDK, You can't sign-in or sign-out with GoogleSignIn API, any more. (cf. Remove sign-in and sign-out calls )
Sign-in is triggered automatically when your game is launched (for the first time), or you can trigger it manually with GamesSignInClient.signIn()
. (cf. Migrate to Play Games Services Sign In v2 )
So your code could be modified like:
private void startSignInIntent() {
PlayGames.getGamesSignInClient(this).signIn()
}
onResume
and signInSilently
(I renamed it checkAuthentication
) would be modified like this:
override fun onResume() {
super.onResume()
// Since the state of the signed in user can change when the activity is not active
// it is recommended to try and sign in silently from when the app resumes.
checkAuthentication()
}
private fun checkAuthentication() {
PlayGames.getGamesSignInClient(this).isAuthenticated.addOnCompleteListener {
val isAuthenticated = it.isSuccessful && it.result.isAuthenticated
if (isAuthenticated) {
// Continue with Play Games Services
PlayGames.getPlayersClient(this).currentPlayer.addOnCompleteListener { task ->
val displayName = if (task.isSuccessful) {
task.result.displayName
} else {
handleException(
task.exception, "There was an issue communicating with players."
)
"???"
}
updateUI(displayName)
}
} else {
// Disable your integration with Play Games Services or show a
// login button to ask players to sign-in. Clicking it should
// call GamesSignInClient.signIn().
updateUI(null)
}
}
}
(The above modifications are for examples. It might not be applied straight foward to your code as they are.)
I think the Google's official document about Play Games Services v2 SDK has some flaws. For example:
The doc aboutSavedGames uses signInSilently
still with v2 but it is obsolete (causing 'com.google.android.gms.common.api.ApiException: 4: 4 '
).
The doc about SavedGames uses GoogleSignInClient
to specify the Drive scope, but it seems not necessary (just let alone with Play Games Services Sign In v2 is sufficient).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.