在Android

时间:2016-12-06 14:04:04

标签: android oauth-2.0 google-api

我们使用Android(Jellybean及更高版本),我们有一个应用需要使用OAuth2与Google进行身份验证。

我简化了登录活动,但看起来像是这样:

AccountManager mAccountManager;
// [...]
Account account = new Account("myEmail@gmail.com", "com.google");
// same with professional email managed by Google as myEmail@myDomain.com
// real code recovers accounts with mAccountManager.getAccountsByType("com.google")
mAccountManager = AccountManager.get(getBaseContext());
mAccountManager.getAuthToken(account, "oauth2:https://www.googleapis.com/auth/userinfo.email", null, MyActivity.this, new AccountManagerCallback<Bundle>() {
    @Override
    public void run(AccountManagerFuture<Bundle> accountManagerFuture) {
        try {
            String token = accountManagerFuture.getResult().getString(AccountManager.KEY_AUTHTOKEN);
            // exception occurs here
            // [...]
        } catch (Exception e) {
            Log.e("account", "exception occurs", e);
        }
    }
}, null);

当我们调用accountManagerFuture.getResult()时,它会触发此异常:

android.accounts.AuthenticatorException: UNREGISTERED_ON_API_CONSOLE
    at android.accounts.AccountManager.convertErrorToException(AccountManager.java:2024)
    at android.accounts.AccountManager.access$400(AccountManager.java:144)
    at android.accounts.AccountManager$AmsTask$Response.onError(AccountManager.java:1867)
    at android.accounts.IAccountManagerResponse$Stub.onTransact(IAccountManagerResponse.java:69)
    at android.os.Binder.execTransact(Binder.java:446)

我找不到关于此的文档或其他具有相同异常的人,我很困惑:对AccountManager.getAuthToken的调用只提供了一个帐户(名称和类型),范围和回调方法,没有参数来指定我可以在开发API控制台中自定义的应用程序。

我确定我错过了什么,但是什么?

6 个答案:

答案 0 :(得分:32)

好吧,我终于明白了。不确定我是否误读了文档或是否缺少链接,但无论如何。

事实是,当您签署APK然后向Google询问OAuth2令牌时,您必须通过开发控制台注册已签名的应用。这是基于应用程序包名称和sha1指纹的安全措施。

要做到这一点,你必须:

  1. 手动或通过Gradle或其他任何方式签署您的APK:Android documentation在此步骤中非常清楚;
  2. 得到你的sha1指纹;正如this SO answer中提到的,在Android Studio上很容易:在Gradle面板中,选择根项目下的signingReport任务并运行它 - SHA1指纹将显示在文本输出中;
  3. 通过Google dev console注册您的APK:创建一个新的凭据/ OAuth客户端ID / Android,由您获得的SHA1指纹和您的APK包名称定义。
  4. 瞧!

    有关信息,我发现的唯一官方文档解释了最后两个步骤的原因和方法: https://developers.google.com/drive/android/auth

答案 1 :(得分:13)

对于仍在努力解决这个问题的人来说,这对我有用:

如果您将应用注册到 Google Play App Signing 计划中,那么您的KeyStore一旦到达游戏商店就不会事实上用于签署该应用程序 - 这就是指纹的原因不配。

Google会移除您的证书并创建一个用于签署APK的新签名证书。

在Play控制台中,转到版本管理 - &gt;应用签名

如果您选择加入 Google Play App Signing ,则会在其中看到2个证书及其所有指纹。使用应用签名证书指纹代替上传证书,这是您的KeyStore。

答案 2 :(得分:8)

不赞成对已接受的答案发表评论......

在google开发者控制台中注册我的应用并不适合我。事实证明,由于我使用的是调试gradle构建,我不得不追加&#34; .debug&#34;到google dev控制台中的包名称。

我通过调试Android AccountManager代码找到了这个。当我进入代码时,我注意到我的应用程序包名称的变量有&#34; .debug&#34;在它的最后。因此,而不是使用实际的包名称&#34; com.package.name&#34;在google开发者控制台中,我将其更改为&#34; com.package.name.debug&#34;它为我修复了UNREGISTERED_ON_API_CONSOLE例外。

原因是因为我在gradle中的调试buildType有&#39; applicationIdSuffix&#34; .debug&#34;&#39;。

答案 3 :(得分:0)

对我来说,上述解决方案根本不起作用。我终于自己找出了这个bug。 我的工作空间中有几个文件夹,每个文件夹都有自己的 Manifest.xml 文件,这意味着它们具有不同的包名称。在这种情况下,当我们在Google API上注册时,我们必须使用文件 build.gradle 中的包名称,属性 applicationId 。 然后就是。

答案 4 :(得分:0)

谢谢Xavier Portebois,你的答案真的很有帮助。我不得不再做两步。

  • 请确保在同一个Google开发者控制台中启用您正在使用的服务的API(在我的情况下是Calendar API)
  • 如果您使用的是Google Play应用程序签名,则不希望使用Android Studio中的调试SHA指纹。相反,请转到您的应用发布控制台 - &gt;发布管理 - &gt;应用签名。使用App Signing证书中的SHA-1指纹。 2nd line in this screenshot

感谢您提供丰富的答案!

答案 5 :(得分:0)

对我来说,问题是调试应用程序的签名证书指纹(SHA-1)和升级应用程序在升级应用程序和更改包名称时不匹配。我浪费了几天检查包名,然后找出问题是包名。

要获得正确的SHA-1密钥,请按此S.O post,然后使用此密钥为您的应用创建新的OAuth客户端ID。