I am completely new to aws cognito, and these guides are all over the place and i am kind of lost. In my aws account i have made an identity pool, and now i want to try to create a new user from my android app, but it fails to create user or fails to connect to the cognito pool. I am not sure if i am doing this write and hope for your guidance!
Here is what i have so far.
public class aws extends AppCompatActivity
{
private EditText firstName,lastName,email,password;
private Button loginButton;
private String poolId,clientId,clientSecret;
CognitoUserPool userPool;
CognitoUserAttributes userAttributes;
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_register);
CognitoCachingCredentialsProvider credentialsProvider = new
CognitoCachingCredentialsProvider(
getApplicationContext(), // Context
"IDENTITY POOL_ID", // Identity Pool ID
MY_REGION // Region
);
CognitoSyncManager syncClient = new CognitoSyncManager(
getApplicationContext(), // Context
MY_REGION, // Region
credentialsProvider
);
Dataset dataset = syncClient.openOrCreateDataset("myDataset");
dataset.put("myKey", "myValue");
dataset.synchronize(new DefaultSyncCallback() {
#Override
public void onSuccess(Dataset dataset, List newRecords) {
//Your handler code here
}
});
poolId = "MY_POOL_ID";
clientId = "MY_CLIENT_ID";
clientSecret = "MY_CLIENT_SECRET";
ClientConfiguration clientConfiguration = new ClientConfiguration();
// Create a CognitoUserPool object to refer to your user pool
userPool = new CognitoUserPool(getBaseContext(), poolId, clientId, clientSecret, clientConfiguration);
bindActivity();
}
private void bindActivity()
{
firstName = (EditText) findViewById(R.id.register_firstNameET);
lastName = (EditText) findViewById(R.id.register_lastNameET);
email = (EditText) findViewById(R.id.register_emailET);
password = (EditText) findViewById(R.id.register_passwordET);
loginButton = (Button) findViewById(R.id.intro_register_zivit_button);
loginButton.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
setUpCognito();
}
});
}
private void setUpCognito()
{
// Create a CognitoUserAttributes object and add user attributes
userAttributes = new CognitoUserAttributes();
// Add the user attributes. Attributes are added as key-value pairs
// Adding user's given name.
// Note that the key is "given_name" which is the OIDC claim for given name
userAttributes.addAttribute("given_name", firstName.getText().toString());
// Adding user's lastName
userAttributes.addAttribute("family_Name", lastName.getText().toString());
// Adding user's email address
userAttributes.addAttribute("email", email.getText().toString());
setUpCognitoHandler();
}
private void setUpCognitoHandler()
{
SignUpHandler signupCallback = new SignUpHandler() {
#Override
public void onSuccess(CognitoUser cognitoUser, boolean userConfirmed, CognitoUserCodeDeliveryDetails cognitoUserCodeDeliveryDetails)
{
Log.d("myCognito","sign up succeeded!");
// Sign-up was successful
// Check if this user (cognitoUser) needs to be confirmed
if(!userConfirmed)
{
Log.d("myCognito","not confirmed! Need to confirm");
confirmUser();
// This user must be confirmed and a confirmation code was sent to the user
// cognitoUserCodeDeliveryDetails will indicate where the confirmation code was sent
// Get the confirmation code from user
}
else {
Log.d("myCognito","confirmed!");
// The user has already been confirmed
}
}
#Override
public void onFailure(Exception exception)
{
Log.d("myCognito","sign up failed!");
// Sign-up failed, check exception for the cause
}
};
userPool.signUpInBackground("user1ID", password.getText().toString(), userAttributes, null, signupCallback);
}
private void confirmUser()
{
// Callback handler for confirmSignUp API
GenericHandler confirmationCallback = new GenericHandler() {
#Override
public void onSuccess() {
// User was successfully confirmed
Log.d("myCognito","Confirmed User Success!");
}
#Override
public void onFailure(Exception exception) {
// User confirmation failed. Check exception for the cause.
Log.d("myCognito","Confirmed User faileure :(");
}
};
}
}
Again im really confused on how to make this class, when i used mobile hub, the code was all over the place in the sample app.
Try this Document Amazon Cognito Credentials Provider
In Mobile hub look for this file CognitoUserPoolsSignInProvider
It has all the details how the sign in works
Below is the Authenctication Handler (I have commented few things to remove errors)
private AuthenticationHandler authenticationHandler = new AuthenticationHandler() {
#Override
public void onSuccess(final CognitoUserSession userSession, final CognitoDevice newDevice) {
Log.i(LOG_TAG, "Logged in. " + userSession.getIdToken());
cognitoUserSession = userSession;
if (null != resultsHandler) {
ViewHelper.showDialog(activity, activity.getString(title_activity_sign_in),
activity.getString(login_success) + " " + userSession.getIdToken());
resultsHandler.onSuccess(CognitoUserPoolsSignInProvider.this);
}
initializedLatch.countDown();
}
#Override
public void getAuthenticationDetails(
final AuthenticationContinuation authenticationContinuation, final String userId) {
if (null != username && null != password) {
final AuthenticationDetails authenticationDetails = new AuthenticationDetails(
username,
password,
null);
authenticationContinuation.setAuthenticationDetails(authenticationDetails);
authenticationContinuation.continueTask();
}
initializedLatch.countDown();
}
#Override
public void getMFACode(final MultiFactorAuthenticationContinuation continuation) {
multiFactorAuthenticationContinuation = continuation;
//todo uncomment it
/* final Intent intent = new Intent(context, MFAActivity.class);
activity.startActivityForResult(intent, MFA_REQUEST_CODE);*/
}
#Override
public void authenticationChallenge(final ChallengeContinuation continuation) {
throw new UnsupportedOperationException("Not supported in this sample.");
}
#Override
public void onFailure(final Exception exception) {
Log.e(LOG_TAG, "Failed to login.", exception);
if (null != resultsHandler) {
ViewHelper.showDialog(activity, activity.getString(R.string.title_activity_sign_in),
"Failed" + " " + exception);
// activity.getString( //todo uncomment it) + " " + exception);
resultsHandler.onError(CognitoUserPoolsSignInProvider.this, exception);
}
initializedLatch.countDown();
}
};
This is the onClick Listener
#Override
public View.OnClickListener initializeSignInButton(final Activity signInActivity,
final View buttonView,
final IdentityManager.SignInResultsHandler resultsHandler) {
this.activity = signInActivity;
this.resultsHandler = resultsHandler;
// User Pools requires sign in with the username or verified channel.
// Mobile Hub does not set up email verification because it requires SES verification.
// Hence, prompt customers to login using the username or phone number.
final EditText emailField = (EditText) activity.findViewById(EDIT_TEXT_USERNAME_ID);
emailField.setHint(R.string.button_text_sign_in);
final View.OnClickListener listener = new View.OnClickListener() {
#Override
public void onClick(View v) {
username = ViewHelper.getStringValue(activity, EDIT_TEXT_USERNAME_ID);
password = ViewHelper.getStringValue(activity, EDIT_TEXT_PASSWORD_ID);
final CognitoUser cognitoUser = cognitoUserPool.getUser(username);
cognitoUser.getSessionInBackground(authenticationHandler);
}
};
buttonView.setOnClickListener(listener);
return listener;
}
Related
I created a connection by phone number, all works very well. My only problem is that the number does not appear in the IDs on firebase.
With google auth it works very well but no with phone auth. I probably forgot something, but I can't find it.
Do you have an idea?
On firebase and gmail ID :
My activity auth phone:
public class Activity_aunth_phone extends AppCompatActivity {
EditText numero;
String verificationId;
FirebaseAuth mAuth;
Button button;
EditText cp;
private static final String TAG = "PhoneAuthActivity";
private static final String KEY_VERIFY_IN_PROGRESS = "key_verify_in_progress";
private static final int STATE_INTIALIZED = 1;
private static final int STATE_CODE_SEND = 2;
private static final int STATE_VERIFY_FAILED = 3;
private static final int STATE_VERIFY_SUCCES = 4;
private static final int STATE_SIGNIN_FAILED = 5;
private static final int STATE_SIGNIN_SUCCES = 6;
private FirebaseAuth auth;
private boolean mVerificationInProgress = false;
private String mVerificationId;
private PhoneAuthProvider.ForceResendingToken mResendToken;
private PhoneAuthProvider.OnVerificationStateChangedCallbacks mCallbacks;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_aunth_phone);
cp = findViewById(R.id.cp);
numero = (EditText) findViewById(R.id.num);
button = findViewById(R.id.button);
auth = FirebaseAuth.getInstance();
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
attemptLogin();
}
});
mCallbacks = new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
#Override
public void onVerificationCompleted(PhoneAuthCredential credential) {
// This callback will be invoked in two situations:
// 1 - Instant verification. In some cases the phone number can be instantly
// verified without needing to send or enter a verification code.
// 2 - Auto-retrieval. On some devices Google Play services can automatically
// detect the incoming verification SMS and perform verification without
// user action.
Log.d(TAG, "onVerificationCompleted:" + credential);
signInWithPhoneAuthCredential(credential);
}
#Override
public void onVerificationFailed(FirebaseException e) {
// This callback is invoked in an invalid request for verification is made,
// for instance if the the phone number format is not valid.
Log.w(TAG, "onVerificationFailed", e);
if (e instanceof FirebaseAuthInvalidCredentialsException) {
// Invalid request
// ...
} else if (e instanceof FirebaseTooManyRequestsException) {
// The SMS quota for the project has been exceeded
// ...
}
// Show a message and update the UI
// ...
}
#Override
public void onCodeSent(String verificationId,
PhoneAuthProvider.ForceResendingToken token) {
// The SMS verification code has been sent to the provided phone number, we
// now need to ask the user to enter the code and then construct a credential
// by combining the code with a verification ID.
Log.d(TAG, "onCodeSent:" + verificationId);
// Save verification ID and resending token so we can use them later
mVerificationId = verificationId;
mResendToken = token;
// ...
}
};
}
private void attemptLogin() {
numero.setError(null);
String cpp = cp.getText().toString();
String number = numero.getText().toString();
String phone = cpp + number;
startPhoneNumberVerification(phone);
boolean cancel = false;
View focusView = null;
if (!isPhoneValid(phone)) {
focusView = numero;
cancel = true;
}
if (cancel) {
focusView.requestFocus();
} else {
startPhoneNumberVerification(phone);
}
}
private boolean isPhoneValid(String phone){
return phone.length() > 8;
}
private void startPhoneNumberVerification(String phoneNumber) {
PhoneAuthProvider.getInstance().verifyPhoneNumber(
phoneNumber,
60,
TimeUnit.SECONDS,
this,
mCallbacks);
mVerificationInProgress = true;
}
private void signInWithPhoneAuthCredential(PhoneAuthCredential credential) {
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");
Intent intent = new Intent(Activity_aunth_phone.this, Activity_profile.class);
startActivity(intent);
FirebaseUser user = task.getResult().getUser();
// ...
} else {
// Sign in failed, display a message and update the UI
Log.w(TAG, "signInWithCredential:failure", task.getException());
if (task.getException() instanceof FirebaseAuthInvalidCredentialsException) {
// The verification code entered was invalid
}
}
}
});
}
}
You forgot to put the Code :
private void verifyPhoneNumberWithCode(String verificationId, String code) {
PhoneAuthCredential credential = PhoneAuthProvider.getCredential(mVerificationId, code); // Just Pass the otp in Code Section.
signInWithPhoneAuthCredential(credential);
}
Which provide credentials to new User.
Please Check this link : https://firebase.google.com/docs/auth/android/phone-auth?authuser=1#create-a-phoneauthcredential-object
I am new to Android development. I am not getting OTP message from Fire base but if I enter the code manually then it works. I am not sure why I am not getting text message. Your help is highly appreciated. I am not sure whether I am doing correctly sendVerificationcode method correctly or not.
Steps Completed:
1) I added GSON file to app directory
2) I added test phone number in the firebase console
3) I added SHA1 code to fire base
4) I added SMS permission in the Android manifest file.
5) I enabled firebase authentication in Android studio
6) I tried different phone numbers too
VerifyPhoneActivity.java
public class VerifyPhoneActivity extends AppCompatActivity {
private String verificationId;
private FirebaseAuth mAuth;
private ProgressBar progressBar;
private EditText editText;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_verify_phone);
mAuth = FirebaseAuth.getInstance();
progressBar = findViewById(R.id.progressbar);
editText = findViewById(R.id.editTextCode);
String phonenumber = getIntent().getStringExtra("phonenumber");
sendVerificationCode(phonenumber);
findViewById(R.id.buttonSignIn).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String code = editText.getText().toString().trim();
if (code.isEmpty() || code.length() < 6) {
editText.setError("Enter code...");
editText.requestFocus();
return;
}
verifyCode(code);
}
});
}
private void verifyCode(String code) {
PhoneAuthCredential credential = PhoneAuthProvider.getCredential(verificationId, code);
signInWithCredential(credential);
}
private void signInWithCredential(PhoneAuthCredential credential) {
// private void signInWithCredential(PhoneAuthCredential) {
mAuth.signInWithCredential(credential)
.addOnCompleteListener(new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
Intent intent = new Intent(VerifyPhoneActivity.this, ProfileActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
} else {
Toast.makeText(VerifyPhoneActivity.this, task.getException().getMessage(), Toast.LENGTH_LONG).show();
}
}
});
}
private void sendVerificationCode(String number) {
progressBar.setVisibility(View.VISIBLE);
PhoneAuthProvider.getInstance().verifyPhoneNumber(
number,
60,
TimeUnit.SECONDS,
TaskExecutors.MAIN_THREAD,
mCallBack
);
}
private PhoneAuthProvider.OnVerificationStateChangedCallbacks
mCallBack = new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
#Override
public void onCodeSent(String s, PhoneAuthProvider.ForceResendingToken forceResendingToken) {
super.onCodeSent(s, forceResendingToken);
verificationId = s;
}
#Override
public void onVerificationCompleted(PhoneAuthCredential phoneAuthCredential) {
String code = phoneAuthCredential.getSmsCode();
if (code != null) {
editText.setText(code);
verifyCode(code);
}
System.out.println("Hello Phone Number"+code);
}
#Override
public void onVerificationFailed(FirebaseException e) {
Toast.makeText(VerifyPhoneActivity.this, e.getMessage(), Toast.LENGTH_LONG).show();
}
};
}
Below code looks like not working:
#Override
public void onVerificationCompleted(PhoneAuthCredential phoneAuthCredential) {
String code = phoneAuthCredential.getSmsCode();
// String code="000000";
if (code != null) {
editText.setText(code);
verifyCode(code);
}
System.out.println("Hello Phone Number2"+code);
}
Use like this following:
onCreate
mAuth = FirebaseAuth.getInstance();
mCallbacks = new PhoneAuthProvider.OnVerificationStateChangedCallbacks()
{
#Override
public void onVerificationCompleted(PhoneAuthCredential credential)
{
// This callback will be invoked in two situations:
// 1 - Instant verification. In some cases the phone number can be instantly
// verified without needing to send or enter a verification code.
// 2 - Auto-retrieval. On some devices Google Play services can automatically
// detect the incoming verification SMS and perform verificaiton without
// user action.
Log.d(TAG, "onVerificationCompleted:" + credential);
Log.e("number","credential=-=-=>>><<>>>signInWithPhoneAuthCredential-->>");
signInWithPhoneAuthCredential(credential);
}
#Override
public void onVerificationFailed(FirebaseException e)
{
// This callback is invoked in an invalid request for verification is made,
// for instance if the the phone number format is not valid.
Log.e(TAG, "onVerificationFailed", e);
// Show a message and update the UI
// ...
}
#Override
public void onCodeSent(String verificationId,
PhoneAuthProvider.ForceResendingToken token)
{
// The SMS verification code has been sent to the provided phone number, we
// now need to ask the user to enter the code and then construct a credential
// by combining the code with a verification ID.
Log.e(TAG, "onCodeSent:" + verificationId+"<<token>>"+token);
// Save verification ID and resending token so we can use them later
mVerificationId = verificationId;
//mResendToken = token;
// ...
}
};
//String phoneNumber=Settings.PREFIX + Settings.PREFIX_PHONE;
String phoneNumber="your phone number with prefix";
Log.e("number","credential=-=-=>>>22222>>"+phoneNumber);
if(phoneNumber!=null && !phoneNumber.isEmpty())
{
startPhoneNumberVerification(phoneNumber);
}
Method:
private void startPhoneNumberVerification(String phoneNumber)
{
Log.e("startPhoneNumber","startPhoneNumberVerification------>>"+phoneNumber);
PhoneAuthProvider.getInstance().verifyPhoneNumber(
phoneNumber, // Phone number to verify
60, // Timeout duration
TimeUnit.SECONDS, // Unit of timeout
this, // Activity (for callback binding)
mCallbacks); // OnVerificationStateChangedCallbacks
Log.e("startPhoneNumber","startPhoneNumberVerification--2222222---->>"+phoneNumber);
}
Method:
private void signInWithPhoneAuthCredential(PhoneAuthCredential credential)
{
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.e(TAG, "signInWithCredential:success");
} else
{
// Sign in failed, display a message and update the UI
Log.e(TAG, "signInWithCredential:failure", task.getException());
if (task.getException() instanceof FirebaseAuthInvalidCredentialsException)
{
}
}
}
});
}
I am trying to build an Android App with Amazon Cognito authentication but don't want to use the default AuthUI for logging in users.
But, I couldn't find any references, samples, examples, blogs as to how this can be done.
I tried to follow the manuals here at https://docs.aws.amazon.com/aws-mobile/latest/developerguide/tutorial-android-aws-mobile-notes-auth.html
& I am able to successfully sign in with the default AuthUI.
Now, to login with the username, password I created an Authentication Handler like this from this reference - https://aws.amazon.com/blogs/mobile/using-android-sdk-with-amazon-cognito-your-user-pools/
AuthenticationHandler handler = new AuthenticationHandler() {
#Override
public void onSuccess(CognitoUserSession userSession, CognitoDevice newDevice) {
}
#Override
public void getAuthenticationDetails(AuthenticationContinuation authenticationContinuation, String userId) {
AuthenticationDetails authenticationDetails = new AuthenticationDetails(mEmailEditText.getText().toString(), mPasswordEditText.getText().toString(), null);
authenticationContinuation.setAuthenticationDetails(authenticationDetails);
authenticationContinuation.continueTask();
}
#Override
public void getMFACode(MultiFactorAuthenticationContinuation continuation) {
}
#Override
public void authenticationChallenge(ChallengeContinuation continuation) {
}
#Override
public void onFailure(Exception exception) {
}
};
So, now how to call this handler to get the Cognito user session & details
Can anyone please share appropriate directions to get this done or any other way this can be done?
So, now how to call this handler to get the Cognito user session & details
You need to initialise CognitoUser object first and call getSessionInBackground()
Check below code, call login() to login with the username, password. And make sure build.gradle imports required AWS libraries:
import com.amazonaws.mobile.client.AWSMobileClient;
import com.amazonaws.mobile.config.AWSConfiguration;
import com.amazonaws.mobileconnectors.cognitoidentityprovider.CognitoDevice;
import com.amazonaws.mobileconnectors.cognitoidentityprovider.CognitoUser;
import com.amazonaws.mobileconnectors.cognitoidentityprovider.CognitoUserPool;
import com.amazonaws.mobileconnectors.cognitoidentityprovider.CognitoUserSession;
import com.amazonaws.mobileconnectors.cognitoidentityprovider.continuations.AuthenticationContinuation;
import com.amazonaws.mobileconnectors.cognitoidentityprovider.continuations.AuthenticationDetails;
import com.amazonaws.mobileconnectors.cognitoidentityprovider.continuations.ChallengeContinuation;
import com.amazonaws.mobileconnectors.cognitoidentityprovider.continuations.MultiFactorAuthenticationContinuation;
import com.amazonaws.mobileconnectors.cognitoidentityprovider.handlers.AuthenticationHandler;
// ...
private EditText mEmailEditText;
private EditText mPasswordEditText;
private String email;
private String password;
// ...
private void login()
{
email = mEmailEditText.getText().toString(); // email
password = mPasswordEditText.getText().toString(); // password
if (email.isEmpty() || password.isEmpty())
{
return;
}
final AWSConfiguration awsConfiguration = AWSMobileClient.getInstance().getConfiguration();
final CognitoUserPool userPool = new CognitoUserPool(this, awsConfiguration);
final CognitoUser user = userPool.getUser(email); // Create a User Object with a UserId
user.getSessionInBackground(authenticationHandler);
}
private AuthenticationHandler authenticationHandler = new AuthenticationHandler()
{
#Override
public void onSuccess(final CognitoUserSession userSession, final CognitoDevice newDevice)
{
// Login success, do startActivity() or other thing
}
#Override
public void getAuthenticationDetails(final AuthenticationContinuation continuation, final String userId)
{
if (userId != null)
{
email = userId;
}
final AuthenticationDetails authDetails = new AuthenticationDetails(email, password, null);
continuation.setAuthenticationDetails(authDetails);
continuation.continueTask();
}
#Override
public void getMFACode(final MultiFactorAuthenticationContinuation continuation)
{
}
#Override
public void authenticationChallenge(final ChallengeContinuation continuation)
{
}
#Override
public void onFailure(final Exception exception)
{
}
};
I want to implement sign up with two activities with the help of firebase, first sign up activity contains email mobile and password, and in this activity i want to check whether the entered email ID or mobile is registered or not, if it does not then move the data(i.e. email, mobile no. and password) to next activity where final registration will happen. The two methods which are present in the code i.e. userMobileExists() and userEmailExists() to check the email and mobile. But the problem is these are asynchronous so when I go to next activity then the Toast appear that email is already registered.
I am returning valid, if all the valid are true then it goes to next activity , I debugged it and it returns valid before going inside the method. It is because of asynchronous code, Please suggest something how it can be achieved on the first activity only. Or tell if I should provide the whole code.
public class SignupActivity extends AppCompatActivity {
private static final String TAG = "SignupActivity";
private static final int REQUEST_SIGNUP = 0;
private Firebase mRef = new Firebase("https://abcdef.firebaseio.com/");
private User user;
private FirebaseAuth mAuth;
private FirebaseAuth.AuthStateListener mAuthListener;
private ProgressDialog mProgressDialog;
boolean valid = true;
String email;
String mobile;
String password;
#Bind(R.id.input_email)
EditText _emailText;
#Bind(R.id.input_mobile)
EditText _mobileText;
#Bind(R.id.input_password)
EditText _passwordText;
#Bind(R.id.btn_next)
Button _signupButton;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_signup);
ButterKnife.bind(this);
//For Full screen
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
mAuth = FirebaseAuth.getInstance();
//Back button initialization
Button backButton = (Button) findViewById(R.id.back_signup);
backButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent in = new Intent(view.getContext(), LoginActivity.class);
startActivity(in);
}
});
mAuth = FirebaseAuth.getInstance();
// mRef = Firebase(Config.FIREBASE_URL);
_signupButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
signup();
}
});
}
protected void setUpUser() {
user.setPhoneNumber(_mobileText.getText().toString());
user.setEmail(_emailText.getText().toString());
user.setPassword(_passwordText.getText().toString());
}
//private void
public void signup() {
Log.d(TAG, "Signup");
//showProgressDialog();
if (validate() && userEmailExist() && userMobileExist()) {
onSignupSuccess();
} else {
onSignupFailed();
return;
}
//_signupButton.setEnabled(false);
email = _emailText.getText().toString();
mobile = _mobileText.getText().toString();
password = _passwordText.getText().toString();
// TODO: Implement your own signup logic here.
}
public void onSignupSuccess() {
//_signupButton.setEnabled(true);
Log.d(TAG, "NEXT BUTTTON");
//hideProgressDialog();
Intent in = new Intent(this, SignupActivity2.class);
in.putExtra("Email", _emailText.getText().toString());
in.putExtra("Mobile", _mobileText.getText().toString());
startActivity(in);
/*setResult(RESULT_OK, null);
finish();*/
}
public void onSignupFailed() {
// hideProgressDialog();
Toast.makeText(getBaseContext(), "SignUp failed", Toast.LENGTH_LONG).show();
// _signupButton.setEnabled(true);
}
public boolean validate() {
email = _emailText.getText().toString();
mobile = _mobileText.getText().toString();
password = _passwordText.getText().toString();
if (email.isEmpty() || !android.util.Patterns.EMAIL_ADDRESS.matcher(email).matches()) {
_emailText.setError("enter a valid email address");
valid = false;
} else {
_emailText.setError(null);
}
if (mobile.isEmpty() || mobile.length() != 10) {
_mobileText.setError("Enter Valid Mobile Number");
valid = false;
} else {
_mobileText.setError(null);
}
if (password.isEmpty() || password.length() < 4 || password.length() > 10) {
_passwordText.setError("between 4 and 10 alphanumeric characters");
valid = false;
} else {
_passwordText.setError(null);
}
return valid;
}
public boolean userEmailExist() {
//private Firebase mRef = new Firebase("https://.firebaseio.com/users/");
mRef.child("users").orderByChild("email").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.getValue()== _emailText.getText().toString()) {
Toast.makeText(getBaseContext(), "Email already exist. Please choose a different one", Toast.LENGTH_SHORT).show();
_emailText.setError("Email already exist. Please choose a different one");
valid = false;
} else {
email = _emailText.getText().toString();
}
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});
return valid;
}
public boolean userMobileExist() {
mRef.child("users").
orderByChild("cellPhone").equalTo(_mobileText.getText().toString()).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
_mobileText.setError("Mobile Number already exist");
valid = false;
} else {
mobile = _mobileText.getText().toString();
}
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});
return valid;
}
#Override
public void onBackPressed() {
// Disable going back to the MainActivity
moveTaskToBack(true);
}
public void showProgressDialog(){
if(mProgressDialog == null){
mProgressDialog = new ProgressDialog(this);
mProgressDialog.setMessage("loading");
mProgressDialog.setIndeterminate(true);
}
mProgressDialog.show();
}
public void hideProgressDialog(){
if(mProgressDialog != null && mProgressDialog.isShowing()){
mProgressDialog.dismiss();
}
}
}
You need to grasp the concept of callbacks. You cannot return a variable that's assigned asynchronously.
As a quick solution to your problem, start with an interface
public interface OnUserActionListener {
void onExists(Boolean exists);
}
Then, make your methods be void and accept a parameter
public void userEmailExist(final String email, final OnUserActionListener listener) {
mRef.child("users")
.orderByChild("email")
.equalTo(email)
.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
listener.onExists( dataSnapshot.exists() );
}
...
// no return statement
}
Then, when you call that method, you can pass in the string value you want to search for, and implement your interface.
So replace this synchronous code
validate() && userEmailExist()
With the async version
if (validate()) { // This is synchonous
final String email = _emailText.getText().toString();
final String mobile = _mobileText.getText().toString();
// This is asynchronous
userEmailExist(email, new OnUserActionListener() {
#Override
public void onExists(Boolean exists) {
if (exists) {
Toast.makeText(getBaseContext(), "Email already exist. Please choose a different one", Toast.LENGTH_SHORT).show();
_emailText.setError("Email already exist. Please choose a different one");
onSignupFailed();
} else {
onSignupSuccess();
}
}
});
However you choose to define that interface is up to you
And again, worth repeating, don't assign a field valid within your callbacks. Try your best to implement all logic requiring a value to the callback itself
You can also implement the entire interface on the class, which is what I would recommend in this scenario as a SignUpActivity because you want to listen for user event actions such as success or error
Just an example using the method names you already have
public interface OnUserActionListener {
// Combine the email and phone into one action
void onUserExists(User user, Boolean exists);
void onSignupSuccess(User user);
void onSignupFailed(String reason);
}
public class SignupActivity extends AppCompatActivity
implements OnUserActionListner { // Implement this interface
// Define the needed methods
#Override
public void onUserExists(User user, Boolean exists) {
if (exists) {
onSignupFailed("User " + user + " already exists");
} else {
onSignupSuccess(user);
}
}
#Override
public void onSignupSuccess(User user) {
// Do something
}
#Override
public void onSignupFailed(String reason) {
Toast.makeText(this, reason, Toast.LENGTH_SHORT).show();
}
#Override
protected void onCreate(Bundle b) {
...
}
etc. etc.
Then, that other method call simply becomes.
if (validate()) { // This is synchonous
final String email = _emailText.getText().toString();
final String mobile = _mobileText.getText().toString();
// This is asynchronous & you defined the Activity as the interface
userEmailExist(email, SignupActivity.this);
I'm not satisfied with the accepted answer because when I used it in my project it still failed. After trying many thing I write my own code ... and it is working. If you want check whether user is already registered or not you can try the following code.
private void isUserAlreadySignUp(String phone){
firebaseAuth = FirebaseAuth.getInstance();
DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference("authUser");
// after getting reference of child, checked orderbykey so we get if phone is key we can get ref in dataSnapshot...
databaseReference.child( "userPhone" ).orderByKey().equalTo( phone ).addListenerForSingleValueEvent( new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
Boolean isExists = dataSnapshot.exists();
if (isExists)
showToast( "This number is alredy Registerd..!!" );
else
{
// if mobile is not registered you can go ahead...
// You can write your further code here or call methods...
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
showToast("Error :" + databaseError);
wSignUpProgressBar.setVisibility( View.GONE );
}
} );
}
// For Toast msg...
private void showToast(String s){ Toast.makeText( getActivity(), s , Toast.LENGTH_SHORT ).show(); }
To register a users mobile number on the database after authenticating the user, you can call this method.
// Register User on the database --------------------------
private void registerUserOnDatabase( String userPhone){
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference userRef = database.getReference("authUser").child("userPhone");
userRef.child( userPhone ).setValue( userPhone );
}
I am implementing an application using FireBase, in this application I have to save user information with user enter unique id. How can I do that. Actually it saving the data with random generated value. But I want to add a user enter unique id.
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
txtDetails = (TextView) findViewById(R.id.txt_user);
inputName = (EditText) findViewById(R.id.name);
inputEmail = (EditText) findViewById(R.id.email);
btnSave = (Button) findViewById(R.id.btn_save);
mFirebaseInstance = FirebaseDatabase.getInstance();
// get reference to 'users' node
mFirebaseDatabase = mFirebaseInstance.getReference("users");
// store app title to 'app_title' node
mFirebaseInstance.getReference("app_title").setValue("Realtime Database");
// app_title change listener
mFirebaseInstance.getReference("app_title").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Log.e(TAG, "App title updated");
// update toolbar title
}
#Override
public void onCancelled(DatabaseError error) {
// Failed to read value
Log.e(TAG, "Failed to read app title value.", error.toException());
}
});
// Save / update the user
btnSave.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String name = inputName.getText().toString();
String email = inputEmail.getText().toString();
// Check for already existed userId
if (TextUtils.isEmpty(userId)) {
createUser(name, email);
} else {
createUser(name, email);
}
}
});
toggleButton();
}
// Changing button text
private void toggleButton() {
if (TextUtils.isEmpty(userId)) {
btnSave.setText("Save");
} else {
btnSave.setText("Save");
}
}
/**
* Creating new user node under 'users'
*/
private void createUser(String name, String email) {
// TODO
// In real apps this userId should be fetched
// by implementing firebase auth
if (TextUtils.isEmpty(userId)) {
userId = mFirebaseDatabase.push().getKey();
}
User user = new User(name, email);
mFirebaseDatabase.child(userId).push().setValue(user);
addUserChangeListener();
}
/**
* User data change listener
*/
private void addUserChangeListener() {
// User data change listener
mFirebaseDatabase.child(userId).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
User user = dataSnapshot.getValue(User.class);
// Check for null
if (user == null) {
Log.e(TAG, "User data is null!");
return;
}
Log.e(TAG, "User data is changed!" + user.name + ", " + user.email);
// Display newly updated name and email
// txtDetails.setText(user.name + ", " + user.email);
// clear edit text
inputEmail.setText("");
inputName.setText("");
toggleButton();
}
#Override
public void onCancelled(DatabaseError error) {
// Failed to read value
Log.e(TAG, "Failed to read user", error.toException());
}
});
}
private void updateUser(String name, String email) {
// updating the user via child nodes
if (!TextUtils.isEmpty(name))
mFirebaseDatabase.child(userId).child("name").setValue(name);
if (!TextUtils.isEmpty(email))
mFirebaseDatabase.child(userId).child("email").setValue(email);
}
To save user data under an unique identifier i suggest you using the email address in stead of pushing a new key or using the uid. The email address is unique and easy to use. But because Firebase does not accept . symbol in the key i suggest you encode the email address like this:
name#email.com -> name#email,com
As you see, i have changed the the dot symbol . with a coma ,. To achive this i recomand you using this methods:
static String encodeUserEmail(String userEmail) {
return userEmail.replace(".", ",");
}
static String decodeUserEmail(String userEmail) {
return userEmail.replace(",", ".");
}
Hope it helps.