Trying to write same child to firebase twice - java

I am trying to execute this if statement so the value 'Like' with the unique id is written to the database twice. The line of code is:
mDatabaseChemRef.child(uploadCurrent.getNumber()).child(mAuth.getCurrentUser().getUid()).setValue("Like");
and the database is stored like so:
{
"467" : {
"4ulBYMRcP4WbhTCFXHSTNwX2yPU2" : "Like"
}
}
So essentially I want the "Like" along side the same unique ID to be written twice rather than once. Below is the full code. So when the user clicks the like button I want it to like twice rather than once is there a way to write this line twice?
holder.mLikebtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mProcessTechLike = true;
mDatabaseTechRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if(uploadCurrent.getCategory().equals("Technology")) {
if (mProcessTechLike) {
if (dataSnapshot.child(uploadCurrent.getNumber()).hasChild(mAuth.getCurrentUser().getUid())) {
//delete like
dataSnapshot.child(uploadCurrent.getNumber()).child(mAuth.getCurrentUser().getUid()).getRef().removeValue();
mProcessTechLike = false;
Toast.makeText(mContext, "Vote Retracted", Toast.LENGTH_LONG).show();
holder.mLikebtn.setColorFilter(null);
} else {
Resources res = mContext.getResources();
final int newColor = res.getColor(R.color.new_color);
holder.mLikebtn.setColorFilter(newColor, Mode.SRC_ATOP);
mDatabaseTechRef.child(uploadCurrent.getNumber()).child(mAuth.getCurrentUser().getUid()).setValue("Like");
mProcessTechLike = false;
Toast.makeText(mContext, "Vote Counted", Toast.LENGTH_LONG).show();
}
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});

Related

How to make "int" based on number from database? - Java

I'm making a game, so far I've made two buttons for the test. The first button makes a win, and the second one loses, all this is added to the database.
int win_int = 0;
int lose_int = 0;
The fact is that every time you enter this activity, the number is reset to zero, since I set the number 0 in the variable. I want to understand how to make "integer" take a number not just one, but the number that is in the database.
Here are the codes for the two buttons:
Button win = (Button)findViewById(R.id.Poke);
win.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
winsRef = database.getReference();
winsRef.child("players/").child(playerName).child("/wins").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
dataSnapshot.getRef().setValue(win_int = win_int + 1);
Toast.makeText(DuelGame.this, "+1 win!", Toast.LENGTH_SHORT).show();
}
#Override
public void onCancelled(DatabaseError databaseError) {
Toast.makeText(DuelGame.this, "Data error!", Toast.LENGTH_SHORT).show();
}
});
}
});
Button lose = (Button)findViewById(R.id.lose_POKE);
lose.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
losesRef = database.getReference();
losesRef.child("players/").child(playerName).child("/loses").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
dataSnapshot.getRef().setValue(lose_int = lose_int + 1);
Toast.makeText(DuelGame.this, "+1 Lose!", Toast.LENGTH_SHORT).show();
}
#Override
public void onCancelled(DatabaseError databaseError) {
Toast.makeText(DuelGame.this, "Data error!", Toast.LENGTH_SHORT).show();
}
});
}
});
In general, I want that every time I enter the activity, the number is not reset to zero, and Integer takes the number from the database and is based on them, and not on zero in the variable.
If you want to increment a value in the database, you can use the atomic increment operation:
Map updates = new HashMap();
updates.put("wins", ServerValue.increment(1));
database.getReference().child("players/").child(playerName).updateChildren(updates);

Get a specific nested child and count it

