In 10% of the cases there is a null pointer exception when trying to log in with the email and password authentication with Firebase. This only happens in the release apk. It doesn't occur in the debug app. It says it can't pass null for email. But the email is filled in. And otherwise Firebase sents an error code, but not a npe.
This is the error message:
Caused by: java.lang.NullPointerException: Can't pass null for argument 'email' in authWithPassword()
at com.firebase.client.Firebase.authWithPassword(Unknown Source)
at com.example.verdienapp.ui.start.StartActivity$LoginTask.doInBackground(Unknown Source)
at com.example.verdienapp.ui.start.StartActivity$LoginTask.doInBackground(Unknown Source)
My apologies. I should have directly added my code.
First validating the input:
private void validate() {
this.mEmailEditText.setError(null);
this.mPasswordEditText.setError(null);
String email = this.mEmailEditText.getText().toString();
String password = this.mPasswordEditText.getText().toString();
boolean cancel = false;
View focusView = null;
if (TextUtils.isEmpty(password)) {
this.mPasswordEditText.setError(getString(R.string.error_field_required));
focusView = this.mPasswordEditText;
cancel = true;
} else if (password.length() < 6) {
this.mPasswordEditText.setError(getString(R.string.error_invalid_password));
focusView = this.mPasswordEditText;
cancel = true;
}
if (TextUtils.isEmpty(email)) {
this.mEmailEditText.setError(getString(R.string.error_field_required));
focusView = this.mEmailEditText;
cancel = true;
} else if (!email.contains("#")) {
this.mEmailEditText.setError(getString(R.string.error_invalid_email));
focusView = this.mEmailEditText;
cancel = true;
}
if (cancel) {
if (focusView != null) {
focusView.requestFocus();
}
} else {
Utils.closeKeyboard(getActivity(), this.mEmailEditText);
LoginEvent event = new LoginEvent(R.id.button_login, email, password);
BusProvider.getInstance().post(event);
}
}
Then the login event:
private void login(final ButtonEvent buttonEvent) {
LoginEvent loginEvent = (LoginEvent) buttonEvent;
new LoginTask().execute();
email = loginEvent.getEmail();
password = loginEvent.getPassword();
}
And finally the login process with Firebase in a AsyncTask.
private class LoginTask extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog = new ProgressDialog(StartActivity.this);
progressDialog.setTitle(“please wait..");
progressDialog.setMessage(“authorizing...");
progressDialog.setCancelable(false);
progressDialog.show();
}
#Override
protected Void doInBackground(Void... params) {
mFirebase.authWithPassword(email, password, new Firebase.AuthResultHandler() {
#Override
public void onAuthenticated(AuthData authData) {
// System.out.println("User ID: " + authData.getUid() + ", Provider: " + authData.getProvider());
Intent intent2 = new Intent(StartActivity.this, MainActivity.class);
startActivity(intent2);
finish();
}
#Override
public void onAuthenticationError(FirebaseError firebaseError) {
// error encountered
switch (firebaseError.getCode()) {
case FirebaseError.USER_DOES_NOT_EXIST:
// handle a non existing user
Toast.makeText(getApplicationContext(), getString(R.string.error_user_not_exist)
Toast.LENGTH_LONG).show();
break;
case FirebaseError.INVALID_PASSWORD:
// handle an invalid password
Toast.makeText(getApplicationContext(), getString(R.string.error_invalid_password)
Toast.LENGTH_LONG).show();
break;
default:
// handle other errors
Toast.makeText(getApplicationContext(), getString(R.string.error_reset_password),
Toast.LENGTH_LONG).show();
break;
}
}
});
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
progressDialog.dismiss();
}
}
Related
i wrote these two functions and called theme in signup button but no user is created in Firebase.(The connection between the app and Firebase is done correctly) so whats the problem?
private void attemptRegistration() {
// Reset errors displayed in the form.
edtEmail.setError(null);
edtPassword.setError(null);
// Store values at the time of the login attempt.
String email = edtEmail.getText().toString();
String password = edtPassword.getText().toString();
boolean cancel = false;
View focusView = null;
// Check for a valid password, if the user entered one.
if (!TextUtils.isEmpty(password) && !isPasswordValid(password)) {
edtPassword.setError(getString(R.string.error_invalid_password));
focusView = edtPassword;
cancel = true;
}
// Check for a valid email address.
if (TextUtils.isEmpty(email)) {
edtEmail.setError(getString(R.string.error_field_required));
focusView = edtEmail;
cancel = true;
} else if (!isEmailValid(email)) {
edtEmail.setError(getString(R.string.error_invalid_email));
focusView = edtEmail;
cancel = true;
}
if (cancel) {
// There was an error; don't attempt login and focus the first
// form field with an error.
focusView.requestFocus();
} else {
// TODO: Call create FirebaseUser() here
createFirebaseUser();
}
}
private void createFirebaseUser() {
String email = edtEmail.getText().toString();
String password = edtPassword.getText().toString();
auth.createUserWithEmailAndPassword(email, password).addOnCompleteListener(this,
new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
Log.d("FlashChat", "createUser onComplete: " + task.isSuccessful());
if (!task.isSuccessful()) {
Log.d("FlashChat", "user creation failed");
showErrorDialog("Registration attempt failed");
} else {
saveDisplayName();
Intent intent = new Intent(RegisterActivity.this, LoginActivity.class);
finish();
startActivity(intent);
}
}
});
}
I have been trying to make a registration page. I'm using email authentication. My registered data is stored in a firebase database.
For security purposes, I want my password string to be hidden. So for that I'm using SHA-256 to hash but it's not working.
Here is my code:
protected void setUpUser() {
user = new User();
user.setName(name.getText().toString().trim());
user.setPhoneNumber(phoneNumber.getText().toString().trim());
user.setAddress(address.getText().toString().trim());
user.setEmail(email.getText().toString().trim());
user.setPassword(password.getText().toString().trim());
}
#Override
public void onClick(View v) {
String pass = password.getText().toString();
MessageDigest digest = null;
try {
digest = MessageDigest.getInstance("SHA-256");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
byte[] hash = digest.digest(pass.getBytes(StandardCharsets.UTF_8));
mref = new Firebase("https://tango-3a561.firebaseio.com/");
createNewAccount(email.getText().toString(), hash);
}
private void createNewAccount(String email, final byte[] password) {
Log.d(TAG, "createNewAccount:" + email);
if (!validateForm()) {
return;
}
//This method sets up a new User by fetching the user entered details.
setUpUser();
//This method method takes in an email address and password, validates them and then creates a new user
// with the createUserWithEmailAndPassword method.
// If the new account was created, the user is also signed in, and the AuthStateListener runs the onAuthStateChanged callback.
// In the callback, you can use the getCurrentUser method to get the user's account data.
showProgressDialog();
mAuth.createUserWithEmailAndPassword(email, String.valueOf(password))
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
Log.d(TAG, "Register Successfully " + task.isSuccessful());
hideProgressDialog();
// 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()) {
/* Toast.makeText(RegisterActivity.this, "Registration failed.", Toast.LENGTH_SHORT).show();
hideProgressDialog();*/
if (task.getException() instanceof FirebaseAuthUserCollisionException){
Toast.makeText(RegisterActivity.this,"User with this email already exist.",Toast.LENGTH_SHORT).show();
}else {
Toast.makeText(RegisterActivity.this, "Register Successful.", Toast.LENGTH_SHORT).show();
hideProgressDialog();
}
/* if (password.length() < 6) {
Toast.makeText(getApplicationContext(), "minimum password!", Toast.LENGTH_SHORT).show();
hideProgressDialog();
} else {
Toast.makeText(getApplicationContext(), "Registration failed.!", Toast.LENGTH_SHORT).show();
hideProgressDialog();
}*/
} else {
onAuthenticationSuccess(task.getResult().getUser());
Toast.makeText(RegisterActivity.this, "Register Successful.", Toast.LENGTH_SHORT).show();
} hideProgressDialog();
}
});
}
private void onAuthenticationSuccess(FirebaseUser mUser) {
// Write new user
saveNewUser(mUser.getUid(), user.getName(), user.getPhoneNumber(),user.getAddress(), user.getEmail(), user.getPassword());
signOut();
// Go to LoginActivity
Intent i =new Intent(RegisterActivity.this, LoginActivity.class);
startActivity(i);
}
private void saveNewUser(String userId, String name, String phone, String address, String email, String password) {
User user = new User(userId,name,phone,address,email,password);
mref.child("Users").child(name).setValue(user);
}
private void signOut() {
mAuth.signOut();
}
//This method, validates email address and password
private boolean validateForm() {
boolean valid = true;
String userName = name.getText().toString();
if (TextUtils.isEmpty(userName)) {
name.setError("Required.");
valid = false;
} else {
name.setError(null);
}
String userEmail = email.getText().toString();
if (TextUtils.isEmpty(userEmail)) {
email.setError("Required.");
valid = false;
} else {
email.setError(null);
}
if (!Patterns.EMAIL_ADDRESS.matcher(userEmail).matches()) {
email.setError("Invalid Mail Address.");
valid = false;
} else {
email.setError(null);
}
String userPassword = password.getText().toString();
if (TextUtils.isEmpty(userPassword)) {
password.setError("Required.");
valid = false;
} else {
password.setError(null);
}
String userPhoneNumber = phoneNumber.getText().toString();
if (TextUtils.isEmpty(userPhoneNumber)){
phoneNumber.setError("Required");
valid = false;
}else {
phoneNumber.setError(null);
}
if (phoneNumber.length() < 10){
phoneNumber.setError("Should be 10 Digit");
valid = false;
}else {
phoneNumber.setError(null);
}
String userAddress = address.getText().toString();
if (TextUtils.isEmpty(userAddress)){
address.setError("Required");
valid = false;
}else {
address.setError(null);
}
/* if(!Patterns.EMAIL_ADDRESS.matcher(userEmail).matches()){
Toast.makeText(getApplicationContext(),"please enter valid email",Toast.LENGTH_LONG).show();
}*/
/* if (Patterns.PHONE.matcher(userPhoneNumber).matches()){
Toast.makeText(getApplicationContext(),"please enter valid mobile no",Toast.LENGTH_LONG).show();
}*/
if (userName.isEmpty() && userEmail.isEmpty() && userPassword.isEmpty() && userAddress.isEmpty() && userPhoneNumber.isEmpty()){
Toast.makeText(getApplicationContext(),"all fields are mandatory",Toast.LENGTH_LONG).show();
}
return valid;
}
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();
}
}
#Override
public void onPointerCaptureChanged(boolean hasCapture) {
}
}
As you can see my password is not hashed.
I have solved this type of issue with this code:
public static String sha256(String base) {
try{
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hash = digest.digest(base.getBytes("UTF-8"));
StringBuffer hexString = new StringBuffer();
for (int i = 0; i < hash.length; i++) {
String hex = Integer.toHexString(0xff & hash[i]);
if(hex.length() == 1) hexString.append('0');
hexString.append(hex);
}
return hexString.toString();
} catch(Exception ex){
throw new RuntimeException(ex);
}
}
Then you just call the method and pass the password field:
String newPass = sha256(pass).toString();
Edit
At your question, this would solve the problem:
#Override
public void onClick(View v) {
String pass = password.getText().toString();
String newPass = sha256(pass);
mref = new Firebase("https://tango-3a561.firebaseio.com/");
createNewAccount(email.getText().toString(), newPass );
}
Change your method params:
private void createNewAccount(String email,String pass)....
I am using Twitter 4j to post tweet on single button. If user revoke access of my app then its showing Error in Logcat in do in background i want this error and if this error comes my another hide button of twitter authorize app visible. how do i do that please help. I need that error and if its exists i want to hide show my buttons.
class updateTwitterStatus extends AsyncTask<String, String, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
protected Void doInBackground(String... args) {
String status = args[0];
try {
ConfigurationBuilder builder = new ConfigurationBuilder();
builder.setOAuthConsumerKey(consumerKey);
builder.setOAuthConsumerSecret(consumerSecret);
String access_token = mSharedPreferences.getString(PREF_KEY_OAUTH_TOKEN, "");
String access_token_secret = mSharedPreferences.getString(PREF_KEY_OAUTH_SECRET, "");
AccessToken accessToken = new AccessToken(access_token, access_token_secret);
twitter4j.Twitter twitter = new TwitterFactory(builder.build()).getInstance(accessToken);
StatusUpdate statusUpdate = new StatusUpdate(status);
File extStore = Environment.getExternalStoragePublicDirectory("/Twitter/Cache/demo.jpg");
statusUpdate.setMedia(extStore);
twitter4j.Status response = twitter.updateStatus(statusUpdate);
} catch (TwitterException e) {
Log.d("Failed to post!", e.getMessage());
error=e; //error is exception
}
return null;}
#Override
protected void onPostExecute(Void result) {
pDialog.dismiss();
Toast.makeText(getContext(), "Posted to Twitter!"+error, Toast.LENGTH_SHORT).show();
/* i need a variable like int a =10; access it globally, How i do that/*
} } }
You can save the exception in a variable and check it in onPostExecute()
and hide your button ..
new AsyncTask<Void, Void, Boolean>() {
Exception error;
#Override
protected Boolean doInBackground(Void... params) {
try {
// do work
return true;
} catch (Exception e) {
error = e;
return false;
}
}
#Override
protected void onPostExecute(Boolean result) {
if (result) {
Toast.makeText(ctx, "Success!",
Toast.LENGTH_SHORT).show();
} else {
if (error != null) {
Toast.makeText(getApplicationContext(), error.getMessage(),
Toast.LENGTH_SHORT).show();
//error occurs hide button here
}
}
}
}
I'm currently in a project of making a service that has a web-app and an Android App. Currently the web team doesn't have the web services up and I need to implement login validation of forms and make it able for the user to sign up. I have tried with Realm but I don't really much understand it.
Any help?
You can follow this
http://sourcey.com/beautiful-android-login-and-signup-screens-with-material-design/
http://www.androidhive.info/2011/10/android-login-and-registration-screen-design/
public class LoginActivity extends AppCompatActivity {
private static final String TAG = "LoginActivity";
private static final int REQUEST_SIGNUP = 0;
#InjectView(R.id.input_email) EditText _emailText;
#InjectView(R.id.input_password) EditText _passwordText;
#InjectView(R.id.btn_login) Button _loginButton;
#InjectView(R.id.link_signup) TextView _signupLink;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
ButterKnife.inject(this);
_loginButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
login();
}
});
_signupLink.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Start the Signup activity
Intent intent = new Intent(getApplicationContext(), SignupActivity.class);
startActivityForResult(intent, REQUEST_SIGNUP);
}
});
}
public void login() {
Log.d(TAG, "Login");
if (!validate()) {
onLoginFailed();
return;
}
_loginButton.setEnabled(false);
final ProgressDialog progressDialog = new ProgressDialog(LoginActivity.this,
R.style.AppTheme_Dark_Dialog);
progressDialog.setIndeterminate(true);
progressDialog.setMessage("Authenticating...");
progressDialog.show();
String email = _emailText.getText().toString();
String password = _passwordText.getText().toString();
// TODO: Implement your own authentication logic here.
new android.os.Handler().postDelayed(
new Runnable() {
public void run() {
// On complete call either onLoginSuccess or onLoginFailed
onLoginSuccess();
// onLoginFailed();
progressDialog.dismiss();
}
}, 3000);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_SIGNUP) {
if (resultCode == RESULT_OK) {
// TODO: Implement successful signup logic here
// By default we just finish the Activity and log them in automatically
this.finish();
}
}
}
#Override
public void onBackPressed() {
// disable going back to the MainActivity
moveTaskToBack(true);
}
public void onLoginSuccess() {
_loginButton.setEnabled(true);
finish();
}
public void onLoginFailed() {
Toast.makeText(getBaseContext(), "Login failed", Toast.LENGTH_LONG).show();
_loginButton.setEnabled(true);
}
public boolean validate() {
boolean valid = true;
String email = _emailText.getText().toString();
String 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 (password.isEmpty() || password.length() < 4 || password.length() > 10) {
_passwordText.setError("between 4 and 10 alphanumeric characters");
valid = false;
} else {
_passwordText.setError(null);
}
return valid;
}
}
If you are looking for login page user credentials validation, below code snippet may help you;
// validating email id
private boolean isValidEmail(String email) {
String EMAIL_PATTERN = "^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*#"
+ "[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$";
Pattern pattern = Pattern.compile(EMAIL_PATTERN);
Matcher matcher = pattern.matcher(email);
return matcher.matches();
}
// validating password with retype password
private boolean isValidPassword(String pass) {
if (pass != null && pass.length() > 6) {
return true;
}
return false;
}
I am attempting to use the android built in login view and parse together.
code
public class UserLoginTask extends AsyncTask<Void, Void, Boolean> {
#Override
protected Boolean doInBackground(Void... params) {
// TODO: attempt authentication against a network service.
try {
// Simulate network access.
Thread.sleep(2000);
} catch (InterruptedException e) {
return false;
}
for (String credential : DUMMY_CREDENTIALS) {
String[] pieces = credential.split(":");
if (pieces[0].equals(mEmail)) {
// Account exists, return true if the password matches.
return pieces[1].equals(mPassword);
}
}
// TODO: register the new account here.
ParseUser newUser = new ParseUser();
newUser.setEmail(mEmail);
newUser.setPassword(mPassword);
newUser.signUpInBackground(new SignUpCallback() {
#Override
public void done(ParseException e) {
if (e == null) {
// Success!
Intent intent = new Intent(LoginActivity.this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
} else {
// Oops!
AlertDialog.Builder builder = new AlertDialog.Builder(LoginActivity.this);
builder.setMessage(e.getMessage().toUpperCase())
.setTitle("Oops!")
.setPositiveButton(android.R.string.ok, null);
AlertDialog dialog = builder.create();
dialog.show();
}
}
});
return true;
}
When I run it, I type in my email / password and the application fails.
Have look at this code:
public class LoginActivity extends PlanndActivity
{
public EditText emailField;
public EditText passwordField;
public Button loginButton;
public View.OnClickListener loginButtonListener;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
PushService.setDefaultPushCallback(getApplicationContext(), PlanndActivity.class);
ParseInstallation.getCurrentInstallation().saveInBackground(
new SaveCallback() {
#Override
public void done(ParseException e) {
if(e!= null)
Log.e(Constants.TAG, "ERROR adding callback", e);
}
}
);
emailField = (EditText) findViewById(R.id.email_login);
passwordField = (EditText) findViewById(R.id.password_login);
loginButton = (Button) findViewById(R.id.login_button);
loginButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
loginButton.setEnabled(false);
String email = ((EditText) findViewById(R.id.email_login)).getText().toString().trim();
String password = ((EditText) findViewById(R.id.password_login)).getText().toString().trim();
ParseUser.logInInBackground(email, password, new LogInCallback() {
#Override
public void done(ParseUser parseUser, ParseException e) {
if(parseUser != null)
{
// User is valid and is now logged in
Log.i(Constants.TAG, "Successful login for user " + parseUser.getUsername());
Intent i = new Intent(getApplicationContext(), MainActivity.class);
startActivity(i);
PushService.subscribe(getApplicationContext(), "user_" + ParseUser.getCurrentUser().getObjectId(), PlanndActivity.class);
}
else
{
loginButton.setEnabled(true);
Log.i(Constants.TAG, "Unsuccessful login for user");
// sign up failed and the problems
// needs to go and do the sign up activity
}
}
});
}
});
((Button)findViewById(R.id.register_button)).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startActivity(new Intent(getApplicationContext(), RegisterActivity.class));
}
});
((Button)findViewById(R.id.fake_login)).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
emailField.setText("rberidon#gmail.com");
passwordField.setText("test");
}
});
}
}
Source: plannd
Try implement this with animation of view like use inline progress bar when user clicks sign in, switch the content and progress bar depending on your logic!
The problem is that your are executing signUpInBackground() inside AsyncTask.doInBackground(). doInBackground is already using a background thread. Just use newUser.signUp()