In one of my Android applications I am trying to include One Tap sign-in authentication by following the example https://developers.google.com/identity/one-tap/android/get-saved-credentials#disable-one-tap. However, here https://developer.android.com/reference/androidx/activity/ComponentActivity#startActivityForResult(android.content.Intent,int) it says that the function startActivityForResult is deprecated and to use instead the function registerForActivityResult passing in a StartActivityForResult object for the ActivityResultContract. With the help of other examples, I could write the following code
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());
}
});
}
}
only I can't figure out how to convert the instruction loginResultHandler.launch(result.getPendingIntent().getIntentSender()) according to the Google Activity Result API (getIntentSender() returns an IntentSender but loginResultHandler.launch() requires an Intent). Would anyone be able to help me or link me working examples? Thank you.
EDIT: Finally, I rewrote the code in the following way (I have tested it up to the account selection screen and it works):
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());
}
});
}
}