Sorry for my bad english.
I want to combine these 2 methods
private void firebaseAuthWithGoogle(GoogleSignInAccount acct) {
Log.d(TAG, "firebaseAuthWithGoogle:" + acct.getId());
AuthCredential credential = GoogleAuthProvider.getCredential(acct.getIdToken(), null);
mAuth.signInWithCredential(credential)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
Log.d(TAG, "signInWithCredential:onComplete:" + task.isSuccessful());
// If sign in fails, display a message to the user. If sign in succeeds
// the auth state listener will be notified and logic to handle the
// signed in user can be handled in the listener.
if (!task.isSuccessful()) {
Log.w(TAG, "signInWithCredential", task.getException());
Toast.makeText(MainActivity.this, "Authentication failed.", Toast.LENGTH_SHORT).show();
}
}
});
}
private void firebaseAuthWithFacebook(AccessToken token) {
Log.d(TAG, "handleFacebookAccessToken:" + token);
AuthCredential credential = FacebookAuthProvider.getCredential(token.getToken());
mAuth.signInWithCredential(credential)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
Log.d(TAG, "signInWithCredential:onComplete:" + task.isSuccessful());
// If sign in fails, display a message to the user. If sign in succeeds
// the auth state listener will be notified and logic to handle the
// signed in user can be handled in the listener.
if (!task.isSuccessful()) {
Log.w(TAG, "signInWithCredential", task.getException());
Toast.makeText(MainActivity.this, "Authentication failed.",
Toast.LENGTH_SHORT).show();
}
// ...
}
});
}
Only this line change
AuthCredential credential = GoogleAuthProvider.getCredential(acct.getIdToken(), null);
FacebookAuthProvider.getCredential(token.getToken());
I take this from FireBase documentation.
I am new on Android Programmation (I'm little C# game dev) so don't blame me.
And I don't enderstind this :https://firebase.google.com/docs/auth/android/account-linking#link-auth-provider-credentials-to-a-user-account
Please can I Have Help ?
Thank's in advance.
You can add both parameters acct and token in one method and check if each of them is null like this private void firebaseAuth(GoogleSignInAccount acct,AccessToken token).If acct is null then the user should be sign in using facebook Given that you checked that the request code is the one you provide when you sign in using Google in OnActivityResult(int requestCode, int resultCode, Intent data) and the result you got from Auth.GoogleSignInApi.getSignInResultFromIntent(data) is result.isSuccess().Same for Facebook as you pass the AccessToken from onSuccess() method of the FacebookCallback<LoginResult>() so you may do some thing like this:
CallbackManager mCallbackManager = CallbackManager.Factory.create();
LoginManager.getInstance().registerCallback(mCallbackManager,
new FacebookCallback<LoginResult>() {
#Override
public void onSuccess(LoginResult loginResult) {
Log.d(TAG, "facebook:onSuccess:" + loginResult);
firebaseAuth(null,loginResult.getAccessToken);
//null here is the google account as you sign in using facebook
}
#Override
public void onCancel() {
//Something to do with user cancel login
}
#Override
public void onError(FacebookException error) {
//Something to do with FacebookException
}
});
and in case of Google Sign in :
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...);
if (requestCode == GOOGLE_SIGN_IN) {
/* request code you pass to
* startActivityForResult(intent, GOOGLE_SIGN_IN)
* where intent is what you get from intent =
* Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient)
*/
GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
if (result.isSuccess()) {
// Google Sign In was successful, authenticate with Firebase
GoogleSignInAccount account = result.getSignInAccount();
firebaseAuth(account,null);
/* null here is the facebook token
* as you sign in using Google
*/
} else if(result.getStatus().isInterrupted()){
// Google Sign In failed, update UI appropriately
}
}
}
Related
I have tried to use this however the recommended does not do anything:
Fitness.getConfigClient(this, GoogleSignIn.getLastSignedInAccount(this)).disableFit()
How I authenticate with Google:
if (!GoogleSignIn.hasPermissions(GoogleSignIn.getLastSignedInAccount(this), fitnessOptions)) {
GoogleSignIn.requestPermissions(this, REQUEST_OAUTH_REQUEST_CODE,
GoogleSignIn.getLastSignedInAccount(this),
fitnessOptions);
} else {
subscribe();
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == Activity.RESULT_OK) {
if (requestCode == REQUEST_OAUTH_REQUEST_CODE) {
subscribe();
}
}
}
public void subscribe() {
Fitness.getRecordingClient(this, GoogleSignIn.getLastSignedInAccount(this))
.subscribe(DataType.TYPE_STEP_COUNT_CUMULATIVE)
.addOnCompleteListener(
new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
Log.i(TAG, "Successfully subscribed!");
} else {
Log.w(TAG, "There was a problem subscribing.", task.getException());
}
}
});
}
I need to be able to get the google account which was last signed in and provide an option to the user to sign out of their google account.
For disconnecting Google account from your app you should use signOut method from GoogleSignIn which will preserve granted permissions or you can use revokeAccess method to do both signing out and revoke granted permissions:
val options = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.addExtension(getFitnessOptions())
.requestProfile()
.build()
GoogleSignIn.getClient(this, options).signOut() // or GoogleSignIn.getClient(this, options).revokeAccess()
i created a standard login and signup page and i added an alternative to sign in with a google account using the custom GogleSignInButton.
The button works welll. am able to select a google account and sign in but the credentials do not reflect in the firebase authentication console nor does it bring up the signup activity for new users like it does when using the standard firebase UI.
I already have a working login with email and password(if it helps).
I would like help in immplementing the storage of credentials and signing up new users with google accounts.
From the image below you can see there are no gmail accounts
SignInButton signInButton = findViewById(R.id.sign_in_button);
signInButton.setSize(SignInButton.SIZE_STANDARD);
GoogleSignInOptions gso = new
GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestEmail()
.build();
mGoogleSignInClient = GoogleSignIn.getClient(this, gso);
if (mAuth.getCurrentUser() != null) {
startActivity(new Intent(LoginActivity.this,
MainActivity.class));
finish();
}
signInButton.setOnClickListener(this);
private void signIn() {
Intent signInIntent = mGoogleSignInClient.getSignInIntent();
startActivityForResult(signInIntent, RC_SIGN_IN);
}
#Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.sign_in_button:
signIn();
break;
}
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...);
if (requestCode == RC_SIGN_IN) {
Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data);
handleSignInResult(task);
}
}
private void handleSignInResult(Task<GoogleSignInAccount> completedTask) {
try {
GoogleSignInAccount account = completedTask.getResult(ApiException.class);
// Signed in successfully, show authenticated UI.
startActivity(new Intent(LoginActivity.this,MainActivity.class));
} catch (ApiException e) {
// The ApiException status code indicates the detailed failure reason.
// Please refer to the GoogleSignInStatusCodes class reference for more information.
Log.w(TAG, "signInResult:failed code=" + e.getStatusCode());
Toast.makeText(this, "Authentication Failed", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onStart() {
// Check if user is signed in (non-null) and update UI accordingly.
GoogleSignInAccount account = GoogleSignIn.getLastSignedInAccount(this);
if(account != null) {
startActivity(new Intent(LoginActivity.this,MainActivity.class));
}
super.onStart();
}
I am using Firebase in my android app. I use Facebook button to sign in in the app. when I press the sign in button it writes on the button logout which means that the button has signed in successfully but no thing happens from the things I wrote them in onSuccess method. I put toasts in all methods of the Facebook login but none of them appears at all.
This is my handleFacebookLogin method :
private void handleFacebookAccessToken(AccessToken token) {
Log.d(TAG, "handleFacebookAccessToken:" + token);
AuthCredential credential = FacebookAuthProvider.getCredential(token.getToken());
mAuth.signInWithCredential(credential)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
// Sign in success, update UI with the signed-in user's information
Log.d(TAG, "signInWithCredential:success");
Toast.makeText(GeneralSignActivity.this, "نجح تسجيل الدخول", Toast.LENGTH_SHORT).show();
FirebaseUser user = mAuth.getCurrentUser();
//updateUI(user);
} else {
// If sign in fails, display a message to the user.
Log.w(TAG, "signInWithCredential:failure",
task.getException());
Toast.makeText(GeneralSignActivity.this, "Authentication failed.",
Toast.LENGTH_SHORT).show();
//updateUI(null);
}
// ...
}
});
}
And this is the code of the button:
mCallbackManager = CallbackManager.Factory.create();
LoginButton loginButton = findViewById(R.id.facebookBtn);
loginButton.setReadPermissions("email", "public_profile");
loginButton.registerCallback(mCallbackManager, new FacebookCallback<LoginResult>() {
#Override
public void onSuccess(LoginResult loginResult) {
Log.d(TAG, "facebook:onSuccess:" + loginResult);
Toast.makeText(GeneralSignActivity.this, "onSuccess" + loginResult, Toast.LENGTH_SHORT).show();
handleFacebookAccessToken(loginResult.getAccessToken());
}
#Override
public void onCancel() {
Log.d(TAG, "facebook:onCancel");
Toast.makeText(GeneralSignActivity.this, "onCancel" , Toast.LENGTH_SHORT).show();
// ...
}
#Override
public void onError(FacebookException error) {
Log.d(TAG, "facebook:onError", error);
Toast.makeText(GeneralSignActivity.this, "onError : " + error, Toast.LENGTH_SHORT).show();
// ...
}
});
I am using firebase auth UI (FirebaseUI-Android) in an android app, where the user can signup with personal email, Facebook, number and Gmail accounts. My question is I need to get email verification when user sign's up with his personal email id.
List<AuthUI.IdpConfig> providers = Arrays.asList(
new AuthUI.IdpConfig.Builder(AuthUI.EMAIL_PROVIDER).build(),
new AuthUI.IdpConfig.Builder(AuthUI.PHONE_VERIFICATION_PROVIDER).build(),
new AuthUI.IdpConfig.Builder(AuthUI.FACEBOOK_PROVIDER).build(),
new AuthUI.IdpConfig.Builder(AuthUI.GOOGLE_PROVIDER).build());
startActivityForResult(
AuthUI.getInstance()
.createSignInIntentBuilder()
.setIsSmartLockEnabled(true)
.setTheme(R.style.GreenTheme)
.setTosUrl("https://termsfeed.com/blog/terms-conditions-mobile-apps/")
.setPrivacyPolicyUrl("https://superapp.example.com/privacy-policy.html")
.setAvailableProviders(providers)
.build(),
RC_SIGN_IN);
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// RC_SIGN_IN is the request code you passed into startActivityForResult(...) when starting the sign in flow.
if (requestCode == RC_SIGN_IN) {
IdpResponse response = IdpResponse.fromResultIntent(data);
// Successfully signed in
if (resultCode == RESULT_OK) {
startActivity(new Intent(Login.this,MainActivity.class));
finish();
return;
} else {
// Sign in failed
if (response == null) {
Toasty.error(getApplicationContext(),"Sign in cancelled",Toast.LENGTH_SHORT, true).show();
return;
}
if (response.getErrorCode() == ErrorCodes.NO_NETWORK) {
Toasty.error(getApplicationContext(),"No internet connection",Toast.LENGTH_SHORT, true).show();
return;
}
if (response.getErrorCode() == ErrorCodes.UNKNOWN_ERROR) {
Toasty.error(getApplicationContext(),"Unkown Error",Toast.LENGTH_SHORT, true).show();
return;
}
}
Toasty.error(getApplicationContext(),"Unknown sign in response",Toast.LENGTH_SHORT, true).show();
}
}
Here is my intent for sign up options.
You can simply do it as follows,
Get Current Firebase User Instance,
final FirebaseUser currentUser = mAuth.getCurrentUser();
Check if the provider is password indicating that the login method used is Email Auth,
if(null != currentUser) {
if("password".equals(currentUser.getProviderData().get(0).getProviderId())) {
/* Handle Verification */
}
}
Reference Link: https://firebase.google.com/docs/reference/android/com/google/firebase/auth/EmailAuthProvider#PROVIDER_ID
Check if user is already verified,
currentUser.isEmailVerified();
If user is not verified then the following code can be used to send a verification EMail,
if (!currentUser.isEmailVerified()) {
/* Do Something */
}
/* Send Verification Email */
currentUser.sendEmailVerification()
.addOnCompleteListener(this, new OnCompleteListener() {
#Override
public void onComplete(#NonNull Task task) {
/* Check Success */
if (task.isSuccessful()) {
Toast.makeText(getApplicationContext(),
"Verification Email Sent To: " + currentUser.getEmail(),
Toast.LENGTH_SHORT).show();
} else {
Log.e(TAG, "sendEmailVerification", task.getException());
Toast.makeText(getApplicationContext(),
"Failed To Send Verification Email!",
Toast.LENGTH_SHORT).show();
}
}
});
Once you have all the pieces in place, the final code snippet should look something like below:
Final Code Snippet:
if (requestCode == RC_SIGN_IN) {
IdpResponse response = IdpResponse.fromResultIntent(data);
/* Success */
if (resultCode == RESULT_OK) {
final FirebaseUser currentUser = mAuth.getCurrentUser();
if(null != currentUser) {
if("password".equals(currentUser.getProviderData().get(0).getProviderId())) {
if(!currentUser.isEmailVerified()) {
/* Send Verification Email */
currentUser.sendEmailVerification()
.addOnCompleteListener(this, new OnCompleteListener() {
#Override
public void onComplete(#NonNull Task task) {
/* Check Success */
if (task.isSuccessful()) {
Toast.makeText(getApplicationContext(),
"Verification Email Sent To: " + currentUser.getEmail(),
Toast.LENGTH_SHORT).show();
} else {
Log.e(TAG, "sendEmailVerification", task.getException());
Toast.makeText(getApplicationContext(),
"Failed To Send Verification Email!",
Toast.LENGTH_SHORT).show();
}
}
});
/* Handle Case When Email Not Verified */
}
}
/* Login Success */
startActivity(new Intent(Login.this, MainActivity.class));
finish();
return;
}
} else {
/* Handle Failure */
}
}
#user2004685 answer above gives very good hint. But it does not work at least for the latest firebase-ui because currentUser.getProviderData().get(0).getProviderId() returns 'firebase'.
So the updated solution is
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == RC_SIGN_IN) {
IdpResponse response = IdpResponse.fromResultIntent(data);
/* Success */
if (resultCode == RESULT_OK) {
final FirebaseUser currentUser = mAuth.getCurrentUser();
if(null != currentUser) {
if(currentUser.getEmail()!=null) {
if(!currentUser.isEmailVerified()) {
/* Send Verification Email */
currentUser.sendEmailVerification()
.addOnCompleteListener(this, new OnCompleteListener() {
#Override
public void onComplete(#NonNull Task task) {
/* Check Success */
if (task.isSuccessful()) {
Toast.makeText(getApplicationContext(),
"Verification Email Sent To: " + currentUser.getEmail(),
Toast.LENGTH_SHORT).show();
} else {
Log.e(TAG, "sendEmailVerification", task.getException());
Toast.makeText(getApplicationContext(),
"Failed To Send Verification Email!",
Toast.LENGTH_SHORT).show();
}
}
});
/* Handle Case When Email Not Verified */
}
}
/* Login Success */
startActivity(new Intent(Login.this, MainActivity.class));
finish();
return;
}
} else {
/* Handle Failure */
}
}
}
simply replace if("password".equals(currentUser.getProviderData().get(0).getProviderId())) with if(currentUser.getEmail()!=null)
I have made a login activity using firebase to connect with google. The user can login without problems Now I want to show a leaderboard on another activity however, when I check if the user is logged in and I try to show the leaderboard I get the error:
E/UncaughtException: java.lang.IllegalStateException: GoogleApiClient
must be connected.
How can I connect GoogleApiClient using firebase? I have tried using mGoogleApiClient.connect(GoogleApiClient.SIGN_IN_MODE_OPTIONAL); but this also does not work.
here my code:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_achievements);
// Configure Google Sign In
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestIdToken(getString(R.string.default_web_client_id))
.requestEmail()
.build();
mGoogleApiClient = new GoogleApiClient.Builder(this)
.enableAutoManage(this, new GoogleApiClient.OnConnectionFailedListener() {
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
// connection failed, should be handled
}
})
.addApi(Auth.GOOGLE_SIGN_IN_API, gso)
.build();
mAuth = FirebaseAuth.getInstance();
mAuthListener = new FirebaseAuth.AuthStateListener() {
#Override
public void onAuthStateChanged(#NonNull FirebaseAuth firebaseAuth) {
FirebaseUser user = firebaseAuth.getCurrentUser();
if (user != null) {
// User is signed in
Log.d(TAG, "onAuthStateChanged:signed_in:" + user.getUid());
////// is crashing googleapiclient not connected
startActivityForResult(Games.Leaderboards.getLeaderboardIntent(mGoogleApiClient,
getString(R.string.leaderboard_la_classifica)), REQUEST_LEADERBOARD);
} else {
// User is signed out
}
// ...
}
};
}
See https://firebase.google.com/docs/auth/android/google-signin for more details.
When building the client, you need to use GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_firebase_games_signin);
String webclientId = getString(R.string.web_client_id);
GoogleSignInOptions options =
new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN)
.requestServerAuthCode(webclientId)
.requestEmail()
.requestIdToken()
.build();
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(Games.API).addScope(Games.SCOPE_GAMES)
.addApi(Auth.GOOGLE_SIGN_IN_API, options)
.addConnectionCallbacks(this)
.build();
}
Then to start the explicit sign-in start the signIn Intent:
private void signIn() {
Intent signInIntent =
Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
startActivityForResult(signInIntent, RC_SIGN_IN);
}
You should also use an automanaged client, or simply call mGoogleApiClient.connect(GoogleApiClient.SIGN_IN_MODE_OPTIONAL); in onStart() and disconnect in onStop().
In onActivityResult, handle the result of the explicit sign-in intent:
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...);
if (requestCode == RC_SIGN_IN) {
GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
if (result.isSuccess()) {
// Google Sign In was successful, authenticate with Firebase
GoogleSignInAccount acct = result.getSignInAccount();
completeFirebaseAuth(acct);
// At this point, the Games API can be called.
} else {
// Google Sign In failed, update UI appropriately
// ...
}
}
}
Completing the Firebase authentication:
private void completeFirebaseAuth(GoogleSignInAccount acct) {
AuthCredential credential = GoogleAuthProvider.getCredential(acct.getIdToken(), null);
FirebaseAuth mAuth = FirebaseAuth.getInstance();
mAuth.signInWithCredential(credential)
.addOnCompleteListener(this, new
OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
Log.d(TAG, "signInWithCredential:onComplete:" + task.isSuccessful());
// If sign in fails, display a message to the user. If sign in succeeds
// the auth state listener will be notified and logic to handle the
// signed in user can be handled in the listener.
if (!task.isSuccessful()) {
Log.w(TAG, "signInWithCredential", task.getException());
}
// ...
}
});
}
The other situation you need to handle is the silent sign-in, which happens when resuming an app:
#Override
public void onConnected(#Nullable Bundle bundle) {
// Handle the silent sign-in case.
if (mGoogleApiClient.hasConnectedApi(Games.API)) {
Auth.GoogleSignInApi.silentSignIn(mGoogleApiClient).setResultCallback(
new ResultCallback<GoogleSignInResult>() {
#Override
public void onResult(
#NonNull GoogleSignInResult googleSignInResult) {
if (googleSignInResult.isSuccess()) {
completePlayGamesAuth(
googleSignInResult.getSignInAccount());
} else {
Log.e(TAG, "Error with silentSignIn: " +
googleSignInResult.getStatus());
}
}
}
);
}
}