- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我在我的应用中使用“Google 登录”。因此,我使用类 GoogleApiClient 来获取后端所需的用户电子邮件和 ID token 。
当用户登录时,我可以访问一个 Activity(当然),我使用该 Activity 让 GoogleApiClient 通过调用来处理 UI 生命周期的东西builder.enableAutoManage(myActivity, ...)
这很好用。
但是,在稍后的阶段(几天后),我需要获得一个新的 token (出于某种原因,我在此不再赘述)。我想得到这个 token 静默,无需用户交互。但是,在我需要这个新 token 的代码中,我无法访问任何 Activity 实例。这意味着我无法调用上述电话,即“builder.enableAutoManage”。而且我发现如果我不打那个电话,那么静默登录似乎不起作用。
我附上了下面的代码。现在,看看“silentLogin”方法。只要我在用户实际登录时收到的 token 小于一小时,那么语句“pendingResult.isDone”将返回 true,并且可以接收缓存的 token 。但是,如果我在用户实际登录时收到的 token 超过一小时,则调用“pendingResult.setResultCallback”,但从未调用过“onResult”方法,我无法获得新的 token 。如果我从一个 Activity 中执行完全相同的操作(并且由此也调用“builder.enableAutoManage”),则不会发生此问题。
那么,有谁知道我做错了什么,更重要的是 - 如何解决这个问题并在不访问 Activity 实例的情况下获取新 token ?
我正在使用 com.google.android.gms:play-services-auth:8.4.0
package com.google.samples.quickstart.signin;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import com.google.android.gms.auth.api.Auth;
import com.google.android.gms.auth.api.signin.GoogleSignInAccount;
import com.google.android.gms.auth.api.signin.GoogleSignInOptions;
import com.google.android.gms.auth.api.signin.GoogleSignInResult;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.Scopes;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.OptionalPendingResult;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.common.api.Scope;
/**
* Use this class to login with google account using the OpenId oauth method.
*/
public class GoogleLoginStackOverflow {
private static final String TAG = GoogleLoginIdToken.class.getName();
private static final String SERVER_CLIENT_ID = "XXXXXXXXXXXXXXXXXXXXXXXX.apps.googleusercontent.com";
private GoogleApiClient mGoogleApiClient;
private Context mContext;
private GoogleLoginStackOverflow(Context appContext) {
this.mContext = appContext;
createGoogleClient();
}
/**
* Performs a silent sign in and fetch a token.
*
* @param appContext Application context
*/
public static void silentLogin(Context appContext) {
GoogleLoginStackOverflow googleLoginIdToken = new GoogleLoginStackOverflow(appContext);
googleLoginIdToken.silentLogin();
}
private void createGoogleClient() {
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestProfile()
.requestScopes(new Scope(Scopes.PROFILE))
.requestIdToken(SERVER_CLIENT_ID)
.requestEmail()
.build();
mGoogleApiClient = new GoogleApiClient.Builder(mContext)
.addOnConnectionFailedListener(new GoogleApiClient.OnConnectionFailedListener() {
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
System.out.println("onConnectionFailed = " + connectionResult);
onSilentLoginFinished(null);
}
})
.addConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() {
@Override
public void onConnected(Bundle bundle) {
System.out.println("onConnected bundle = " + bundle);
onSilentLoginFinished(null);
}
@Override
public void onConnectionSuspended(int i) {
System.out.println("onConnectionSuspended i = " + i);
onSilentLoginFinished(null);
}
}).addApi(Auth.GOOGLE_SIGN_IN_API, gso)
.build();
}
private void silentLogin() {
OptionalPendingResult<GoogleSignInResult> pendingResult = Auth.GoogleSignInApi.silentSignIn(mGoogleApiClient);
if (pendingResult != null) {
if (pendingResult.isDone()) {
// If the user's cached credentials are valid, the OptionalPendingResult will be "done"
// and the GoogleSignInResult will be available instantly.
Log.d(TAG, " ---------------- CACHED SIGN-IN ------------");
System.out.println("pendingResult is done = ");
GoogleSignInResult signInResult = pendingResult.get();
onSilentLoginFinished(signInResult);
} else {
System.out.println("Setting result callback");
// If the user has not previously signed in on this device or the sign-in has expired,
// this asynchronous branch will attempt to sign in the user silently. Cross-device
// single sign-on will occur in this branch.
pendingResult.setResultCallback(new ResultCallback<GoogleSignInResult>() {
@Override
public void onResult(GoogleSignInResult googleSignInResult) {
System.out.println("googleSignInResult = " + googleSignInResult);
onSilentLoginFinished(googleSignInResult);
}
});
}
} else {
onSilentLoginFinished(null);
}
}
private void onSilentLoginFinished(GoogleSignInResult signInResult) {
System.out.println("GoogleLoginIdToken.onSilentLoginFinished");
if (signInResult != null) {
GoogleSignInAccount signInAccount = signInResult.getSignInAccount();
if (signInAccount != null) {
String emailAddress = signInAccount.getEmail();
String token = signInAccount.getIdToken();
System.out.println("token = " + token);
System.out.println("emailAddress = " + emailAddress);
}
}
}
}
最佳答案
是的,上面的答案是正确的。一般来说,任何 GoogleApiClient 都需要连接才能返回任何数据。 enableAutoManage 帮助您在 onStart()/onStop() 期间自动调用 connect()/disconnect()。如果不使用 autoManage,则需要手动 connect()。
更好的是,您应该在 finally block 中断开连接。
假设您不在 UI 线程上。
try {
ConnectionResult result = mGoogleApiClient.blockingConnect();
if (result.isSuccess()) {
GoogleSignInResult googleSignInResult =
Auth.GoogleSignInApi.silentSignIn(googleApiClient).await();
...
}
} finally {
mGoogleApiClient.disconnect();
}
此外,稍微清理一下您的代码:1. 从以下配置构建的 gso 与上面粘贴的代码相同:
GoogleSignInOptions gso =
new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestIdToken(SERVER_CLIENT_ID)
.requestEmail()
.build();
关于android - 使用 GoogleApiClient 静默登录以检索 token ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34900956/
我对 JavaScript/jQuery 和 Web 开发有点陌生。我当前的项目是为网站建立一个小型聊天室。一切正常,但我有一个问题: 如何将数据从客户端传输到服务器并返回(例如通过 javascri
warn 4 与 print STDERR 4 有何不同? perl -e 'local *STDERR; warn 4' (输出仍然转到 STDERR ) perl -e 'local *STDER
所以在面对可怕的javax.faces.application.ViewExpiredException之后,我不得不在互联网上寻找合适的解决方案。幸运的是,这些解决方案随时可用,我继续采用了 Omn
我正在尝试使用 Spring Modules 项目中的声明性缓存。 它不起作用,即。似乎没有任何东西被缓存。 这是我的配置:
我正在实现以下教程:Speech To Text 我正在使用 AVAudioEngine 和 SFSpeechRecognizer 录制音频实现语音到文本。此处教程使用以下方法将语音引导至文本一个开始
我有一个文本(有多行),需要将其放入 wxPython TextCtrl 中。 问题是其中一些行包含无法打印的字符。 我的解决方案是使用 AppendText,并 try catch 有问题的行。 当
有没有办法直接从 Angular/客户端应用程序使用“用户名”和“密码”登录? 例如像这样的东西? Keycloak.init({username: 'guest', password: 'abc'}
我这样执行 GET 请求: http://www.smurf.com/path/?var=val 这显示在用户的 URL 中。我当然在几乎每个主要网站上都看到了这一点。 但我只是好奇是否有办法绕过它。
假设我有两个相互硬链接(hard link)的文件: -rw-rw-r-- 2 mparrott grp 5 Jul 28 09:38 bar -rw-rw-r-- 2 mparrott grp 5
我想在 android 4+ 中以编程方式(直接)添加日历事件。这可以在模拟器上测试吗?我没有安卓手机。一些示例代码将不胜感激。我阅读了 android 开发人员的日历提供程序,但我很困惑。如何将事件
我正在向我的工作簿添加一个新工作表 Application.ScreenUpdating = False SheetExists = False For Each WS In Worksheets
我正在 Excel 中的 VBA 中进行一些网页解析;我是 MSHTML 来下载和解析网页。但是,在某些站点上,会弹出一个对话框。它工作正常;但是,我想知道是否有办法禁用它或可能绕过它。感谢您的时间。
有没有办法使用谷歌的 firebase 发送一个无声的 APNS? 似乎如果应用程序在后台,它总是会向用户显示通知。 谢谢? 最佳答案 您可以使用 FCM 服务器 API 发送静默 APNS 消息 h
我有一个 Powershell 脚本来放松机器上的执行策略,本质上是运行: Set-ExecutionPolicy Unrestricted -Force 由于 ExecutionPolicy 在机器
我有一个 Powershell 脚本,用于将我们的生产数据库复制到我们的测试环境以及相关的清理事件。我想清理为用户输出到控制台的信息,但在清理从 Az.sql 命令中收到的错误消息时遇到了问题。 我的
这是我当前的 Facebook 应用程序登录流程(有关解释,请参阅 this answer)。 logout() 和 login() 是在用户注销或登录时呈现页面的虚拟函数。 window.fbAsy
我有一个 React Native 应用程序,我正在尝试将静默的 iOS 推送通知发送到 JavaScript 中的处理程序。 我看到的行为是 AppDelegate 中的 didReceiveRem
我正在使用数据通知来更新我的应用程序状态,它在 Android 上运行完美,但我无法在 IOS 上接收到任何数据消息,甚至没有触发 onMessage 监听器。 我正在使用这些: firebase_c
我知道较新的 GCC 版本引入了可能错误的字符串操作“stringop-truncation”的警告 这是我可以轻松触发此警告的示例代码: $ cat strncpy-warning.cxx #inc
标题基本上描述了它。 我检查过的事情: 验证了远程 Powershell session 中的用户名(以确保事情正在以我期望的权限执行) 检查了所描述文件的权限。预期用户拥有文件的完全控制权 删除了
我是一名优秀的程序员,十分优秀!