I've written an android app using Firebase as the backend. My problem is only one item can be stored in Firebase and when I try to write more data it replaces the existing data. I want to write multiple bits and data and retrieve them in a list view or something.
My Code is below:
public class Capture_Meetings extends AppCompatActivity {
private EditText editTextName;
private EditText editTextAddress;
private EditText editDateTime;
private TextView textViewPersons;
private Button buttonSave;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_capture__meetings);
Firebase.setAndroidContext(this);
buttonSave = (Button) findViewById(R.id.buttonSave);
editTextName = (EditText) findViewById(R.id.editTextName);
editTextAddress = (EditText) findViewById(R.id.editTextAddress);
editDateTime = (EditText) findViewById(R.id.editDateTime);
textViewPersons = (TextView) findViewById(R.id.textViewPersons);
buttonSave.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Creating firebase object
Firebase ref = new Firebase(Config.FIREBASE_URL);
//Getting values to store
String name = editTextName.getText().toString().trim();
String address = editTextAddress.getText().toString().trim();
String DateTime = editDateTime.getText().toString().trim();
//Creating Person object
final MeetingUser person = new MeetingUser();
//Adding values
person.setName(name);
person.setAddress(address);
person.setDateTime(DateTime);
//Storing values to firebase
ref.child("Person").setValue(person);
//Value event listener for realtime data update
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot)
{
for (DataSnapshot postSnapshot : snapshot.getChildren()) {
//Getting the data from snapshot
MeetingUser person = postSnapshot.getValue(MeetingUser.class);
//Adding it to a string
String string = "\n Name of School: "+person.getName()+"\n Date:"+ person.getDateTime()+"\nMeeting Notes: "+person.getAddress()+"\n\n";
//Displaying it on textview
textViewPersons.setText(string);
}
}
#Override
public void onCancelled(FirebaseError firebaseError) {
System.out.println("The read failed: " + firebaseError.getMessage());
}
});
}
});
}
Have a look at the Firebase documentation. You can use the push method to append data to a node, which will have a unique id.
in Firebase you can not store many items/values under one child. But, you can make as many childs (children) with a single value as you want. Just make childs with tags s.a. "address" and "name" with their respective values.
To avoid overwriting of data we can use push() method in following way-
from your code -
ref.child("Person").setValue(person);
just put push() before setValue() method, that is -
ref.child("Person").push().setValue(person);
It will avoid overwriting and it will create a unique id for each data you store under the Person.
Related
This question already has answers here:
Duplicate objects from Firebase loaded into ListView
(2 answers)
Closed 1 year ago.
I am trying to add the teacher to the firebase real-time DB and Retrieving the teachers in the listView as shown in this image:
But when add a new item I get retrieved the existing data twice and new data once as shown in the picture below:
After Adding - Leading the Duplication of the ListView
''' //value variables
ArrayList<teachersHelper> teachersFromdatabase = new ArrayList<>();
teacher_adapter teacher_adapter;
THIS METHOD IS CALLED ON ONCLICK OF ADDTEACHERS
private void addingteacher() {
progressBar.setVisibility(View.VISIBLE);
// opening the Custom dialog to get the information of the new Teachers
Dialog mydialog = new Dialog(teacher_admin.this);
mydialog.setContentView(R.layout.addteachers);
mydialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
progressBar.setVisibility(View.GONE);
mydialog.show();
mydialog.setOnDismissListener(dialog -> progressBar.setVisibility(View.GONE));
// hooking all the views of the dialog
EditText teache5rName = mydialog.findViewById(R.id.teacherssname_dialogbox);
EditText registrationNumber = mydialog.findViewById(R.id.teachersReg_dialogbox);
EditText passwordteacher = mydialog.findViewById(R.id.teacherspassword_dialogbox);
EditText department = mydialog.findViewById(R.id.teachersDepartment_dialogbox);
EditText mobilenumber = mydialog.findViewById(R.id.teacherMobilenumber_dialogbox);
NeumorphButton addteachersButton = mydialog.findViewById(R.id.add_teachersDialog);
// when the add button on the dialog is pressed
addteachersButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// dilog and progress bar
progressBar.setVisibility(View.VISIBLE);
//converting the edittext the String Literals
String tnamez = teache5rName.getEditableText().toString().trim();
String tregNu = registrationNumber.getEditableText().toString().trim();
String tpassw = passwordteacher.getEditableText().toString().trim();
String tdepartment = department.getEditableText().toString().trim();
String tmobileNum = "+91" + mobilenumber.getEditableText().toString().trim();
// validating the fields wheather they are empty or not
if (!validateFields(tnamez, tregNu, tpassw, tdepartment, tmobileNum)) {
// if empty then show a error custom dialog
donedialogboxMeathod(false);
progressBar.setVisibility(View.GONE);
return;
}
donedialogboxMeathod(true);
// where the teachers are under so the adding teacher fuction is in admin so
// adminhelper is created and called the function
AdminHelper adminHelper = new AdminHelper();
// adding the teacher
adminHelper.addTEachers(tnamez, tregNu, tpassw, "No", tdepartment,
"No", tmobileNum, "No");
// notifyin the adpater that we added new ber
teacher_adapter.notifyDataSetChanged();
// dissmissing the progressbar and Custom dialog
progressBar.setVisibility(View.GONE);
mydialog.dismiss();
}
});
THIS METHOD IN ADMINHELPER TO ADDTEACHERS
public teachersHelper addteacher(String tName, String tregNumber, String tPassword,String
imageId, String tDepartment,String tEmail, String
tphoneNumber, String tadress) {
// creating the teachers Helper Class
teachersHelper teachersHelpers = new teachersHelper(tName, tregNumber, tPassword, imageId, tDepartment,
tEmail, tphoneNumber, tadress);
// database stuff
DatabaseReference teacherreferenc = FirebaseDatabase.getInstance().
getReference("Admin").child(mAuth.getUid()).child("INSTITUTE");
//adding value
teacherreferenc.child("TEACHERS").child(tregNumber).setValue(teachersHelpers);
return teachersHelpers;
}
RETRIEVING THE TEACHERS AND ADDING THEM TO THE LISTVIEW (i think the problem is here)
public void settingViews(){
// Firebase variables to retreive the data of the teacher
FirebaseAuth mAuth = FirebaseAuth.getInstance();
DatabaseReference databasereference = FirebaseDatabase.getInstance()
.getReference("Admin").child(mAuth.getUid()).child("INSTITUTE")
.child("TEACHERS");
//the teachers are stored with the node of registrationNumber so i created a arraylist
ArrayList<String> registrattionNumber = new ArrayList<>();
// valueevent to retreving the data
databasereference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
// cheching if the snapshot exists
if (snapshot.exists()) {
// getting all the registration Number
for (DataSnapshot regis : snapshot.getChildren()) {
// adding the registrationNumbers to the arraylist
registrattionNumber.add(regis.getKey());
}
// based on the arraylist of the registrationNUmber we will be retriving
// the data of teachers of particular registrartion Number
for (int i = 0; i < registrattionNumber.size(); i++) {
//firebase stuff
Query teacherssdata = FirebaseDatabase.getInstance()
.getReference("Admin").child(mAuth.getUid()).child("INSTITUTE")
.child("TEACHERS").child(registrattionNumber.get(i));
// value evnet listener
teacherssdata.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
if (snapshot.exists()) {
// retreiving all the teachers data from the snapshot
String _name = snapshot.child("tName").getValue().toString();
String _regno = snapshot.child("tregNumber").getValue().toString();
String _pass = snapshot.child("tPassword").getValue().toString();
String _img = snapshot.child("image").getValue().toString();
String _depart = snapshot.child("tDepartment").getValue().toString();
String _phonenumber = snapshot.child("tphoneNumber").getValue().toString();
String _adress = snapshot.child("tadress").getValue().toString();
String _emai = snapshot.child("tEmail").getValue().toString();
// creating the teacherclass and adding all the info from the firebase
teachersHelper teachersHelperzzzz = new
teachersHelper(_name, _regno, _pass, _img, _depart, _emai
, _phonenumber, _adress);
// adding the teacher objects to the Golbal Variable
teachersFromdatabase.add(teachersHelperzzzz);
// creating listview
// creating the adapter
teacher_adapter = new teacher_adapter(teacher_admin.this,
teachersFromdatabase);
// setting the adapter to the listview
listView.setAdapter(teacher_adapter);
progressBar.setVisibility(View.GONE);
} else {
progressBar.setVisibility(View.VISIBLE);
StyleableToast.makeText(teacher_admin.this, "Deleted Sucessfully"
, R.style.exampleToast).show();
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
dialogboxMeathod(teacher_admin.this, error.getMessage());
}
});}
Every time there's a change to databasereference, your onDataChange gets called with a full snapshot of the data at that path. So even if only one child node was changed/added/removed, the snapshot also contains all other (unmodified) child nodes that you already added to registrattionNumber.
The simplest solution is to clear registrattionNumber at the top of onDataChange:
databasereference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
registrattionNumber.clear();
...
Also see:
Duplicate objects from Firebase loaded into ListView
Duplicate data from firebase realtime databse
Item gets duplicated in adapter, when we delete or update item from Firebase Realtime Database
Why do i get duplicate values when adding data to firebase realtime database using kotlin?
And many more from this search: https://stackoverflow.com/search?q=%5Bfirebase-realtime-database%5D%5Bandroid%5D+duplicate
I am trying to implement a functionality in my app such that if the user chooses a restaurant, a list of items that are available in the restaurant are displayed and if there are none, it displays a text and a button.
I went about it like this:I would compare two child items, the restaurant names to check if they are equal.If they are, it displays a recyclerview with a list of the items available.
Here's a screenshot of my firebase database
Here's the code snippet of how I save to the FoodRequestRest database child
requestPlceTxt = placeTxt.getText().toString();
System.out.println("First instance of Request place her : " + requestPlceTxt);
FirebaseUser user = mAuth.getCurrentUser();
userID = user.getUid();
// String id = UserReqPlaceRef.push().getKey();
Request request = new Request(requestPlceTxt);
// save to database
UserReqPlaceRef.child("Food Request Restaurant")
.child(userID)
.push()
.setValue(request);
Here's the code snippet of how I retrieve the database and display it on the recycler view
// Initialize FirebaseAuth
mFirebaseAuth = FirebaseAuth.getInstance();
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
final RecyclerView recyclerView = (RecyclerView) findViewById(R.id.dummyfrag_scrollableview);
noItemsTxt = (TextView) findViewById(R.id.no_items);
OkExitBtn = (Button) findViewById(R.id.ok_exit);
recyclerView.setLayoutManager(linearLayoutManager);
recyclerView.setHasFixedSize(true);
linearLayoutManager.setReverseLayout(true);
linearLayoutManager.setStackFromEnd(true);
final List<Donation> donationList = new ArrayList<Donation>();
final DonationAdapter adapter = new DonationAdapter(donationList, this);
recyclerView.setAdapter(adapter);
noItemsTxt.setVisibility(View.GONE);
OkExitBtn.setVisibility(View.GONE);
final String curtUserId = FirebaseAuth.getInstance().getCurrentUser().getUid();
final FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference rootRef = database.getReference();
// get key for each restuarant chosen to make a donation
final String donateId = rootRef.child("All Donations").getKey();
// get key each restuarant chosen to make a request
final String requestId = rootRef.child("Food Request Restaurant").child(curtUserId).getKey();
final Query latestQuery = rootRef
.child("All Donations")
// .child(curtUserId)
.orderByKey()
.limitToFirst(50);
final DatabaseReference reqRestLoc = rootRef
.child("Food Request Restaurant")
.child(curtUserId)
.child(requestId);
// code here to retrieve the string value located at reqRestLoc
// then compare it with donateRest
// make another value event listener and get the string?
latestQuery.addValueEventListener(new com.google.firebase.database.ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
donationList.clear();
for (DataSnapshot gigSnapshot : dataSnapshot.getChildren()) {
Donation donation = gigSnapshot
.getValue(Donation.class);
donationList.add(donation);
adapter.notifyDataSetChanged();
String donateRest = (String) dataSnapshot
.child("All Donaations")
.child(donateId)
.getValue();
Log.d(donateRest, "This is the ");
if (s.equals(donateRest)) { // s is the string value gotten from the restReqLoc
recyclerView.setVisibility(View.VISIBLE);
noItemsTxt.setVisibility(View.GONE);
OkExitBtn.setVisibility(View.GONE);
OkExitBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
DisplayItems.super.onBackPressed();
}
});
}
else {
recyclerView.setVisibility(View.GONE);
noItemsTxt.setVisibility(View.VISIBLE);
OkExitBtn.setVisibility(View.VISIBLE);
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
I have tried different ways of comparing the two strings but I do not have access to both of these data items at the same time, it's either I make a reference to the child of All Donations or FoodRequestRestuarant. Is there a way I can do this?
I have a Firebase database which I can read from and write to from my Android App. However, I am having problems with one aspect of the read.
Users can set up an account in the App (Firebase email and password) and are taken to a data input screen and save that information to Firebase using this structure:
myAndroidApp
users
21XKq2RXQYZ36l363msI26XOKdn2
description:
emailAddress:
name:
ownerName:
..... etc.
I have a PropertyData Java Class.
The code for saving the data is:
PropertyData propertyData = new PropertyData(ownerName, headline, description....... etc.);
String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
databasePropertyData.child(uid).setValue(propertyData);
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot childSnapShot : dataSnapshot.getChildren()) {
String propNameTxt = (String) childSnapShot.child("name").getValue();
String ownerNameTxt = (String) childSnapShot.child("ownerName").getValue();
So that all seems to work fine and I can log in to different test users and write to the Firebase database.
But what I want is for any existing information in the database to be downloaded and populate the data entry form when the user next signs in. The code I have written does this, but when I sign out of the test account and sign into a different one the data entry form is populated by the previous account!! I thought I was using the Uid correctly but obviously not!
When signed into an account if I change the info in the data entry form it does save it to the correct node. So the problem is with the downloading of existing data on startup.
This is the code for downloading existing data to the data entry form:
databasePropertyData = FirebaseDatabase.getInstance().getReference("users");
String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
//FirebaseDatabase.getInstance().getReference().child(uid).addValueEventListener(new ValueEventListener() {
//FirebaseDatabase.getInstance().getReference().child("users").child(uid).addValueEventListener(new ValueEventListener() {
FirebaseDatabase.getInstance().getReference().child("users").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot childSnapShot : dataSnapshot.getChildren()) {
String propNameTxt = (String) childSnapShot.child("name").getValue();
String ownerNameTxt = (String) childSnapShot.child("ownerName").getValue();
String headlineTxt = (String) childSnapShot.child("headline").getValue();
String descriptionTxt = (String) childSnapShot.child("description").getValue();
....... etc.
I have tried different variations on the listener without success. Any help/suggestions appreciated.
You cannot use child("users" + uid). To solve this, you have two options:
.child("users").child(uid)
or
child("users/" + uid)
Remember, every node in a Firebase database has it's url.
In order to get the from a single authenticated user, you don't need use getChildren() method. You also don't need to use addValueEventListener, you only need to use addListenerForSingleValueEvent. Please see the following code:
String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference uidRef = rootRef.child("users").child(uid);
ValueEventListener eventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String propNameTxt = dataSnapshot.child("name").getValue(String.class);
String ownerNameTxt = dataSnapshot.child("ownerName").getValue(String.class);
String headlineTxt = dataSnapshot.child("headline").getValue(String.class);
String descriptionTxt = dataSnapshot.child("description").getValue(String.class);
}
#Override
public void onCancelled(DatabaseError databaseError) {}
};
uidRef.addListenerForSingleValueEvent(eventListener);
You set the database accurate address till where you want to get all the elements on databaseReference as you want. Then get the specific element you want to be store by its unique key Ex :- dataSnapshot.child("name").getValue().toString(); i hope it will help you else reply what you have confusion about firebase connectivity.
private String CurrentUserID;
private DatabaseReference databaseReference
//Outside of Oncreate for user Detection
#Override
protected void onStart(){
super.onStart();
mAuth.addAuthStateListener(mauthListener);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_profile);
mAuth = FirebaseAuth.getInstance();
mauthListener = new FirebaseAuth.AuthStateListener() {
#Override
public void onAuthStateChanged(#NonNull FirebaseAuth firebaseAuth) {
if (firebaseAuth.getCurrentUser() != null){
CurrentUserID = firebaseAuth.getCurrentUser().getUid();
}
databaseReference = FirebaseDatabase.getInstance().getReference().getRoot().child("myAndroidApp").child("users").child(CurrentUserID);
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String propNameTxt = dataSnapshot.child("name").getValue().toString();
String ownerNameTxt = dataSnapshot.child("ownerName").getValue().toString();
String headlineTxt = dataSnapshot.child("headline").getValue().toString();
String descriptionTxt = dataSnapshot.child("description").getValue().toString();
}
}
}
First of all use ...child("users/" + uid)... instead of ...child("users" + uid).... Because you will get the child "users21XKq2RXQYZ36l363msI26XOKdn2".
Second:
for(DataSnapshot childSnapShot : dataSnapshot.getChildren()) in your listener already gets child one by one in "users/21XKq2RXQYZ36l363msI26XOKdn2". So right now you are trying to get the value of "users/21XKq2RXQYZ36l363msI26XOKdn2/name/name", "users/21XKq2RXQYZ36l363msI26XOKdn2/description/name" and others. I offer you than do it without for cycle.
Like this:
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String propNameTxt = (String) dataSnapshot.child("name").getValue();
String ownerNameTxt = (String) dataSnapshot.child("ownerName").getValue();
String headlineTxt = (String) dataSnapshot.child("headline").getValue();
String descriptionTxt = (String) dataSnapshot.child("description").getValue();
}
Also you can create data class with setters and getters for these parameters (name, ownerName, headline, description) and use it to get all data.
Like this:
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
MyData data = (MyData) dataSnapshot.getValue(MyData.class);
}
Then you can get your field value using getter: data.getName(). I am offering setters and getters because you can insert there some validation.
If you are using data class for Firebase make sure it has an empty constructor.
More about it in my other answer: https://stackoverflow.com/a/48868970/5272951
Hi I am making an app where you enter a number in an EditText, if that number matches with some key from the database in Firebase it will show up the value of that key in a TextView.
Here's the structure of the database:
Structure DB
The problem i have is that when i enter "1" in my EditText and it searches for the key that matches with it in the database i can retrieve the value of it because it's the first child (i guess) but when i enter another key (2-5) it says that doesn't exists because of the else sentence in my code.
I think i'm not iterating the full database so i can retrieve the correct value.
Here's the code:
public class MainActivity extends AppCompatActivity {
private DatabaseReference mDatabase;
private TextView mEstado ;
private Button B_buscar;
private EditText E_buscar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDatabase = FirebaseDatabase.getInstance().getReference().child("no_orden");
mEstado = (TextView) findViewById(R.id.estado);
B_buscar = (Button) findViewById(R.id.B_buscar);
E_buscar = (EditText) findViewById(R.id.E_buscar);
B_buscar.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final String buscar = E_buscar.getText().toString().trim();
mDatabase.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
DataSnapshot estado = dataSnapshot.getChildren().iterator().next();
if (estado.getKey().toString().equals(buscar)){
mEstado.setText("The number #" + buscar + " contains: " + estado);
}else{
if (buscar.equals("")){
mEstado.setText("Enter a valid number.");
}else {
mEstado.setText("The number #" + buscar + " doesn't exists.");
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
});
}}
Hope someone can help me.
Thanks.
You can use a for iterator like this:
for (DataSnapshot postSnapshot: dataSnapshot.getChildren()) {
Log.d(TAG, "Key: "+postSnapshot.getKey());
Log.d(TAG, "Value: "+postSnapshot.getValue());
}
So you are trying to send a string called buscar and you want to check its existance, I suggest you do this :
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
//in this part of your code use this
if(dataSnapshot.hasChild(buscar)){
//this means the number is found in the database
}else{
//this means the number is not found in the database
}
}
The retrieve time should be display below the Time textview
I want to fetch the stored time and display it user.
How to do it?
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference myRef = database.getReference("user_time_table");
myRef.child("Y71VckCvTPVyqLCtrSQNHRiThsc2").child("Mondey").child("time").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String time = dataSnapshot.getValue(String.class);
myEditText.setText(time);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
This is hardcoded solution. If you want to make it more flexible, you can change "Y71VckCvTPVyqLCtrSQNHRiThsc2" to current user's id, for example:
FirebaseUser user = firebaseAuth.getCurrentUser();
String id = user.getUid();
and then use this id instead of hardcoded String.
String x = String.valueOf(drposts.getTime());
long milliSeconds= Long.parseLong(x);
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
String dateAsString = sdf.format (milliSeconds);
myEditText.setText(dateAsString );
//first convert the time value in string and store into it long after that
//define the simple date format and store it again in string and pass it text view
//drposts is my object class u an use
//String x = dataSnapshot.getValue(String.class);