在我的一个 Android 应用程序中,我试图按照示例 https://developers.google.com/identity/one-tap/android/get-saved-credentials#disable-one-tap 来包含一键登录身份验证。 .然而,这里https://developer.android.com/reference/androidx/activity/ComponentActivity#startActivityForResult(android.content.Intent,int)它说函数 startActivityForResult 已被弃用,而是使用函数 registerForActivityResult 传递 ActivityResultContract 的 StartActivityForResult 对象。借助其他示例,我可以编写以下代码
public class MainActivity extends AppCompatActivity {
private SignInClient oneTapClient;
private BeginSignInRequest signInRequest;
private ActivityResultLauncher<Intent> loginResultHandler = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
// handle intent result here
if (result.getResultCode() == RESULT_OK) {
SignInCredential credential = null;
try {
credential = oneTapClient.getSignInCredentialFromIntent(result.getData());
String idToken = credential.getGoogleIdToken();
String username = credential.getId();
String password = credential.getPassword();
if (idToken != null) {
// Got an ID token from Google. Use it to authenticate
// with your backend.
Log.d(TAG, "Got ID token.");
} else if (password != null) {
// Got a saved username and password. Use them to authenticate
// with your backend.
Log.d(TAG, "Got password.");
}
} catch (ApiException e) {
e.printStackTrace();
}
}
else {
//...
}
});
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//...
oneTapClient.beginSignIn(signInRequest)
.addOnSuccessListener(this, new OnSuccessListener<BeginSignInResult>() {
@Override
public void onSuccess(BeginSignInResult result) {
/*try {
android.app.Activity.startIntentSenderForResult(result.getPendingIntent().getIntentSender(), REQ_ONE_TAP,
null, 0, 0, 0);
} catch (IntentSender.SendIntentException e) {
Log.e(TAG, "Couldn't start One Tap UI: " + e.getLocalizedMessage());
}*/
loginResultHandler.launch(result.getPendingIntent().getIntentSender());
}
})
.addOnFailureListener(this, new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
// No saved credentials found. Launch the One Tap sign-up flow, or
// do nothing and continue presenting the signed-out UI.
Log.d(TAG, e.getLocalizedMessage());
}
});
}
}
只有我不知道如何根据 Google Activity Result API(getIntentSender() 返回一个 IntentSender 但 loginResultHandler.launch() 需要一个 Intent )。任何人都可以帮助我或将我的工作示例链接起来吗?谢谢。
编辑: 最后,我按照以下方式重写了代码(我已经测试到帐户选择屏幕并且可以运行):
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private SignInClient oneTapClient;
private BeginSignInRequest signInRequest;
private boolean showOneTapUI = true;
private ActivityResultLauncher<IntentSenderRequest> loginResultHandler = registerForActivityResult(new ActivityResultContracts.StartIntentSenderForResult(), result -> {
// handle intent result here
if (result.getResultCode() == RESULT_OK) Log.d(TAG, "RESULT_OK.");
if (result.getResultCode() == RESULT_CANCELED) Log.d(TAG, "RESULT_CANCELED.");
if (result.getResultCode() == RESULT_FIRST_USER) Log.d(TAG, "RESULT_FIRST_USER.");
try {
SignInCredential credential = oneTapClient.getSignInCredentialFromIntent(result.getData());
String idToken = credential.getGoogleIdToken();
String username = credential.getId();
String password = credential.getPassword();
if (idToken != null) {
// Got an ID token from Google. Use it to authenticate
// with your backend.
Log.d(TAG, "Got ID token.");
} else if (password != null) {
// Got a saved username and password. Use them to authenticate
// with your backend.
Log.d(TAG, "Got password.");
}
} catch (ApiException e) {
switch (e.getStatusCode()) {
case CommonStatusCodes.CANCELED:
Log.d(TAG, "One-tap dialog was closed.");
// Don't re-prompt the user.
showOneTapUI = false;
break;
case CommonStatusCodes.NETWORK_ERROR:
Log.d(TAG, "One-tap encountered a network error.");
// Try again or just ignore.
break;
default:
Log.d(TAG, "Couldn't get credential from result."
+ e.getLocalizedMessage());
break;
}
}
});
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//...
oneTapClient.beginSignIn(signInRequest)
.addOnSuccessListener(this, new OnSuccessListener<BeginSignInResult>() {
@Override
public void onSuccess(BeginSignInResult result) {
try {
loginResultHandler.launch(new IntentSenderRequest.Builder(result.getPendingIntent().getIntentSender()).build());
} catch(android.content.ActivityNotFoundException e){
e.printStackTrace();
Log.e(TAG, "Couldn't start One Tap UI: " + e.getLocalizedMessage());
}
}
})
.addOnFailureListener(this, new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
// No saved credentials found. Launch the One Tap sign-up flow, or
// do nothing and continue presenting the signed-out UI.
Log.d(TAG, e.getLocalizedMessage());
}
});
}
}
最佳答案
您可以使用 ActivityResultContracts.StartIntentSenderForResult
类而不是 ActivityResultContracts.StartActivityForResult
因此您可以将您的代码重构为这样的东西,
首先使用 ActivityResultLauncher<IntentSenderRequest>
定义将结果提供给您时将执行的操作实例而不是 ActivityResultLauncher<Intent>
实例
private ActivityResultLauncher<IntentSenderRequest> loginResultHandler = registerForActivityResult(new ActivityResultContracts.StartIntentSenderForResult(), result -> {
// handle intent result here
if (result.getResultCode() == RESULT_OK) {
SignInCredential credential = null;
try {
credential = oneTapClient.getSignInCredentialFromIntent(result.getData());
String idToken = credential.getGoogleIdToken();
String username = credential.getId();
String password = credential.getPassword();
if (idToken != null) {
// Got an ID token from Google. Use it to authenticate
// with your backend.
Log.d(TAG, "Got ID token.");
} else if (password != null) {
// Got a saved username and password. Use them to authenticate
// with your backend.
Log.d(TAG, "Got password.");
}
} catch (ApiException e) {
e.printStackTrace();
}
}
else {
//...
}
});
现在在您的 onCreate
中正如您在上面的代码中提到的,您可以使用 IntentSenderRequest.Builder
类转你的IntentSender
实例化为 IntentSenderRequest
将在 launch
中接受的实例方法
oneTapClient.beginSignIn(signInRequest)
.addOnSuccessListener(this, new OnSuccessListener<BeginSignInResult>() {
@Override
public void onSuccess(BeginSignInResult result) {
try{
loginResultHandler.launch(new IntentSenderRequest.Builder(result.getPendingIntent().getIntentSender()).build());
}catch(IntentSenderException e){
e.printStackTrace()
}
}
})
.addOnFailureListener(this, new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
// No saved credentials found. Launch the One Tap sign-up flow, or
// do nothing and continue presenting the signed-out UI.
Log.d(TAG, e.getLocalizedMessage());
}
});
}
确保将其包装在 try-catch
中构造,它应该是它。
刚刚发现这个answer在谷歌搜索时,它也可能对您有帮助
关于android - 如何在一键登录中使用 Google Activity Result API,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69212531/