In my app I want to add data to my Firebase database and read the data simultaneously. So I am using addChildEventListener() method to retrieve data. But this method is not working and the app is getting crashed everytime.
The code is given below:
public class ChatActivity extends AppCompatActivity {
LinearLayout layout;
RelativeLayout layout_2;
ImageView sendButton;
EditText messageArea;
ScrollView scrollView;
//Firebase reference1, reference2;
private DatabaseReference reference1, reference2,reference3;
private FirebaseAuth firebaseAuth;
private FirebaseUser firebaseUser;
private String username,userId;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat);
layout = (LinearLayout) findViewById(R.id.layout1);
layout_2 = (RelativeLayout)findViewById(R.id.layout2);
sendButton = (ImageView)findViewById(R.id.sendButton);
messageArea = (EditText)findViewById(R.id.messageArea);
scrollView = (ScrollView)findViewById(R.id.scrollView);
username=getIntent().getStringExtra("abc");
userId=getIntent().getStringExtra("abcd");
reference1= FirebaseDatabase.getInstance().getReferenceFromUrl("https://career-dna-bec2e.firebaseio.com/CHAT/user/" +username);
reference2=FirebaseDatabase.getInstance().getReferenceFromUrl("https://career-dna-bec2e.firebaseio.com/CHAT/admin/"+username);
sendButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String messageText = messageArea.getText().toString();
if(!messageText.equals("")){
Map<String, String> map = new HashMap<String, String>();
map.put("message", messageText);
map.put("user",userId);
reference1.push().setValue(map);
reference2.push().setValue(map);
messageArea.setText("");
}
}
});
try
{
reference1.addChildEventListener(new com.google.firebase.database.ChildEventListener() {
#Override
public void onChildAdded(com.google.firebase.database.DataSnapshot dataSnapshot, String s) {
Map<String, String> map = dataSnapshot.getValue(Map.class);
String message = map.get("message").toString();
String userName = map.get("user").toString();
if(userName.equals(userId)){
addMessageBox("You:-\n" + message, 1);
}
else{
addMessageBox("admin"+ ":-\n" + message, 2);
}
}
#Override
public void onChildChanged(com.google.firebase.database.DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(com.google.firebase.database.DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(com.google.firebase.database.DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
catch (Exception e)
{
Toast.makeText(getApplicationContext(),"error:"+e,Toast.LENGTH_SHORT).show();
}
}
The app is crashing with this error:
02-23 20:43:15.832 12583-12583/com.ankush.anthroplace.careerdna
E/AndroidRuntime: FATAL EXCEPTION: main Process:
com.ankush.anthroplace.careerdna, PID: 12583
com.google.firebase.database.DatabaseException: Class java.util.Map
has generic type parameters, please use GenericTypeIndicator instead
Try using :
Map<String, Object> map = new HashMap<String, Object>();
While retrieving data use this :
Map<String, Object> map = dataSnapshot.getValue(Map.class);
But, if you really want to use Map class with 2 Strings as parameters, use this inside onChildAdded method :-
GenericTypeIndicator<Map<String, String>> genericTypeIndicator = new GenericTypeIndicator<Map<String, String>>() {};
Map<String, String> map = dataSnapshot.getValue(genericTypeIndicator);
There's no need to enter the full URL, use this instead
DatabaseReference reference1 = FirebaseDatabase.getInstance().getReference().child("CHAT").child("user").child(username);
DatabaseReference reference2 = FirebaseDatabase.getInstance().getReference().child("CHAT").child("admin").child(username);
And, one more thing you are doing wrong is, you are adding ChildEventListener everytime the sendButton is clicked, which is not neccesary, just create a ChildEventListener inside onCreate() and not in onClick() like this:-
ChildEventListener childEventListener = new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Map<String, String> map = dataSnapshot.getValue(Map.class);
String message = map.get("message").toString();
String userName = map.get("user").toString();
if(userName.equals(userId)){
addMessageBox("You:-\n" + message, 1);
}
else{
addMessageBox("admin"+ ":-\n" + message, 2);
}
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.e("TAG", databaseError.toString());
}
};
//attaching the ChildEventListener to the DatabaseReference
reference1.addChildEventListener(childEventListener);
Don't forget to remove the listener in onStop()
#Override
protected void onStop() {
super.onStop();
reference1.removeEventListener(childEventListener);
}
I have solved the problem myself by using an object to store the data instead of hashmap. I am not sure why map is not working,but use of object is doing fine.
the code is given below:
sendButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String messageText = messageArea.getText().toString();
if(!messageText.equals("")){
map=new messageModel(messageText,userId);
reference1.child(""+n).setValue(map).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if(task.isSuccessful())
{
reference2.child(""+n2).setValue(map).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if(task.isSuccessful())
{
messageArea.setText("");
}
}
});
}
else
{
Toast.makeText(getApplicationContext(),"server problem try again",Toast.LENGTH_SHORT).show();
}
}
});
}
}
});
try
{
reference1.addChildEventListener(new com.google.firebase.database.ChildEventListener() {
#Override
public void onChildAdded(com.google.firebase.database.DataSnapshot dataSnapshot, String s) {
map = dataSnapshot.getValue(messageModel.class);
String message = map.myMessage;
String userName = map.user;
if(userName.equals(userId)){
addMessageBox("You:\n" + message, 1);
}
else{
addMessageBox("USER:\n" + message, 2);
}
}
#Override
public void onChildChanged(com.google.firebase.database.DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(com.google.firebase.database.DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(com.google.firebase.database.DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
catch (Exception e)
{
Toast.makeText(getApplicationContext(),"error:"+e,Toast.LENGTH_SHORT).show();
}
as u can see no part of the code has been changed except the map portion.The code of messageModel class is as following:
public class messageModel {
public String myMessage;
public String user;
public messageModel()
{
}
public messageModel(String a,String b)
{
myMessage=a;
user=b;
}
}
Related
I am fetching data and adding it to List from firebase database.
Now i want to sort the list data based on time so that latest data will appear first on the list and then setting the updated list into my RecyclerView.Adapter. I have tried layoutmanager.setReverseLayout(true); and layoutmanager.setStackFromEnd(true); for reversing the RecyclerView but it always shows data from the middle and also I don't want to follow this method.
How can i do that.
public class HistoryActivity extends AppCompatActivity{
private String customerOrDriver, userId;
private String doctorId, patientId, pharmacyId, userDriverOrCustomer;
private Long timestamp;
private String name, service;
private SwipeRefreshLayout swipeRefreshLayout;
private RecyclerView mHistoryRecyclerView;
private RecyclerView.Adapter mHistoryAdapter;
private RecyclerView.LayoutManager mHistoryLayoutManager;
SharedPreferences sharedPreferences;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_history);
customerOrDriver = getIntent().getExtras().getString("customerOrDriver");
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(HistoryActivity.this);
userId = sharedPreferences.getString("UID","");
mHistoryRecyclerView = (RecyclerView) findViewById(R.id.historyRecyclerView);
mHistoryAdapter = new HistoryAdapter(getDataSetHistory(), HistoryActivity.this);
mHistoryLayoutManager = new LinearLayoutManager(HistoryActivity.this);
mHistoryRecyclerView.setLayoutManager(mHistoryLayoutManager);
mHistoryRecyclerView.setHasFixedSize(true);
/*// sort the recycler view to descending order
((LinearLayoutManager) mHistoryLayoutManager).setReverseLayout(true);
((LinearLayoutManager) mHistoryLayoutManager).setStackFromEnd(true);*/
mHistoryRecyclerView.setItemAnimator(new DefaultItemAnimator());
mHistoryRecyclerView.addItemDecoration(new DividerItemDecoration(this, LinearLayoutManager.VERTICAL));
mHistoryRecyclerView.setAdapter(mHistoryAdapter);
getUserHistoryIds();
}
private void getUserHistoryIds() {
//swipeRefreshLayout.setRefreshing(true);
DatabaseReference userHistoryDatabase = FirebaseDatabase.getInstance().getReference().child(Common.user_table).child(customerOrDriver).child(userId).child(Common.history_table);
userHistoryDatabase.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(dataSnapshot.exists()){
for(DataSnapshot history : dataSnapshot.getChildren()){
FetchRideInformation(history.getKey());
//swipeRefreshLayout.setRefreshing(false);
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
//swipeRefreshLayout.setRefreshing(false);
}
});
}
private void FetchRideInformation(String rideKey) {
DatabaseReference historyDatabase = FirebaseDatabase.getInstance().getReference().child(Common.history_table).child(rideKey);
historyDatabase.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(dataSnapshot.exists()){
String rideId = dataSnapshot.getKey();
timestamp = 0L;
for(DataSnapshot child : dataSnapshot.getChildren()){
if (child.getKey().equals("timestamp")){
timestamp = Long.valueOf(child.getValue().toString());
}
}
getRideInformation(rideId, timestamp);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
private void getRideInformation(final String rideId, final Long timestamp) {
DatabaseReference historyRideInfoDb = FirebaseDatabase.getInstance().getReference().child(Common.history_table).child(rideId);
historyRideInfoDb.addListenerForSingleValueEvent(new ValueEventListener() {
#SuppressLint("SetTextI18n")
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
for (DataSnapshot child : dataSnapshot.getChildren()) {
if (child.getKey().equals("patient")) {
patientId = child.getValue().toString();
if (!patientId.equals(userId)) {
userDriverOrCustomer = "Doctors";
getUserInformation("Patients", patientId, rideId, timestamp);
}
}
else if (child.getKey().equals("patient")) {
patientId = child.getValue().toString();
if (!patientId.equals(userId)) {
userDriverOrCustomer = "Phamacys";
getUserInformation("Patients", patientId, rideId, timestamp);
}
}
if (child.getKey().equals("doctor")) {
doctorId = child.getValue().toString();
if (!doctorId.equals(userId)) {
userDriverOrCustomer = "Patients";
getUserInformation("Doctors", doctorId, rideId, timestamp);
}
}
else if (child.getKey().equals("pharmacy")) {
pharmacyId = child.getValue().toString();
if (!pharmacyId.equals(userId)) {
userDriverOrCustomer = "Patients";
getUserInformation("Pharmacys", pharmacyId, rideId, timestamp);
}
}
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
private void getUserInformation(String otherUserDriverOrCustomer, String otherUserId, final String rideId, final Long timestamp) {
DatabaseReference mOtherUserDB = FirebaseDatabase.getInstance().getReference().child(Common.user_table).child(otherUserDriverOrCustomer).child(otherUserId);
mOtherUserDB.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
Map<String, Object> map = (Map<String, Object>) dataSnapshot.getValue();
if (map.get("name") != null) {
name = (map.get("name").toString());
}
if(map.get("service") == null)
{
service = (map.get("phone").toString());
}
else if (map.get("service") != null) {
service = (map.get("service").toString());
}
HistoryObject obj = new HistoryObject(rideId, name, service, getDate(timestamp));
resultsHistory.add(obj);
mHistoryAdapter.notifyDataSetChanged();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
private String getDate(Long time) {
Calendar cal = Calendar.getInstance(Locale.getDefault());
cal.setTimeInMillis(time*1000);
String date = DateFormat.format("MMMM dd yyyy, hh:mm a", cal).toString();
return date;
}
private ArrayList resultsHistory = new ArrayList<HistoryObject>();
private ArrayList<HistoryObject> getDataSetHistory() {
return resultsHistory;
}
}
Simply use myList.sort() then read it the way its needed like ascending or descending amd put it in the RecyclerView
You can sort your by following way
Her i just showed you an Student object but in your case you can check with datetime
Using Lambda expression: The Java 8 equivalent code using Lambda expression would look like this:
studentlist.sort((Student s1, Student s2)->s1.getName().compareTo(s2.getName()));
I am using firebase real-time database to store and retrieve data but for some reason, I am unable to achieve what I want.
I want to get 20 records at a time on swipe refresh layout.
My data looks like:
Initially, I load 50 records:
chat.limitToLast(default_num_of_messages).addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Map map = dataSnapshot.getValue(Map.class);
String user_id = map.get("user_id").toString();
String message = map.get("message").toString();
String timestamp = map.get("timestamp").toString();
Log.d("MAP", map.toString());
ChatMessage chat_message = new ChatMessage();
chat_message.setUser_id(user_id);
chat_message.setMessage(message);
chat_message.setTimestamp(Long.parseLong(timestamp));
Log.d("CHAT MSG", chat_message.toString());
if(Integer.parseInt(user_id) == Utils.getInstance().getLoggedInUser().getId()) {
addMessageBox(chat_message, 1);
}
else{
addMessageBox(chat_message, 2);
}
}
after these on refresh, I want to load 20 more. I am trying to do something like these. but it does not seem to return.
#Override
public void onRefresh() {
if(refresh_toggle) {
swipe_view.setRefreshing(true);
Log.d("CHAT", "REFRESHED!!!");
//reload new data
chat.orderByChild("timestamp").endAt(10).addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Map map = dataSnapshot.getValue(Map.class);
String user_id = map.get("user_id").toString();
String message = map.get("message").toString();
String timestamp = map.get("timestamp").toString();
Log.d("CHATS", map.toString());
ChatMessage chat_message = new ChatMessage();
chat_message.setUser_id(user_id);
chat_message.setMessage(message);
chat_message.setTimestamp(Long.parseLong(timestamp));
swipe_view.setRefreshing(false);
if(Integer.parseInt(user_id) == Utils.getInstance().getLoggedInUser().getId()) {
addMessageBox(chat_message, 1);
}
else{
addMessageBox(chat_message, 2);
}
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {}
#Override
public void onCancelled(FirebaseError firebaseError) {}
});
}
}
As you can see I am trying to orderByChild "timestamp" and then tried different combination of startAt(), endAt() but nothing seem to work.
Try this:
int number_item_load = 10; //changed number if you want
public void loadMore(int offset, String theLastValue) {
// theLastValue: depend on your orderByChild() 's value
mDatabase = FirebaseDatabase.getInstance().getReference().child(Utils.FB_ROOT);
mEventListener = new ChildEventListener() {
#Override
public void onChildAdded(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
if (isAlreadyAttach()) {
// Get your item and callback to view and insert to listView
}
} ...
};
mDatabase.orderByChild("yourvalue").startAt(theLastValue).limitToFirst(number_item_load ).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
// TODO Finished loaded number_item_load item
OnLoadedFinish(); //
mDatabase.removeEventListener(mEventListener); // Remove listener after load
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
mDatabase.orderByChild("yourvalue").startAt(theLastValue).limitToFirst(number_item_load ).addChildEventListener(mEventListener);
}
It worked perfectly in my case. Goodluck
I am currently programin a test QuizApp. The gameplay is pretty easy I just want an online database of questions and a user can answer them.
This is what the database looks like:
That collection questions contains an unique ID and a custom Object (questionObject) named 'content'. The number is only something easy I can query/search for.
This is my questionAdder and query UI. It's only a small test App.
public class questionAdder extends AppCompatActivity {
EditText pQuestion, pAnwerA, pAnswerB, pAnswerC, pAnswerD, number;
Button pAdd, query;
private DatabaseReference databaseReference;
private FirebaseFirestore firebaseFirestore;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.addquestion);
firebaseFirestore = FirebaseFirestore.getInstance();
pQuestion = (EditText) findViewById(R.id.question);
pAnwerA = (EditText) findViewById(R.id.answerA);
pAnswerB = (EditText) findViewById(R.id.answerB);
pAnswerC = (EditText) findViewById(R.id.answerC);
pAnswerD = (EditText) findViewById(R.id.answerD);
number = (EditText) findViewById(R.id.number);
pAdd = (Button) findViewById(R.id.addQuestion);
pAdd.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
readQuestionStore();
}
});
query = (Button) findViewById(R.id.query);
query.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
CollectionReference questionRef = firebaseFirestore.collection("questions");
questionRef.whereEqualTo("content.number", "20").get().addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
#Override
public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
questionObject pContent = queryDocumentSnapshots.toObjects(questionObject.class);
}
});
}
});
}
public void readQuestionStore(){
Map<String, Object> pContent = new HashMap<>();
pContent.put("question", pQuestion.getText().toString());
pContent.put("Corr Answer", pAnwerA.getText().toString());
pContent.put("AnswerB", pAnswerB.getText().toString());
pContent.put("AnswerC", pAnswerC.getText().toString());
pContent.put("AnswerD", pAnswerD.getText().toString());
questionObject content = new questionObject(pContent, number.getText().toString()); //document("Essen").collection("Katalog")
firebaseFirestore.collection("questions").add(content).addOnSuccessListener(new OnSuccessListener<DocumentReference>() {
#Override
public void onSuccess(DocumentReference documentReference) {
Toast.makeText(questionAdder.this, "Klappt", Toast.LENGTH_LONG).show();
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(questionAdder.this, "Klappt nicht", Toast.LENGTH_LONG).show();
}
});
}
}
And this is how my questionObject looks like:
public class questionObject{
private Map<String, Object> content;
private String number;
public questionObject(){
}
public questionObject(Map<String, Object> pContent, String pNumber) {
this.content = pContent;
this.number = pNumber;
}
public Map<String, Object> getContent() {
return content;
}
public void setContent(Map<String, Object> content) {
this.content = content;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
}
Problem In that questionAdder class in the onClickListener I receive an "incompatible types" Error (Found: java.utils.list Required: questionObject).
query.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
CollectionReference questionRef = firebaseFirestore.collection("questions");
questionRef.whereEqualTo("content.number", "20").get().addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
#Override
public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
questionObject pContent = queryDocumentSnapshots.toObjects(questionObject.class);
}
});
}
});
If if I change that to a List it is empty. So the actual question is, how do I get the CustomObject into my code using the Database. Thanks!
The reason you are getting this error in because the QuerySnapshot is a type which "contains" multiple documents. Firestore won't decide for you whether there are a bunch of objects to return as a result, or just one.
This is why you can take two different approaches:
Put the data in a custom object's list:
List<questionObject> questionsList=new ArrayList<>();
if (!documentSnapshots.isEmpty()){
for (DocumentSnapshot snapshot:queryDocumentSnapshots)
questionsList.add(snapshot.toObject(questionObject.class));
}
If you're sure that your gonna get only one queried object, you can just get the first object from the returned queryDocumentSnapshots:
questionObject object=queryDocumentSnapshots.getDocuments().get(0).toObject(questionObject.class);
A few more things you should be aware of:
Why do you write content.number instead of just number?
It seems like number is a separated field in your question document, so your code should be as follows:
CollectionReference questionRef = firebaseFirestore.collection("questions");
questionRef.whereEqualTo("number", "20").get().addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
#Override
public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
questionObject pContent = queryDocumentSnapshots.toObjects(questionObject.class);
}
});
In addition, try to change your number field to int, because it's not a String but a just a number.
By the way, it is more acceptable to write classes' names with a capital letter at a beginning, for example: QuestionObject question=new QuestionObject();
I'm testing Firebase by building an app that simply puts a message in the Database (authorisations are set to true for the test), it worked only once, and now nothing is pushed to the database. But as you can see I put logs everywhere to see where the problem is and surprisingly the onChildEventListener() seems to notice a change.
Here is the code for my main activity :
public class MainActivity extends AppCompatActivity {
public final static String TAG = "Main Activity";
public final int[] id = {0};
Button sendButton;
EditText messageEditText;
String message;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
id[0] = 0;
sendButton = findViewById(R.id.send_message);
messageEditText = findViewById(R.id.message_text);
final DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference("test/geomessage/");
sendButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
message = messageEditText.getText().toString();
Log.e(TAG, "Test 1");
GeoMessage currentGeomessage = new GeoMessage(id[0], message);
Log.e(TAG, "Test 2");
databaseReference.child("children").push().setValue(currentGeomessage).addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
Log.e(TAG, "Success !");
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.e(TAG, "FAIL");
}
}).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
Log.e(TAG, "Complete");
}
});
Log.e(TAG, "Test 3");
}
});
databaseReference.child("children").addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Log.e("101", "Child Added !");
id[0] = (int) dataSnapshot.getChildrenCount();
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
Log.e("101", "Child CHanged !");
id[0] = (int) dataSnapshot.getChildrenCount();
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
private static class GeoMessage {
int id;
String content;
public GeoMessage() {};
public GeoMessage(int id, String content) {
this.id = id;
this.content = content;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
}
Here are the logs when I click on the "Send" Button :
11-03 19:02:13.338 7440-7440/com.example.brumor.geofiretest E/Main Activity: Test 1
11-03 19:02:13.338 7440-7440/com.example.brumor.geofiretest E/Main Activity: Test 2
11-03 19:02:13.340 7440-7440/com.example.brumor.geofiretest E/Main Activity: Test 3
11-03 19:02:13.420 7440-7440/com.example.brumor.geofiretest E/101: Child Added !
The observed behavior occurs when the device does not have a connection to the Firebase servers. Calls to setValue() change the DB cache held locally in the client. This causes listeners for the changed location to fire. But the completion listeners for setValue() do not fire until the update to the Firebase server completes successfully or fails.
Check that your device has a network connection. You can detect the Firebase connection status using the example here.
sendButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
message = messageEditText.getText().toString();
GeoMessage currentGeomessage = new GeoMessage(id[0], message);
databaseReference.child("children").push().setValue(currentGeomessage);
}
});
No need to use addonSuccessListener to store data. Also it is not even entering the method addonSuccessListener , so its skipping the whole method and then it prints the Log for you, but nothing is entering the database. Usually onSuccessListener is used for firebase storage, to see if the task is successful or not.
Also according to this page: https://firebase.google.com/docs/reference/admin/java/reference/com/google/firebase/tasks/Task
public abstract Task<T> addOnSuccessListener (OnSuccessListener<? super T> listener)
The above method is deprecated.
You have to use this now:
public abstract Task<T> addOnSuccessListener (Executor executor, OnSuccessListener<? super T> listener)
I'm new to Firebase and working on simple project. I have a method to get a list of teachers from Firebase and add their emails to an ArrayList and return.
public ArrayList<String> getTeacherList() {
temp = new ArrayList();
Firebase node = ref.child("teachers");
Query query = node.orderByChild("subject").equalTo(selected_subject);
query.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Map<String,Object> value = (Map<String, Object>) dataSnapshot.getValue();
Log.d("TEACHER"," "+value.toString());
Iterator entries = value.entrySet().iterator();
while (entries.hasNext()) {
Map.Entry thisEntry = (Map.Entry) entries.next();
String key = (String) thisEntry.getKey();
Object data = thisEntry.getValue();
if(key.equals("email")) {
temp.add(data.toString());
Log.d("ENTRY",": DATA "+data.toString());
}
}
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});
Log.d("RETURN", temp.toString());
return temp;
}
This method is working fine. But the problem is this returns the temp variable before completing adding child.
For example my Android Monitor is like that :
D/RETURN: []
D/TEACHER: {number=1, name=Teacher, email=teacher#new.lk, subject=Physics}
D/ENTRY: : DATA teacher#new.lk
Is there any way to wait until complete thatonChildAdded method..?
=========================================================================
I tried in this way also. But then it stopped at inside method.
Even it didn't go to Log.d("TEACHER", " " + value.toString()); tag here.
public ArrayList getTeacherList() throws InterruptedException {
temp = new ArrayList();
Firebase node = ref.child("teachers");
Query query = node.orderByChild("subject").equalTo(selected_subject);
semaphore = new Semaphore(0);
query.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Map<String, Object> value = (Map<String, Object>) dataSnapshot.getValue();
Log.d("TEACHER", " " + value.toString());
Iterator entries = value.entrySet().iterator();
while (entries.hasNext()) {
Map.Entry thisEntry = (Map.Entry) entries.next();
String key = (String) thisEntry.getKey();
Object data = thisEntry.getValue();
if (key.equals("email")) {
setArrayList(data.toString());
Log.d("ENTRY", ": DATA " + data.toString());
}
}
semaphore.release();
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});
semaphore.acquire();
return temp;
}
public class MainActivity extends AppCompatActivity{
public static Bus bus;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
bus = new Bus(ThreadEnforcer.MAIN);
bus.register(this);
//CALL TO LOAD DATA FROM FIREBASE
loadData();
}
private void loadData(){
DatabaseReference mDatabase = FirebaseDatabase.getInstance().getReference();
mDatabase.child("my-data").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
//CREATE YOUR OWN OBJECT USING RECEIVED DATA
MyObject o = new MyObject();
//CALL FOR METHOD nextMethod()
bus.post(o);
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.d("Error", databaseError.toString());
}
});
}
#Subscribe
private void nextMethod(MyObject o){
}
}
This is a very basic example for a usage of otto - EventBus. From bus.post(o), you can call to relavant Subscribed method.
Solved :
I used Otto EventBus Library from http://square.github.io/otto/ and it worked for me