I making an Attendance App.
In the app there is a function to know how many event an users already attend and what event they attend.
What i want is something like this (i dont know if it work or there is a better way):
private void fetchSpecificEvent() {
//Fetch event that user already attend
FirebaseRecyclerOptions<ModelEvent> options = new FirebaseRecyclerOptions.Builder<ModelEvent>()
.setQuery(referenceForSpecificEvent, snapshot -> new ModelEvent(
Objects.requireNonNull(snapshot.child("eventID").getValue()).toString(),
...
...
...
)
.build();
...
}
private void getAttendanceCount(){
//Get how many event user already attend
referenceForCount.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
attendanceCount = (int) snapshot.getChildrenCount();
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
}
The main problem is i dont know what reference i use on: referenceForSpecificEvent and referenceForCount
This the JSON:
This the full JSON : https://pastebin.com/k65jhMUC
Sorry for the title, i dont know the keyword for it.
I found the way to do it. Probably not the best (because i cant really explain what i want) but it works.
reference = FirebaseDatabase.getInstance().getReference().child("Attendance");
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()){
for (DataSnapshot eventSnapshot: dataSnapshot.getChildren()) {
//Get Event ID
Log.i(TAG, eventSnapshot.getKey());
for (DataSnapshot userSnapshot: dataSnapshot.child(Objects.requireNonNull(eventSnapshot.getKey())).getChildren()) {
//Get User ID
//Log.i(TAG, userSnapshot.getKey());
if(Objects.equals(userSnapshot.getKey(), stringEmail)){
intCount++;
listEvent.add(eventSnapshot.getKey());
}
}
}
}
else{
Log.i(TAG, "No Value Found");
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
Log.d(TAG, error.getMessage()); //Don't ignore errors!
}
});

Compare data from RecyclerView with Realtime Database in Firebase

