Firebase User always initialized to null in oncreate - android

Firebase user.currentuser() is always null in oncreate. I want to implement this access controll so that only a user called a credit controller can add items to the recyclerview using the floating action button, while other users can only see the items added.
I want the floating action button's visibility to be determined as soon as the activity is open. Is there any other way to achieve this?
I used the reveal button to achieve this but it's a very bad user experience to click it every time you want to go into this activity.
This is my code below:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_collections);
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
userEmail = user.getEmail();
FloatingActionButton buttonAddNote = findViewById(R.id.button_add_note);
Button revealButton = findViewById(R.id.revealButton);
revealButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(userEmail.equals("creditcontroller#outlook.com")){
buttonAddNote.setVisibility(View.VISIBLE);
revealButton.setVisibility(View.GONE);
}
else revealButton.setVisibility(View.GONE);
}
});
buttonAddNote.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(CollectionsActivity.this, AddEditNoteActivity.class);
intent.putExtra("USER_EMAIL", userEmail);
startActivityForResult(intent, ADD_NOTE_REQUEST);
}
});
Unfortunately I can't upload images yet but the reveal button is just a button that's centered in the activity. Upon clicking it its visibility is set to gone and everything else is set to visible
The code is working but the user experience is pretty bad.

Firebase calls are asynchronous which means that you can't get results instantly.
You should add a callback to your calls.
FirebaseUser user = firebaseAuth.getCurrentUser();
userEmail = user.getEmail();
database.child(userEmail).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String email = dataSnapshot.child("email").getValue(String.class);
Log.d(TAG, "email: " + email);
}
#Override
public void onCancelled(DatabaseError databaseError) {}
});
The code is just an example. It may not work in your case, because you must know the structure of your nodes.
You can read more in the Firebase documentation: https://firebase.google.com/docs/database/android/read-and-write

Related

Firebase: How to make one app hides button for another app

I have 2 android apps connected to the same Firebase database, and I want to add a button in the first app to hide another button in the inside the second app.
This is my code on the first app which hides 'btnact' depending on the status of the settings in Remote Config of Firebase:
myconfiguration=FirebaseRemoteConfig.getInstance();
FirebaseRemoteConfigSettings configuratonsettings = new FirebaseRemoteConfigSettings.Builder().build();
myconfiguration.setConfigSettings(configuratonsettings);
Map<String,Object> defaultvalues = new HashMap<>();
defaultvalues.put("btn_enable",false);
myconfiguration.setDefaults(defaultvalues);
fetcher.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
myconfiguration.fetch(0).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if(task.isSuccessful()){
myconfiguration.activateFetched();
btnact.setEnabled(myconfiguration.getBoolean("btn_enable"));
}
else
{
Toast.makeText(MainActivity.this, "Something went Wrong\nPlease try again", Toast.LENGTH_SHORT).show();
}
}
});
}
});
I want a way to change this 'btnact' to the id of the button of the other app.. Can anyone have a clue for it?
You can fetch the value of the button you want to hide (boolean value: false or true) inside your second app, then set that button visibility to invisible or gone based on the fetched boolean value.
You can change the value that controls your second app's enabled status/visibility inside your first app.
I don't test this right now, but I think it should work and it is easy to accomplish what you want.

How to check value in realtime database (ON/OFF)

How i can in this code
#Override
protected void onStart() {
super.onStart();
//if the user is already signed in
//we will close this activity
//and take the user to profile activity
if (mAuth.getCurrentUser() != null) {
finish();
startActivity(new Intent(this, ActivitySplash.class));
}
}
make check whether the child (userId) is set to ON / OFF and if ON then we run the code
if (mAuth.getCurrentUser() != null) {
finish();
startActivity(new Intent(this, ActivitySplash.class));
}
if OFF then we show a specific activity.
My database
As #FrankvanPuffelen said, you should spend some time reading docs, it would help you write code yourself, still I am briefing the things for you here. It should make things more clear.
Reading from database is done by correctly referencing your desired node from the database and then using the correct eventListener. There are 3 types of eventListeners present, singleValueEventListener, valueEventListener and childEventListener.
Read more about each of them in detail in docs.
This answer can also help you understand childEventListeners.
To retrieve the value of status node you have to go sequentially through your database parent nodes, that are users and that uid with value nfe....
So in code it would look something like this:
DatabaseReference ref = FirebaseDatabase.getInstance().getReference().child("users").child(uid);
// uid has the value nfe...
ref.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String status = dataSnapshot.child("status").getValue(String.class);
// compare the value of status here and do what you want
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.d(TAG, "onCancelled", databaseError.toException());
}
});

