androidgoogle-cloud-platformgoogle-drive-apigoogle-drive-android-api

When requesting Google drive scope permission gives infinite loading dialog


I wanted to integrate Google drive into my app for storing user's app data in it.

What I have tried

I have implemented Google Sign-In from Google dev doc and requested drive scope from additional scopes section. Also I tried to request scope directly from .requestScope() method on GoogleSignInOptions.Builder.

I have also added SHA-1 key in GCP.

MainActivity.kt

import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import com.google.android.gms.auth.api.signin.GoogleSignIn
import com.google.android.gms.auth.api.signin.GoogleSignInAccount
import com.google.android.gms.auth.api.signin.GoogleSignInClient
import com.google.android.gms.auth.api.signin.GoogleSignInOptions
import com.google.android.gms.common.SignInButton
import com.google.android.gms.common.api.ApiException
import com.google.android.gms.common.api.Scope
import com.google.android.gms.tasks.Task
import com.google.android.material.textview.MaterialTextView


class MainActivity : AppCompatActivity(), View.OnClickListener {

    private val gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
        .requestEmail()
        .build()

    private lateinit var mGoogleSignInClient: GoogleSignInClient
    lateinit var text: MaterialTextView
    lateinit var signInBtn: SignInButton


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        mGoogleSignInClient = GoogleSignIn.getClient(this, gso)

        text = findViewById(R.id.text)
        signInBtn = findViewById(R.id.signInButton)

        signInBtn.setOnClickListener(this)
    }

    override fun onStart() {
        super.onStart()
        val account = GoogleSignIn.getLastSignedInAccount(this)
        updateUI(account)
    }

    // Update the UI with user name
    private fun updateUI(account: GoogleSignInAccount?) {
        if (account != null)
            text.text = account.displayName
    }

    override fun onClick(v: View?) {
        if (v!!.id == R.id.signInButton) {
            signIn()
        }
    }

    private fun signIn() {
        val signInIntent = mGoogleSignInClient.signInIntent
        startActivityForResult(signInIntent, RC_SIGN_IN)
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (requestCode == RC_SIGN_IN) {
            val task = GoogleSignIn.getSignedInAccountFromIntent(data)
            handleSignInResult(task)
        } else if (RC_DRIVE == requestCode) {
            Log.d(TAG, "onActivityResult: Permission granted")
        }
    }

    private fun handleSignInResult(completedTask: Task<GoogleSignInAccount>) {
        try {
            val account = completedTask.getResult(ApiException::class.java)

            // Signed in successfully, show authenticated UI.
            updateUI(account)
            // If permission is not granted then it will request it
            if (!GoogleSignIn.hasPermissions(
                    GoogleSignIn.getLastSignedInAccount(this),
                    Scope("https://www.googleapis.com/auth/drive.appdata")
                )
            ) {
                // This gives the infinitely loading screen
                GoogleSignIn.requestPermissions(
                    this, RC_DRIVE, GoogleSignIn.getLastSignedInAccount(this),
                    Scope("https://www.googleapis.com/auth/drive.appdata")
                )
            }
        } catch (e: ApiException) {
            // The ApiException status code indicates the detailed failure reason.
            // Please refer to the GoogleSignInStatusCodes class reference for more information.
            Log.w(TAG, "signInResult:failed code=" + e.statusCode)
            updateUI(null)
        }
    }

    companion object {
        const val RC_SIGN_IN = 100
        const val RC_DRIVE = 101
        const val TAG = "MainActivity"
    }
}

Solution

  • I had to add myself as a testing user in GCP console > API and Services > Credentials.

    GCP console > API and Services > Credentials.

    You would require to publish the app if you want to make it publicly available.