I'm making a Quizz app and I have the questions and the answers in Realtime Database,
I have no problem displaying the information in the recyclerview, this recycler view is composed of a radio group of 3 radio buttons,
I need to compare the radio button with the record of the correct answer in realtime database.
btnacab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
database.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
if(corregido == false){
//for(DataSnapshot dataSnapshot : snapshot.getChildren()){
int cont = 1;
String p = "p";
npreg = p + cont;
corregirpregunta("Enfermeria", "p1");
corregido = true;
btnacab.setText("SALIR");
cont++;
// }
}else{
Intent i = new Intent(ModeloExamen3.this, GeneralTest.class);
startActivity(i);
}
myAdapter.notifyDataSetChanged();
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
pauseTimer();
}
});
*/
}
public void corregirpregunta(String tipo, String npreg){
database.child(tipo).child(npreg).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
PreguntaExamen pregunta = snapshot.getValue(PreguntaExamen.class);
if(pregunta != null){
String corr = pregunta.getCorrecta();
int n = Integer.parseInt(corr.toString());
RadioButton rbselected = findViewById(rgrex.getCheckedRadioButtonId());
int nresp = rgrex.indexOfChild(rbselected) +1 ;
if(nresp == n){
puntuacion++;
tvpuntu.setText("PuntuaciĆ³n: " + puntuacion+"/10");
}
resp1.setTextColor(Color.RED);
resp2.setTextColor(Color.RED);
resp3.setTextColor(Color.RED);
switch (n){
case 1:
resp1.setTextColor(Color.GREEN);
break;
case 2:
resp2.setTextColor(Color.GREEN);
break;
case 3:
resp3.setTextColor(Color.GREEN);
break;
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
}
The method to correct a single question works well, the problem is to make a loop so that a single method corrects all the questions that are shown in the recyclerview.

Android Firebase Database check if Username is already use

hello i'm looking to create a way to check if the username is already in use or not.
The problem is that if the username is already taken the error is displayed correctly, but the user still registers ...
private boolean validateForm () {
boolean valid = true;
String username = rUsernameField.getText().toString();
String email = rEmailField.getText().toString();
if (TextUtils.isEmpty(email)) {
rEmailField.setError(getText(R.string.field_error));
valid = false;
} else {
rEmailField.setError(null);
}
String password = rPasswordField.getText().toString();
if (TextUtils.isEmpty(password)) {
rPasswordField.setError(getText(R.string.field_error));
valid = false;
} else {
rPasswordField.setError(null);
}
if (TextUtils.isEmpty(username)) {
rUsernameField.setError(getText(R.string.field_error));
valid = false;
validUsername = false;
} else {
rUsernameField.setError(null);
}
if (!validUsername) {
valid = false;
}
if (rCGUCheck.isChecked()) {
rCGUCheck.setError(null);
} else {
rCGUCheck.setError(getText(R.string.err_cgu));
valid = false;
}
return valid;
}
public void setValidUsername() {
String username = rUsernameField.getText().toString();
FirebaseDatabase.getInstance().getReference().child("users").orderByChild("username").equalTo(username).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
validUsername = false;
Log.d(TAG, "false");
rUsernameField.setError("This username already exists");
} else {
validUsername = true;
Log.d(TAG, "true");
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
private void signUp() {
Log.d(TAG, "signUp");
if (!validateForm()) {
return;
}
#Override
public void onClick (View v){
int i = v.getId();
if (i == R.id.regBtn) {
setValidUsername();
signUp();
}
therefore if one of the fields is not filled in, the user cannot register. But what I don't understand is why even if the username already exists the user can still register ^^
Thank's in advance.
Have one function called validateUser:
public void validateUser() {
//get string from editTexts
String username = rUsernameField.getText().toString();
String email = rEmailField.getText().toString();
String password = rPasswordField.getText().toString();
FirebaseDatabase.getInstance().getReference().child("users").orderByChild("username").equalTo(username).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
//username is not available
rUsernameField.setError("This username already exists");
} else {
//username is available
//so check now if all is okay
if(!TextUtils.isEmpty(email) && !TextUtils.isEmpty(password) && !TextUtils.isEmpty(username) && rCGUCheck.isChecked()){
signUp();
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
The signUp() method:
private void signUp(){
//sign up
Log.d(TAG, "signUp");
}
onclick() method
#Override
public void onClick (View v){
int i = v.getId();
if (i == R.id.regBtn) {
validateUser();
}
Your setValidUsername is an asynchronous operation. Data is loaded from Firebase asynchronously (like with most cloud APIs), since it may take some time to complete. While that is happening, you main code continues and your signUp method executes. Then when the data is available, your onDataChange is called and sets validUsername.
For a good example of this and a solution, see my answer here: getContactsFromFirebase() method return an empty list
For you this could mean:
Defining an interface for your own callback:
public interface UserExistsCallback {
void onCallback(boolean value);
}
Modify setValidUsername to take this callback as an argument, and call it:
public void isValidUsername(UserExistsCallback callback) {
String username = rUsernameField.getText().toString();
FirebaseDatabase.getInstance().getReference().child("users").orderByChild("username").equalTo(username).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
callback.onCallback(false);
rUsernameField.setError("This username already exists");
} else {
callback.onCallback(true);
Log.d(TAG, "true");
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
throw databaseError.toException(); // never ignore errors
}
});
}
Call this new function and use the value in the callback:
isValidUsername(new UserExistsCallback() {
#Override
public void onCallback(boolean exists) {
System.out.println("User exists: "+exists);
}
});

Check if a value exist in more then on child Firebase Database in Android

I'm developing an android application for college project using Java and Firebase. I want to store the details of faculties working in college like name,email,department etc based on their position. I have created 3 child nodes HOD,Class mentor and lecturers inside Faculties as you can see that in here.
my problem is when I want to add the members inside any one these child I want to check if that members email ID is exist in any other childs. For example I want to add a member in HOD child.If this members email existed inside Lecturers child it should display Toast user already existed as Lecturer else it should add member inside Lecturer.
I used this code.
post = "HOD";
databaseReference.child(post).orderByChild("email").equalTo(email).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()){
Toast.makeText(MainActivityAddFaculty.this, "User already exist in "+post, Toast.LENGTH_SHORT).show();
} else {
post = "Class mentor";
databaseReference.child(post).orderByChild("email").equalTo(email).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()){
Toast.makeText(MainActivityAddFaculty.this, "User already exist in "+post, Toast.LENGTH_SHORT).show();
} else {
post = "Lecturer";
databaseReference.child(post).orderByChild("email").equalTo(email).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()){
Toast.makeText(MainActivityAddFaculty.this, "User already exist in "+post, Toast.LENGTH_SHORT).show();
} else {
checkData();
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Toast.makeText(MainActivityAddFaculty.this, databaseError.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Toast.makeText(MainActivityAddFaculty.this, databaseError.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Toast.makeText(MainActivityAddFaculty.this, databaseError.getMessage(), Toast.LENGTH_SHORT).show();
}
});
It works fine but it's lengthy and also it takes time to check.If there is any better solution that would be very helpful.
This is is my code complete code for adding Faculties.
public class MainActivityAddFaculty extends AppCompatActivity {
private TextInputLayout addName, addEmail;
private TextInputEditText addEditName, addEditEmail;
private Button addBtn;
private Spinner addPositionSpinner,addDeptSpinner,addYearSpinner;
private TextView addPosition,addDept,addYear;
private String sDept = "Select department",sPost = "Select position",sYear = "Select year";
private String position,department,year,post;
private boolean b = false;
private FirebaseDatabase firebaseDatabase;
private FirebaseStorage firebaseStorage;
private DatabaseReference databaseReference,databaseReference2;
private StorageReference storageReference;
LoadingDialog loadingDialog;
private String facultyID;
private String name,email;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_faculty);
setTitle("Add Hod");
assert getSupportActionBar() != null;
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
addName = findViewById(R.id.addFName);
addEmail = findViewById(R.id.addFEmail);
addEditName = findViewById(R.id.addFEditName);
addEditEmail = findViewById(R.id.addFEditEmail);
addBtn = findViewById(R.id.addFBtn);
addPositionSpinner = findViewById(R.id.addFPositionSpinner);
addPosition = findViewById(R.id.addFPosition);
addDeptSpinner = findViewById(R.id.addFDepartmentSpinner);
addDept = findViewById(R.id.addFDepartment);
addYearSpinner = findViewById(R.id.addFYearSpinner);
addYear = findViewById(R.id.addFYear);
addDeptSpinner.setVisibility(View.GONE);
addYearSpinner.setVisibility(View.GONE);
addDept.setVisibility(View.GONE);
addYear.setVisibility(View.GONE);
firebaseDatabase = FirebaseDatabase.getInstance();
databaseReference = firebaseDatabase.getReference("FACULTIES");
facultyID = databaseReference.push().getKey();
loadingDialog = new LoadingDialog(MainActivityAddFaculty.this);
//selectPosition();
//TODO:Select position
List<String> categories = new ArrayList<>();
categories.add(0,"Select position");
categories.add("HOD");
categories.add("Class mentor");
categories.add("Lecturer");
ArrayAdapter<String> dataAdapter;
dataAdapter = new ArrayAdapter(this,android.R.layout.simple_spinner_item,categories);
dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
addPositionSpinner.setAdapter(dataAdapter);
addPositionSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
addPosition.setText(parent.getSelectedItem().toString());
test();
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
Toast.makeText(MainActivityAddFaculty.this, "Select a position", Toast.LENGTH_SHORT).show();
}
});
addBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
name = addEditName.getText().toString().trim();
email = addEditEmail.getText().toString().trim();
if (TextUtils.isEmpty(name)) {
Toast.makeText(MainActivityAddFaculty.this, "Enter name", Toast.LENGTH_SHORT).show();
}else {
if (TextUtils.isEmpty(email)) {
Toast.makeText(MainActivityAddFaculty.this, "Enter email.", Toast.LENGTH_SHORT).show();
} else {
checkData();
}
}
}
});
}
private void test(){
position = addPositionSpinner.getSelectedItem().toString();
if (position.equals(sPost)){
addDeptSpinner.setVisibility(View.GONE);
addYearSpinner.setVisibility(View.GONE);
addDept.setVisibility(View.GONE);
addYear.setVisibility(View.GONE);
}else if (position.equals("HOD")){
addDeptSpinner.setVisibility(View.VISIBLE);
addYearSpinner.setVisibility(View.GONE);
addDept.setVisibility(View.VISIBLE);
addYear.setVisibility(View.GONE);
} else if (position.equals("Class mentor")){
addDeptSpinner.setVisibility(View.VISIBLE);
addDept.setVisibility(View.VISIBLE);
addYearSpinner.setVisibility(View.VISIBLE);
addYear.setVisibility(View.VISIBLE);
} else if (position.equals("Lecturer")){
addDeptSpinner.setVisibility(View.GONE);
addYearSpinner.setVisibility(View.GONE);
addDept.setVisibility(View.GONE);
addYear.setVisibility(View.GONE);
} else {
addDeptSpinner.setVisibility(View.GONE);
addYearSpinner.setVisibility(View.GONE);
addDept.setVisibility(View.GONE);
addYear.setVisibility(View.GONE);
}
}
private void checkData(){
position = addPositionSpinner.getSelectedItem().toString();
department = addDeptSpinner.getSelectedItem().toString();
year = addYearSpinner.getSelectedItem().toString();
if (position.equals(sPost)){
Toast.makeText(this, "Select position", Toast.LENGTH_SHORT).show();
} else if (position.equals("HOD")){
if (department.equals(sDept)){
Toast.makeText(MainActivityAddFaculty.this, "Select department.", Toast.LENGTH_SHORT).show();
} else {
AddHOD addHOD = new AddHOD(name,position,department,email,facultyID);
databaseReference.child(position).child(facultyID).setValue(addHOD).addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
Toast.makeText(MainActivityAddFaculty.this, "Faculty added successfully", Toast.LENGTH_SHORT).show();
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(MainActivityAddFaculty.this, e.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
}else if (position.equals("Class mentor")){
//add Class mentor process started
if (!department.equals(sDept)){
if (!year.equals(sYear)) {
AddClassMentor addClassMentor = new AddClassMentor(name, position, department, year, email, facultyID);
databaseReference.child(position).child(facultyID).setValue(addClassMentor).addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
Toast.makeText(MainActivityAddFaculty.this, "Faculty added successfully", Toast.LENGTH_SHORT).show();
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(MainActivityAddFaculty.this, e.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}else {
Toast.makeText(this, "Select year.", Toast.LENGTH_SHORT).show();
}
} else {
Toast.makeText(this, "Select department", Toast.LENGTH_SHORT).show();
}
} else if (position.equals("Lecturer")){
AddLecturer addLecturer = new AddLecturer(name,position,email,facultyID);
databaseReference.child(position).child(facultyID).setValue(addLecturer).addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
Toast.makeText(MainActivityAddFaculty.this, "Faculty added successfully", Toast.LENGTH_SHORT).show();
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(MainActivityAddFaculty.this, e.getMessage(), Toast.LENGTH_SHORT).show();
}
});
} else {
Toast.makeText(this, "Entry is pending.", Toast.LENGTH_SHORT).show();
}
}
}
Firebase's queries work on a list of nodes. Since you have a hierarchy, you'll need to fire the same query for each list you have in there, as you're doing today.
As usual when dealing with NoSQL databases, the solution is to model the data in a way that makes the use-case easiest. If you want to search across all members, store a single list of members:
"members": {
"$memberid": {
"email": "membersemail#institute.edu",
"memberType": "Class mentor" // or "HOD" or "Lecturer"
}
}
With the above structure you only have to execute one query to find all members with a specific email address.
You can either use the above structure to replace the three structures you currently have, or you can use it as an additional structure just for this use-case. Which one to choose depends on the other use-cases in your app, there is no solution that is right for all apps, just the one that works for you.
Enforcing uniques across values as you're doing here, will lead to scalability issues over time, as you:
Need to search across all members, which takes more time as you get more members.
More importantly: you will need to use a transaction to insert new users, to reduce the chances that multiple users claim the same email address at the same time.
This leads to a second scaling problem, as you'll need to run that transaction on the evert-growing /members node.
Finally: a malicious user can bypass the transaction by writing their own code, and still claim any email address.
Ensuring uniqueness on Firebase is only really enforceable if you use those values as the key in a list, so by maintaining a (additional) list of email addresses.
For more on this see:
Firebase security rules to check unique value of a child #AskFirebase
Firebase android : make username unique
How do you prevent duplicate user properties in Firebase?
Firebase realtime database validation username and email

Categories