我们通过Google进行的服务器OAuth验证已开始在GoogleTokenResponse.parseIdToken()中抛出NullPointerException:
func getNumberOfDaysInMonth (month : Int , _ Year : Int) -> Int
{
var dateComponents = DateComponents()
dateComponents.year = Year
dateComponents.month = month
let calendar = Calendar.current
let date = calendar.date(from: dateComponents)
let range = calendar.range(of: .day, in: .month, for: date!)
let numDays = range?.count
let dow = calendar.component(.weekday, from: date!)
let sundays = (numDays! + dow) / 7
return numDays! - sundays
}
这是今天开始的新行为。我们的服务器代码没有变化(它已经工作了几个月)。只有来自一个Android设备的凭据才会出现问题 - 我有另一个工作正常。刷新客户端的服务器访问令牌无法解决问题。
GoogleTokenResponse由GoogleAuthorizationCodeTokenRequest()创建,该调用成功,当我记录GoogleTokenResponse时,它看起来有效:
{ “的access_token”: “ya29.mwJvM ...”, “expires_in”:3600, “token_type”: “承载”}
UPDATE:测试了一些,发现tokenResponse.getIdToken()返回null,所以我假设当我调用parseIdToken()时导致NPE的原因。
当GoogleAuthorizationCodeTokenRequest()显然成功并且存在访问令牌时,什么会导致getIdToken()返回null?
答案 0 :(得分:1)
最终解决方案:此问题似乎是由2016年初的Google Play服务更新间歇性触发,以匿名化PlayerID。我们能够通过将访问令牌的服务器验证更改为更新的方法而不是依赖于旧的getIdToken()/ parseIdToken()方法来解决我们的问题。有关详细信息,请参阅下面的最新更新
两天后,带有此故障的Android设备神秘地再次开始工作。因此,原因可能是客户端的Google Play服务状态中的一个短暂错误,该错误会自我纠正。设备重启后发生了修复。
但是我不确定是什么原因。还有Play服务更改推出以启用身份验证而不暴露G +用户ID - 另一种解释是服务器没有获得检索ID的范围。 (如果这是原因,那么Google必须再次部署修复程序,因为我们没有更改任何内容)
我们将继续监控它,如果有其他人遇到此请添加评论。
4/19/16此问题出现在其他设备上。我想知道这是否与此处描述的Google Play身份验证更改有关http://android-developers.blogspot.com/2016/01/play-games-permissions-are-changing-in.html?m=1
该解释有点稀疏,但确实说“新模型可能不再出现由令牌信息返回的user_id。即使它存在,该值也不会与新玩家ID相同“
在这种情况下,问题发生在
之后我还不确定发生了什么,但研究了两个值得关注的领域:
1)虽然上面引用的Google文档说“现有玩家......会继续获取他们的Google+ ID”,但我想知道这是否是按客户端管理的。这将是一个大问题,因为我们使用该ID为用户跨设备存储云状态,因此如果最初在新玩家ID之前设置其帐户的用户然后在第二个设备上安装了该应用,则他们可以使用gplay但这两个帐户不匹配
2)如果这是原因,那么我们的服务器代码无法使用新的非G +播放器ID,或者当设备在两者之间转换时存在谷歌后端错误。这仍然令人困惑,因为我们之前的问题在几天之后就自我纠正了,这意味着服务器代码很好 - 但我确信希望谷歌后端auth的错误的替代解释是错误的!< / p>
---更新
我认为这个问题与新的GPS匿名玩家ID变化有关。它很难调试,因为看起来Google的遗留服务器身份验证流程(需要非空的GoogleTokenResponse.getIdToken())对于新创建的GPS PlayerID失败了,但是在12-24小时后问题似乎是自我纠正的传统的Google身份验证调用开始成功,包括返回非null的getIdToken()。
但是我尝试在google信息页面的第7步中实现新的PlayerID流程,该步骤通过www.googleapis.com/games/v1/applications将访问令牌(从服务器身份验证代码生成)转换为玩家ID //验证/
即使getToken()返回null,此代码也会成功从accessToken中检索播放器ID:
// URL: www.googleapis.com/games/v1/applications/<app_id>/verify/
URL url = new URL("https://www.googleapis.com/games/v1/applications/" + GPlayServicesAppId + "/verify/");
HttpURLConnection httpConnection = (HttpURLConnection) url.openConnection();
httpConnection.setRequestProperty("Authorization", "OAuth " + accessToken);
httpConnection.setRequestMethod("GET");
int responseCode = httpConnection.getResponseCode();
if (responseCode != HttpURLConnection.HTTP_OK) {
...
}
BufferedReader reader = new BufferedReader(new InputStreamReader(httpConnection.getInputStream()));
String responseJson = (read contents of reader)
// Example response: { "kind": "games#applicationVerifyResponse", "player_id": "11520..."}
我运行了一些测试,就像我可以告诉新方法适用于所有旧G + getToken()方法的工作以及修复它没有的情况一样,所以我相信我们可以切换到上面的代码片段中的新方法,希望这将是可靠的。