Firebase updating password (current pass and new pass)

I've been struggling about the change password functionality of my app. I am confused on how I can compare the current pass and store the new password thru firebase database.
Please don't be harsh on me on comments, educate me please. I did research first before asking and tried several times. Most of the tutorials I found are about updating data while clicking an item in listview. The reason why I use db to store users is because I am going to create 2 keys that identifies if user is student or professor.I just want to ask help how am I able to implement change of password.
ChangePassAccount.class
public class ChangePassAccount extends AppCompatActivity {
Button btnSave;
EditText cpass, npass;
String pass, newpass;
DatabaseReference dbPDF;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getSupportActionBar().hide();
setContentView(R.layout.activity_change_pass_account);
dbPDF = FirebaseDatabase.getInstance().getReference("users").child("password");
cpass = (EditText)findViewById(R.id.currentpass);
npass = (EditText)findViewById(R.id.newpass);
btnSave = (Button) findViewById(R.id.btnsave);
btnSave.setBackgroundResource(R.drawable.button);
btnSave.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
pass = cpass.getText().toString();
newpass = npass.getText().toString();
}
});
}
}
i'll suggest you to using firebase auth to manage User Login or Changes password etc.. So maybe you only has to store user Data by UserInfo
this is a sample from Firebase-Manage User to change the user password
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
String newPassword = "SOME-SECURE-PASSWORD";
user.updatePassword(newPassword)
.addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
Log.d(TAG, "User password updated.");
}
}
});
This is not a very technical answer but I ran into this problem in iOS recently.
There is a FirebaseAuth method named 'reauthenticate' that can be found here. This takes a credential that you create by asking for the user's password and getting the email from currentUser. If this returns successful you will know that password is correct. After reauthenticated you can call updatePassword with the new password.
As a suggestion you should not need to store the password separately in the database since Firebase will handle all this for you.
Hope this helps out, good luck!
You'd use a Firebase Database transaction for that. This gives you the current value, which you then compare against the old password. If they match, you return the new password.
Something like:
passwordRef.runTransaction(new Transaction.Handler() {
#Override
public Transaction.Result doTransaction(MutableData mutableData) {
String password = mutableData.getValue(String.class);
if (password.equals(oldPassword) {
mutableData.setValue(newPassword);
return Transaction.success(mutableData);
}
}
#Override
public void onComplete(DatabaseError databaseError, boolean b, DataSnapshot dataSnapshot) {
Log.d(TAG, "passwordTransaction:onComplete:" + databaseError);
}
});
First you need to read the current password using single value event listener
pass = cpass.getText().toString();
newpass = npass.getText().toString();
dbPDF.addValueEventListener(addListenerForSingleValueEvent(){
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
// Get Post object and use the values to update the UI
String password = dataSnapshot.getValue(String.class);
if(password.equals(pass)){
dbPDF.setValue(newpass);
}else{
// show wrong pass dialog
}
// ...
}
#Override
public void onCancelled(DatabaseError databaseError) {
// Getting Post failed, log a message
Log.w(TAG, "loadPost:onCancelled", databaseError.toException());
// ...
}
};
Also make sure dbref is correct
String username = "helpmepls";
dbPDF = FirebaseDatabase.getInstance().getReference("users").child(username).child("password");

How to stop Firebase database infinite looping

I am creating an app and part of it's features in user interaction. I want to store user comments on a post and I do not want to limit the amount of comments any one user can make. I do this by assigning a random number as the .setValue of the database entry.
With this implementation, whenever the comment is sent to the database it is stuck in an infinite loop where it will continually update with the same string entered in the text box but it will constantly generate new posts.
Full code;
sendComment.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
commitPost();
finish();
}
});
}
private void commitPost() {
commentProgress.setMessage("Posting");
commentProgress.show();
final String commentInput = commentText.getText().toString().trim();
if(TextUtils.isEmpty(commentInput)){
Snackbar.make(commentLayout,"You haven't finished your post yet",Snackbar.LENGTH_SHORT);
}else{
commentDB.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String uniqueId = UUID.randomUUID().toString();
commentDB.child(postID).child("Comments").child(uniqueId).setValue(commentInput);
commentProgress.dismiss();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}
The problem lies in the commentDB.addValueEventListener
The problem is that you set a listener for data changes and you also change data inside it (so it is called).
You don't need the listener, just add:
else {
String uniqueId = UUID.randomUUID().toString();
commentDB.child(postID)
.child("Comments")
.child(uniqueId)
.setValue(commentInput);
commentProgress.dismiss();
}

The Activity restart after saving data in Firebase

Im trying to save user information in Firebase Database but a strange behavior happens that make the Save button to restart the same activity not the Intent that i made for the next activity .
public void userData () {
user.setFName(Fname.getText().toString());
user.setLName(Lname.getText().toString());
user.setEmail(Email.getText().toString());
user.setAddress(userAddress.getText().toString());
user.setPassword(UserInfo.getString("Password", ""));
user.setID(CicID.getText().toString());
user.setUsername(Usnm.getText().toString());
if (bAdmn.isChecked()) user.setMajor("Business Administrator");
if (BTech.isChecked()) user.setMajor("Business Tech");
if (masscom.isChecked()) user.setMajor("Mass Com");
if (Eng.isChecked()) user.setMajor("Engineering");
final String us = user.getUsername();
Log.i("Username", us);
MyDatabase1.child("USERS").child(us).setValue(user);
Intent i = new Intent(getApplicationContext() , chooseCoursesActivity.class);
startActivity(i);
}
that is the method for save button , Note that i want to update the user information in a profile Activity if the user wants to change his First name or Last name or something .
But after Clicking save button , the data is saved correctly but the intent never done . it recreate the same Activity .
in the Login activity there is aLogin button which checks username and password then attempt to log in based on data ,if login successful it goes to that Profile Activity .
Save button in Profile Activity re Do the method in Login button in Login Activity which checks everything and goes to Profile Activity which what causing the Re Create Problem .
Here is the code for login button :
MyDatabase = FirebaseDatabase.getInstance().getReference();
MyDatabase.child("USERS").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
boolean exists = false;
for (DataSnapshot child : dataSnapshot.getChildren()) {
final Map<String, Object> model = (Map<String, Object>) child.getValue();
if (model.get("username").equals(Username.getText().toString())) {
exists = true;
Log.i("USername"," Correct");
if(exists){
MyDatabase.child("USERS").orderByChild("username").equalTo(Username.getText().toString())
.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot child :dataSnapshot.getChildren()){
Log.i("Password",child.getValue().toString());
Log.i( "Password",child.child("password").toString());
if(password.getText().toString().equals(child.child("password").getValue())){
Log.i("LOGIN","Success");
loginsuccessful = true ;
if(loginsuccessful){
saveCredntials(Username.getText().toString(),password.getText().toString());
Intent i2 = new Intent(getApplicationContext(), ProfileActivity.class);
i2.putExtra("loginStats",IsLoggedIn);
i2.putExtra("Username",Un);
i2.putExtra("Password",Pw);
startActivity(i2);
finish();}
}else{
Log.i("LOGIN","Failed");
loginsuccessful= false ;
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
Toast.makeText(getApplicationContext(),"Error",Toast.LENGTH_LONG).show();
}
});
}
break;
}else {
Log.i("LOGIN","FAiled");
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
Sorry for making this too long but i dont know the problem .
I just solved this problem! According to your case, please avoid using addValueEventListener, because it will listen to all changes you make to the database. That's why every time you make any change to the database, the code in the addValueEventListener (startActivity) will be executed no matter you call that login function or not.
My suggestion is using addListenerForSingleValueEvent instead of addValueEventListener (Make sure you change ALL the addValueEventListener in your Android project to addListenerForSingleValueEvent), or you can even remove the listener if you don't really need it. I don't know if it is a good design, but it should be able to solve your problem.
Avoid putting startActivity on a firebase listener. startActivity execute every time a value is added or removed from firebase database.

Categories

Resources