Greeting everyone, im working a project right now and need help for firebase realtime database.
My firebase Project
As you guys can see in the above picture, inside student, I have matric number, and inside matric number have block and department.
I have a barcode scanner which scan the value of department and return to get the matric number. Any solution.
Below code is my progress.
mCodeScanner.setDecodeCallback(new DecodeCallback() {
#Override
public void onDecoded(#NonNull final Result result) {
runOnUiThread(new Runnable() {
#Override
public void run() {
r = result.getText();
Query s = ref.equalTo("JTMK", "department");
name.setText(r);
}});}});
If you don't know the matric number of the student, indeed a query is required. Assuming that result.getText() returns JTMK, please use the following lines of code:
mCodeScanner.setDecodeCallback(new DecodeCallback() {
#Override
public void onDecoded(#NonNull final Result result) {
String department = result.getText();
DatabaseReference db = FirebaseDatabase.getInstance().getReference();
DatabaseReference studentRef = db.child("Student");
Query queryByDepartment = studentRef.orderByChild("department").equalTo(department).limitToFirst(1);
queryByDepartment.get().addOnCompleteListener(new OnCompleteListener<DataSnapshot>() {
#Override
public void onComplete(#NonNull Task<DataSnapshot> task) {
if (task.isSuccessful()) {
for (DataSnapshot ds : task.getResult().getChildren()) {
String block = ds.child("block").getValue(String.class);
name.setText(block);
Log.d("TAG", block);
}
} else {
Log.d("TAG", task.getException().getMessage()); //Never ignore potential errors!
}
}
});
}
});
Things to notice:
There is no need to use runOnUiThread when reading data from the Realtime Database.
Firebase API is asynchronous. So I recommend you read the following resource:
How to read data from Firebase Realtime Database using get()?
When you run the code, you should see in the logcat BESTARI 4, which will also be set to name TextView.
Related
I am working on an application where anyone can list their products. I am storing data in Firebase Firestore in nested collection Now I want to retrieve that data and show that on my home screen. Now the data is showing but the problem is that it is showing only when I am login in with that same number through that I list that data into Firebase but when I try to log in with another number the data doesn't show. I want that to show to everyone who logged in to the app. Basically My app is just like OLX where anyone can list anything which shows to everyone.
MY CODE TO RETRIEVE THE DATA
//CODE TO GET CURRENT ID OR USER
String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
//CODE TO GET THE DATA FROM FIREBASE
DocumentReference uidRef = firebaseFirestore.collection("listing_details").document(uid);
CollectionReference roomDetailsRef = uidRef.collection("room_details");
String doc_id = roomDetailsRef.document().getId();
roomDetailsRef.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
for (QueryDocumentSnapshot document : task.getResult()) {
if (document != null) {
RoomsDetails obj = document.toObject(RoomsDetails.class);
roomsDetails.add(obj);
}
}
roomsAdapter.notifyDataSetChanged();
} else {
Log.d(TAG, task.getException().getMessage()); //Never ignore potential errors!
}
}
});
You have .document(uid) in your path where UID is User ID of user currently logged in. When you use another phone number, that's a different user.
If you want to fetch room_details documents from all listing_details documents then you can use Collection Group queries like this:
db.collectionGroup("room_details").get()
.addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
#Override
public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
// ... iterate over all docs and render
}
});
So I am working on the memories Firebase app and there is a stage where the user can upload photos to his memory. Each photo has uniq name "ImgLink0","ImgLink1",etc..
The function I am working on is to delete a specific photo when I am pressing a long click, but I can't reach the image in Firebase.
I tried like below but I got stuck because I can't identify the image key:
mDatabase.child(userUID).child("Memories").child(memoryName).child("Images").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot imageSnapshot : dataSnapshot.getChildren()) {
String imagesKey = imageSnapshot.getKey();
String imagesValue = (String) imageSnapshot.getValue();
Log.e("Test","" + imagesKey + "" + imagesValue);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
And this is the data structure:
I tried using query too but with no success because I don't have the image key.
Thank you for any help :)
To delete a node from the database, you need to know the completely path to that node.
Assuming you do know the URL of the image to delete, but not the key (ImgLink1 or ImgLink2) that is stored under, you're going to have to use a query to look up that key.
Something like:
DatabaseReference ref = mDatabase.child(userUID).child("Memories").child(memoryName).child("Images");
Query query = ref.orderByValue().equalTo("URL of the image")
query..addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot imageSnapshot : dataSnapshot.getChildren()) {
imageSnapshot.getRef().removeValue();
}
}
...
Also see these related answer:
deleting specific post in database(by post node) but it deletes entire database_table
How can i remove all fields and values by using key value or a field key from firebase realtime database?
To remove the second URL for example, please use the following lines of code:
String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference imageToDeleteRef = rootRef
.child(uid)
.child("Memories")
.child("TestMem")
.child("Images")
.child("ImgLink1");
imageToDeleteRef.removeValue().addOnCompleteListener(/* ... */);
So I have created a reference that points exactly to ImgLink1 node and then I called .removeValue() on reference in order to delete it. So there is no need to read the value in order to perform a delete operation.
If you want to read the URL, please use these lines:
imageToDeleteRef.addOnCompleteListener(new OnCompleteListener<DataSnapshot>() {
#Override
public void onComplete(#NonNull Task<DataSnapshot> task) {
if (task.isSuccessful()) {
String url1 = task.getResult().child("ImgLink1").getValue(String.class);
Log.d("TAG", url1);
} else {
Log.d("TAG", task.getException().getMessage()); //Don't ignore potential errors!
}
}
});
The result in the logcat will be:
https://firebasestorage.googleapis.com...
I have Firebase node that look like this
How can i make a condition if (name.equalsTo("someValue") to scan database inside campus and get reference to node with key? I this case, i want to get reference or key of kazjap
To find the node under /campus/building where name has a certain value, you can use a query like this:
DatabaseReference ref = FirebaseDatabase.getInstance().getReference("campus/building");
Query query = ref.orderByChild("name").equalTo("someValue");
And then read the results of the query with:
query.get().addOnCompleteListener(new OnCompleteListener<DataSnapshot>() {
#Override
public void onComplete(#NonNull Task<DataSnapshot> task) {
if (!task.isSuccessful()) {
Log.e("firebase", "Error getting data", task.getException());
}
else {
for (DataSnapshot childSnapshot: task.getResult().getChildren()) {
Log.d("firebase", String.valueOf(childSnapshot.getKey()));
}
}
}
});
Or:
query.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot childSnapshot: dataSnapshot.getChildren()) {
// Handle the data
Log.d("TAG", childSnapshot.getKey())
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
// Getting User failed, log a message
Log.w("firebase", "Error getting data", databaseError.toException());
// ...
}
});
Firebase queries only work on direct child nodes, so this only works if you know the /campus/building part of the path already. There is no way to search across the entire campus for a building by its name in any campus. For more on that, see Firebase Query Double Nested
I'm just starting to learn android studio and I'm working on a location-based project to insert location information into Firebase. I followed tutorial from youtube [https://www.youtube.com/watch?v=CwxdfamaCrk], however in the video only shows insert data from the code which is like this;
infectedArea = new ArrayList<>();
infectedArea.add(new LatLng(2.2258162, 102.4497224));
infectedArea.add(new LatLng(2.2252313, 102.4563797));
infectedArea.add(new LatLng(2.2261818, 102.4551067));
infectedArea.add(new LatLng(2.275295,102.444035));
FirebaseDatabase.getInstance()
.getReference("InfectedArea")
.child("Location")
.setValue(infectedArea)
.addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
Toast.makeText(MapsActivity.this, "Updated!", Toast.LENGTH_SHORT).show();
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(MapsActivity.this, ""+e.getMessage(), Toast.LENGTH_SHORT).show();
}
});
Below are the snapshot of my firebase.
The one with index 0, 1, 2 and 3 are inserted from the code. Now I'm trying to continue inserting data from an input form but random key was generated and new geofence cannot be created. Is there anyway to continue inserting data with hard key?
I was thinking on removing the hard key and just use the generated key but then I have no idea how to alter the code to create multiple geofence.
Firebase intentionally doesn't offer an operation for inserting items with a sequential numeric key. See:
the documentation on structuring data
The classic blog post on best practices when using arrays in Firebase
How to create auto incremented key in Firebase?
That said, you can use array-like structures with sequential numerical indexes, and you can use auto-ids. So let's look at each in turn.
Using sequential numerical indexes
To add a new item with key 4 to your current structure, you will need to:
Determine the highest key
Add a child node with one key higher
In its simplest format, that looks like this (on Android):
FirebaseDatabase.getInstance()
.getReference("InfectedArea")
.child("Location")
.runTransaction(new Transaction.Handler() {
#Override
public Transaction.Result doTransaction(MutableData mutableData) {
String lastKey = "-1";
for (MutableData child: mutableData.getChildren) {
lastKey = child.getKey();
}
int nextKey = Integer.parseInt(lastKey) + 1;
mutableData.child("" + nextKey).setValue("your next value here");
// Set value and report transaction success
return Transaction.success(mutableData);
}
#Override
public void onComplete(DatabaseError databaseError, boolean b,
DataSnapshot dataSnapshot) {
// Transaction completed
Log.d(TAG, "Transaction:onComplete:" + databaseError);
}
});
As you can see that is quite a lot of code. This is largely needed because multiple users may be accessing the same location at almost the same time, and we need to handle this. Firebase uses optimistic locking, but the above may still be come a serious bottleneck when there are multiple users. Plus: this is a lot more complex than your simple push().setValue(...).
Use auto-ids for your initial set of data, and for new data
You can easily write all points with push IDs (those are the keys that push() generates), once you realize that calling only push() doesn't yet write to the database. You can get a new push ID in pure Android code with:
String pushID = ref.push().getKey();
Knowing this, we can change your code to insert the initial locations to:
DatabaseReference ref = FirebaseDatabase.getInstance().getReference();
// It doesn't matter what the reference points to, as push IDs are statistically guaranteed to be unique, independent of their location.
Map<String, Object> values = new HashMap<>();
infectedArea.put(ref.push().getKey(), new LatLng(2.2258162, 102.4497224));
infectedArea.put(ref.push().getKey(), new LatLng(2.2252313, 102.4563797));
infectedArea.put(ref.push().getKey(), new LatLng(2.2261818, 102.4551067));
infectedArea.put(ref.push().getKey(), new LatLng(2.275295,102.444035));
FirebaseDatabase.getInstance()
.getReference("InfectedArea")
.child("Location")
.setValue(values)
.addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
Toast.makeText(MapsActivity.this, "Updated!", Toast.LENGTH_SHORT).show();
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(MapsActivity.this, ""+e.getMessage(), Toast.LENGTH_SHORT).show();
}
});
This will result in a similar structure as you know have, but then with all keys being push IDs.
it will stockpile at HashMap, so you can getkey to get random key, and you get random key you can insert data
DatabaseReference database = FirebaseDatabase.getInstance().getReference("InfectedArea").child("Location");
database_course.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for(DataSnapshot ds :dataSnapshot.getChildren()){
String key = ds.getKey();
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
Query sqlite = mDatabaseReference.child("Messages").child(MessageSenderId).child(MessageRecieverId);
sqlite.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.hasChild("Message")) {
String msg = dataSnapshot.child("Message").getValue().toString();
String from = dataSnapshot.child("From").getValue().toString();
String time = dataSnapshot.child("Time").getValue().toString();
} else {
Toast.makeText(getApplicationContext(), "NULLLL", Toast.LENGTH_SHORT).show();
}
Database
This is the most basic thing in the database. I have never got a problem with childEvent or valueEvent and i want a single event for now and I'm not able to fetch.
There is no error because i have put an if statement and it shows toast as null which means dataSnapshot doesn't have a child named messages but it's right there. I tried putting a for loop too, but didn't work
You have not given the full reference. There is a list of push keys and you have to use a foreach loop.
Query sqlite = mDatabaseReference.child("Messages").child(MessageSenderId).child(MessageRecieverId);
sqlite.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot vinSnapshot : dataSnapshot.getChildren()) {
if (vinSnapshot .hasChild("Message")) {
String msg = dataSnapshot.child("Message").getValue().toString();
String from = dataSnapshot.child("From").getValue().toString();
String time = dataSnapshot.child("Time").getValue().toString();
} else {
Toast.makeText(getApplicationContext(), "NULLLL", Toast.LENGTH_SHORT).show();
}
}
Or you can store all data into ArrayList then perform your task.