Android 无法使用GoogleSignInClient.silentSignIn()在OkHttpClient身份验证程序中检索id令牌

Android 无法使用GoogleSignInClient.silentSignIn()在OkHttpClient身份验证程序中检索id令牌,android,kotlin,google-api,google-oauth,okhttp,Android,Kotlin,Google Api,Google Oauth,Okhttp,在我用Kotlin编写的Android应用程序中,我使用Google登录进行授权,使用JWT令牌进行后端API的身份验证。我的JWT代币和谷歌登录的JWT代币都在1小时后过期 我希望我的应用程序使用Google登录重新授权,并在对后端API的请求因401错误而失败时使用我的API重新验证,因此我向OkHttpClient添加了一个验证器 但是,当我运行下面的代码时,silentSignIn任务将永久锁定,并且不会在val result=Tasks.wait(task)行上响应 我错过了什么明显的

在我用Kotlin编写的Android应用程序中,我使用Google登录进行授权,使用JWT令牌进行后端API的身份验证。我的JWT代币和谷歌登录的JWT代币都在1小时后过期

我希望我的应用程序使用Google登录重新授权,并在对后端API的请求因401错误而失败时使用我的API重新验证,因此我向OkHttpClient添加了一个验证器

但是,当我运行下面的代码时,silentSignIn任务将永久锁定,并且不会在
val result=Tasks.wait(task)
行上响应

我错过了什么明显的东西吗?我找不到任何理由来解释为什么从验证器调用silentSignIn()时会锁定

在其他地方,我不使用
任务。等待(任务)
,因为在那里我使用
OnCompleteListener
更新UI,更新
apiToken
googleToken
变量,但是在下面的代码中,我想在请求失败时更新
apiToken
googleToken
,不需要我的项目中的其他代码重新激发对后端API的请求

TLDR:我想在OkHttpClient身份验证程序中调用GoogleSignIn.silentSignIn(),获取令牌,然后立即重试请求,但我的应用程序在执行任务时冻结。等待。

val RC\u SIGN\u IN=9001
var apiToken:字符串?=无效的
var googleToken:字符串?=无效的
val客户端:OkHttpClient=OkHttpClient
.Builder()
.authenticator(对象:authenticator{
覆盖验证(路由:路由?,响应:响应):请求{
返回if(response.code==401){
//配置登录以请求用户ID、电子邮件地址和基本信息
//配置文件。ID和基本配置文件包含在默认登录中。
瓦尔格索=
GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT\u SIGN\u-IN)
.requestEmail()
.requestIdToken(“token\u转到这里”)
.build()
//通过访问Google登录API和
//gso指定的选项。
val googleSignInClient=GoogleSignIn.getClient(this@MainActivity,gso)
val task=googleSignInClient.silentSignIn().addOnCompleteListener{
val result=it.getResult(ApiException::class.java)
googleToken=结果?.idToken
}.addOnFailureListener{
val signingent=googleSignInClient.signingent
startActivityForResult(签名、注册)
}
如果(任务成功){
googleToken=task.result?.idToken
}否则{
试一试{
/****下面一行是例程锁定的位置:****/
val结果=任务。等待(任务)
googleToken=结果?.idToken
}捕获(例如:ExecutionException){
//任务失败
Log.e(标记“身份验证错误:{ex}”)
}捕获(例如:中断异常){
//等待任务完成时发生中断
Log.e(标记“身份验证错误:{ex}”)
}
}
apiToken=getApiToken(谷歌代币)
响应.请求
.newBuilder()
.标题(“授权”、“持有人$apiToken”)
.build()
}否则{
无效的
}
}
}
)
.build()

经过一番挖掘,我找到了答案。为了同一条船上的其他人,我将记录以下问题和解决方案:

当我开始用类似的方式锁定Google Play计费库时,我的怀疑增加了。调查显示,我是从runBlocking{}上下文调用API get()代码的。Google使用的线程与OkHTTP使用的线程相同,因此runBlocking导致OkHTTP之外的所有网络I/O都被阻塞,直到OkHTTP完成

解决方案是尽可能地删除runBlocking,通过启动{}异步加载数据,并在完成后使用notifyDataSetChanged()更新RecyclerView。我还不能完全删除runBlocking,但它现在使用得太少了,我重新修改了Task.Wait()块,使其超时,并调用intent on timeout:

试试看{
val结果=任务。等待(任务,5,时间单位。秒)
googleToken=结果?.idToken
}捕获(例如:ExecutionException){
//任务失败
Log.e(标记“身份验证错误:{ex}”)
val signingent=googleSignInClient.signingent
startActivityForResult(签名、注册)
}捕获(例如:中断异常){
//等待任务完成时发生中断
Log.e(标记“身份验证错误:{ex}”)
val signingent=googleSignInClient.signingent
startActivityForResult(签名、注册)
}捕获(例如:TimeoutException){
//等待任务完成时发生超时
Log.e(标记“身份验证错误:{ex}”)
val signingent=googleSignInClient.signingent
startActivityForResult(签名、注册)
}
一个更好的解决方案是实现ViewModels(),这是我为一个新项目推荐的,但由于时间紧迫,我在本版本中未能做到这一点