如何通过Google Sign In接入Google Sheets API实现读写操作?
问题:通过Google Sign In接入Google Sheets API(Android应用)
我正在开发一款可访问Google Sheets的Android应用,因需同时支持读写,无法使用仅能读取的API密钥。参考Google Sheets API Java快速入门文档时登录Google账号遇到问题,随后集成Google Sign In功能并编写了MainActivity代码:
package com.example.frcscout22sheets import Home import android.content.ContentValues.TAG import android.content.Intent import android.os.Bundle import android.util.Log import androidx.appcompat.app.AppCompatActivity import androidx.fragment.app.Fragment import com.example.frcscout22sheets.databinding.ActivityMainBinding 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.api.services.sheets.v4.SheetsScopes class MainActivity : AppCompatActivity() { private lateinit var binding: ActivityMainBinding private lateinit var mGoogleSignInClient: GoogleSignInClient companion object { val instance = MainActivity() } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityMainBinding.inflate(layoutInflater) setContentView(binding.root) val gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) .requestIdToken("975626648989-jf3cl536froqejdc741ai934ek540ovv.apps.googleusercontent.com") .requestScopes(Scope(SheetsScopes.SPREADSHEETS)) .requestServerAuthCode("975626648989-jf3cl536froqejdc741ai934ek540ovv.apps.googleusercontent.com") .requestEmail() .build() mGoogleSignInClient = GoogleSignIn.getClient(this, gso); val dataFragment = Data() val allianceSelectionFragment = AllianceSelection() val homeFragment = Home() val signin = findViewById<SignInButton>(R.id.sign_in_button) setCurrentFragment(homeFragment) signin.setOnClickListener { signIn() } binding.bottomNavigationView.setOnItemSelectedListener { when (it.itemId) { R.id.data -> setCurrentFragment(dataFragment) R.id.alliance_selection -> setCurrentFragment(allianceSelectionFragment) R.id.home -> setCurrentFragment(homeFragment) } true } } private fun setCurrentFragment(fragment: Fragment) = supportFragmentManager.beginTransaction().apply { replace(R.id.flFragment, fragment) commit() } private fun signIn() { val signInIntent: Intent = mGoogleSignInClient.signInIntent startActivityForResult(signInIntent, 1) } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) // Result returned from launching the Intent from GoogleSignInClient.getSignInIntent(...); if (requestCode == 1) { // The Task returned from this call is always completed, no need to attach // a listener. val task: Task<GoogleSignInAccount> = GoogleSignIn.getSignedInAccountFromIntent(data) handleSignInResult(task) } } private fun handleSignInResult(completedTask: Task<GoogleSignInAccount>) { try { val account = completedTask.getResult(ApiException::class.java) // Signed in successfully, show authenticated UI. } 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) } } }
完成登录后,不清楚如何利用该登录信息构建Sheets服务以调用API。此前使用快速入门时,通过云控制台下载的.json文件获取凭据构建服务:
private val service = Sheets.Builder( HTTPTRANSPORT, jsonfactory, getCredentials(context, HTTPTRANSPORT)
解决方案
1. 从登录账号中获取Access Token
修改handleSignInResult方法,通过GoogleAuthUtil获取已授权账号的Access Token,这个Token将用于验证Sheets API请求:
private fun handleSignInResult(completedTask: Task<GoogleSignInAccount>) { try { val account = completedTask.getResult(ApiException::class.java) account?.let { googleAccount -> // 获取Access Token,指定Sheets的权限范围 val accessToken = GoogleAuthUtil.getToken( this, googleAccount.account, "oauth2:${SheetsScopes.SPREADSHEETS}" ) // 用Token构建Sheets服务实例 val sheetsService = buildSheetsService(accessToken) // 后续可使用sheetsService调用Sheets API进行读写操作 } } catch (e: ApiException) { Log.w(TAG, "signInResult:failed code=" + e.statusCode) } catch (e: IOException) { Log.e(TAG, "获取Access Token失败", e) } }
2. 构建Sheets服务实例
编写buildSheetsService方法,利用获取到的Access Token作为请求授权凭据,替代之前的.json文件凭据方式:
import com.google.api.client.extensions.android.http.AndroidHttp import com.google.api.client.json.gson.GsonFactory import com.google.api.services.sheets.v4.Sheets private fun buildSheetsService(accessToken: String): Sheets { val HTTP_TRANSPORT = AndroidHttp.newCompatibleTransport() val JSON_FACTORY = GsonFactory.getDefaultInstance() return Sheets.Builder(HTTP_TRANSPORT, JSON_FACTORY) .setHttpRequestInitializer { request -> // 设置Authorization头,用Bearer Token验证 request.headers.authorization = "Bearer $accessToken" } .setApplicationName("你的应用名称") // 替换为你的应用名称 .build() }
3. 关键注意事项
- SHA-1指纹配置:确保在Google Cloud Console的OAuth 2.0客户端ID设置中,已添加你当前Android应用的SHA-1指纹,否则会出现授权失败。
- 权限范围:当前使用
SheetsScopes.SPREADSHEETS支持全量读写操作,若只需读取可改为SheetsScopes.SPREADSHEETS_READONLY。 - Token刷新:Access Token存在过期时间,可通过
GoogleSignInClient.silentSignIn()实现静默刷新,避免用户重复登录。
内容的提问来源于stack exchange,提问作者user17792511
相关产品推荐
相关产品推荐

