As refer in this link. I want to try in my coding apps. But it didnt retrieve any data from my firebase database. I just cant figure out how to fix it. Can someone please help me. Is there any idea, where did I miss?
My firebase database as show image below:-
Spinner coding:-
mDatabase = FirebaseDatabase.getInstance().getReference();
mDatabase.keepSynced(true);
mDatabase.child("Advertisement").child(mAuth.getUid()).addValueEventListener(new ValueEventListener()
{
#Override
public void onDataChange(DataSnapshot dataSnapshot)
{
//final List<String> name = new ArrayList<String>();
ArrayList<String> identity = new ArrayList<>();
identity.add(0, "Choose Tuition Centre");
for (DataSnapshot nameSnapshot: dataSnapshot.getChildren())
{
String tuitionName = nameSnapshot.child("adstuitioname").getValue(String.class);
identity.add(tuitionName);
}
ArrayAdapter<String> nameAdapter = new ArrayAdapter<String>(RatingActivity.this, android.R.layout.simple_spinner_item, identity);
nameAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mName.setAdapter(nameAdapter);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
mName.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener()
{
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id)
{
if(position==0)
{
//Toast.makeText(getApplicationContext(),"No Item Selected",Toast.LENGTH_LONG).show();
}
else
{
Toast.makeText(getApplicationContext(),parent.getItemAtPosition(position) +" Selected",Toast.LENGTH_SHORT).show();
}
}
#Override
public void onNothingSelected(AdapterView<?> parent)
{
// TODO Auto-generated method stub
}
});
Add listener as below :
DatabaseReference mDatabaseRef =
FirebaseDatabase.getInstance().getReference();
ArrayList<String> list=new ArrayList<>();
mDatabaseRef.child("Advertisement")
.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot :dataSnapshot.getChildren())
{
Advertisementject advertisement=
snapshot.getValue(Advertisement.class);
//replace Object.class with your class name
//get your key value here from your "Custom class"
// which contains "adstutioname"
// add in list
list.add(advertisement.getAdstutuioname());
}
//set adapter
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
generate class like this
public class Advertisement{
#SerializedName("adstutuioname")
#Expose
private String adstutuioname;
public String getAdstutuioname() {
return adstutuioname;
}
public void setAdstutuioname(String adstutuioname) {
this.adstutuioname = adstutuioname;
}
}
Your class contains all your params and .
Replace Object with this class
I hope the problem is with your getValue() method. Firebase getValue method returns an Object, and you are expecting a String. Please modify this line to convert your Object to String -
String tuitionName = nameSnapshot.child("adstuitioname").getValue(String.class).toString();
It's not clear if you're trying to read once, or watch changes Difference between addValueEventListener() and addListenerForSingleValueEvent() of firebase
First things first, look if you are getting a database error
#Override
public void onCancelled(DatabaseError databaseError) {
// Toast or print the databaseError, don't ignore it
}
Then look where you're adding a listener - mDatabase.child("Advertisement").child(mAuth.getUid())., which from your picture is every element at the level of -LNZ6....
For that level, you have a list of object's, so you can need to use a loop, and as shown from some examples on Firebase site, it's recommended that you make an object, but you still can use child method for a certain field as you're trying to do
But if a field doesn't exist, you get null value, and Adapters cannot hold nulls, so you must ignore or set some default value.
ArrayList<String> identity = new ArrayList<>();
identity.add(0, "Choose Tuition Centre");
for (DataSnapshot nameSnapshot: dataSnapshot.getChildren()) {
String tuitionName = nameSnapshot.child("adstuitioname").getValue(String.class);
Log.d("DEBUG TUITION", String.valueOf(tuitionName); // look for this in your logs
identity.add(tuitionName == null ? "none" : tuitionName);
}
ArrayAdapter<String> nameAdapter =...
Related
I am trying to retrieve specific data from google firebase which is specific to each user that is logged in. Basically, the data that i want to retrieve is 'field' data listed under user ID's but in a separate class on google firebase realtime database. I want to be able to show the data of each field in a 'listview' in an activity on my application but whenever i try to run it, the application just closes.
I have already tried running the application under references to the 'users' class.But this didn't work.I also tried running under the 'fields' class but this also does not work.
Here is my FarmActivity.java where I want the 'listview' of the field data to show.
public class FarmActivity extends AppCompatActivity {
ListView listView;
FirebaseDatabase database;
DatabaseReference ref;
ArrayList<String> list;
ArrayAdapter<String> adapter;
FieldInformation fieldInformation;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_farm);
listView = (ListView )findViewById(R.id.listView);
database = FirebaseDatabase.getInstance();
ref = database.getReference("Fields");
list = new ArrayList<>();
adapter = new ArrayAdapter<String>(this, R.layout.user_field_info, R.id.userInfo, list);
fieldInformation = new FieldInformation();
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot ds:dataSnapshot.getChildren()){
fieldInformation = ds.getValue(FieldInformation.class);
list.add(fieldInformation.getFieldName().toString() + " " + "\n"+ fieldInformation.getCrop().toString() + " ");
}
listView.setAdapter(adapter);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Here is my FieldInformation.java where i have specified the strings for the FarmActivity
public class FieldInformation {
public String crop;
public String fieldName;
public FieldInformation(String crop, String fieldName) {
this.crop = crop;
this.fieldName = fieldName;
}
public FieldInformation(){
}
public String getCrop() {
return crop;
}
public void setCrop(String crop) {
this.crop = crop;
}
public String getFieldName() {
return fieldName;
}
public void setFieldName(String fieldName) {
this.fieldName = fieldName;
}
}
Your adapter should have a list in it and your adapter should have a constructor that takes a list. You initialize your adapter in FarmActivity with the list in there and remove your set adapter then set it after you initialize adapter, lastly put adapter.notifydatasetchanged(); where you where setting your adapter. Feel free to post your adapter and ill help you fix it.
I am trying to login a user as a guest which means he can only view whatever is there but not interact with anything. I had some problems doing this.
First of all I used anonymous login, so that is working perfectly to sign in the user.
Now I want the user to select from a list of areaUIDs to view details of only that particular area
My database looks like this,
Areas
-AreaUID1
-Admin
-Admin1UID
-admin_name:""
-admin_area:""
-admin_email:""
-Admin2UID
-admin_name:""
-admin_area:""
-admin_email:""
.
.
-Events
-EventUid1
-event_name:""
-event_timings:""
-EventUid2
-event_name:""
-event_timings:""
.
.
-Gallery
-ImageUid1
-image_link:""
-AreaUid2
-Admin
-Admin1UID
-admin_name:""
-admin_area:""
-admin_email:""
-Admin2UID
-admin_name:""
-admin_area:""
-admin_email:""
.
.
-Events
-EventUid1
-event_name:""
-event_timings:""
-EventUid2
-event_name:""
-event_timings:""
.
.
-Gallery
-ImageUid1
-image_link:""
and so on.
Now I want to show the user a list of the several admin_area located in different AreaUids. I am using FirebaseRecyclerAdapter and I need help implementing the above problem. I want the user to be able to view all the gallery images and events from a particular area that he/she chooses.
mDbRef = FirebaseDatabase.getInstance().getReference().child("Areas");
allAreaUids = new ArrayList<>();
ValueEventListener listener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
//This is where i want to populate my arraylist with all the AreaUids. How do i do it?
}
#Override
public void onCancelled(DatabaseError databaseError) {
// Getting Post failed, log a message
System.out.println(databaseError.toException());
// ...
}
};
mDbRef.addValueEventListener(listener);
adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, android.R.id.text1, allAreaUids);
ListView listView = (ListView) findViewById(R.id.list_of_areas);
listView.setAdapter(adapter);
My Areas class (note the constructors and the getters and setters methods are also present
public class Areas {
private Events Events;
private GalleryPics Gallery;
private Admin Admin;
public Areas(){
}
.
.
.
}
To display the Events of a specific area, please use this code:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference areasRef = rootRef.child("Areas");
ValueEventListener eventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot ds : dataSnapshot.getChildren()) {
String areaUid = ds.getKey();
DatabaseReference eventsRef = rootRef.child("Areas").child(areaUid).child("Events");
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot child : dataSnapshot.getChildren()) {
String event_name = child.child("event_name").getValue(String.class);
Log.d("TAG", event_name);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {}
};
eventsRef.addListenerForSingleValueEvent(valueEventListener);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {}
};
areasRef.addListenerForSingleValueEvent(eventListener);
In the same way you can get all the Gallery of a specific area.
I have wandered YouTube and Stack Overflow in search of way to retrieve the teacherName value from the following database:
I have not yet found a solution for my problem, whether I use a Value or ChildEventListener. This is the code I'm using:
public class ViewTeachersActivity extends AppCompatActivity {
// Define the Teacher Firebase DatabaseReference
private DatabaseReference databaseTeachers;
// Define a String ArrayList for the teachers
private ArrayList<String> teachersList = new ArrayList<>();
// Define a ListView to display the data
private ListView listViewTeachers;
// Define an ArrayAdapter for the list
private ArrayAdapter<String> arrayAdapter;
/**
* onCreate method
*/
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view_teachers);
// Associate the Teacher Firebase Database Reference with the database's teacher object
databaseTeachers = FirebaseDatabase.getInstance().getReference();
databaseTeachers = databaseTeachers.child("teachers");
// Associate the teachers' list with the corresponding ListView
listViewTeachers = (ListView) findViewById(R.id.list_teachers);
// Set the ArrayAdapter to the ListView
arrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, teachersList);
listViewTeachers.setAdapter(arrayAdapter);
// Attach a ChildEventListener to the teacher database, so we can retrieve the teacher entries
databaseTeachers.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
// Get the value from the DataSnapshot and add it to the teachers' list
String teacher = dataSnapshot.getValue(String.class);
teachersList.add(teacher);
// Notify the ArrayAdapter that there was a change
arrayAdapter.notifyDataSetChanged();
}
#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) {
}
});
}
I have also tried using a for loop inside the ChildEventListener, but that also didn't work. Can anyone point me to a solution?
String teacher = dataSnapshot.getValue(String.class);
You don't have a String there. You have an object.
So, you need a Java class
public class Teacher {
String teacherID, teacherEmail; // etc. all fieldnames in the database
public Teacher() {
}
// getters
// setters
#Override
public String toString() {
return this.teacherID + ": " + this.teacherEmail;
}
}
Then from Firebase, you can map the snapshot to that class and add to an adapter.
Teacher teacher = (Teacher) dataSnapshot.getValue(Teacher.class);
String teacherString = String.valueOf(teacher);
arrayAdapter.add(teacherString);
Refer: Firebase-UI | Using Firebase to populate ListView
Since your question is unclear if you want to listen for all teacherNames or just one.
This is an easy way to get all 'teacherName' for every entry (uuid key) under /teachers and adds a listener to this query:
FirebaseDatabase.getInstance()
.getReference()
.child("teachers")
.orderByChild("teacherName")
.addValueEventListener(listener); //listener example below
ValueEventListener listener = new new ValueEventListener()
{
#Override
public void onDataChange(DataSnapshot dataSnapshot)
{
dataSnapshot.getChildren().forEach(
// assuming you are using RetroLambda, if not, implement Consumer<? super T> action
// update change ListView here
);
}
#Override
public void onCancelled(FirebaseError firebaseError)
{
//handle errors here
}
});
If you are looking for getting a specific teacher name, comment and I'll change it. Also, I haven't tested syntax as I'm on mobile, so treat this as pseudocode but it should get you going in the right direction
Check out the Firebase Query documentation, it is really straightforward and as of now can do really powerful stuff in a few lines of code. Be careful of outdated tutorials when searching, Firebase has added allot of its functionality in the last ~1 year
I'd like to have a RecyclerView showing random questions to the users. Once the question is answered (wright or wrong), it should never appear for this user again, even if he closes the app. After that, the activity is reloaded and a new random question appears.
When the users see all the questions in database, it should show a message saying that there is no more question at that time.
My code right now is putting in Firebase database if the user saw the the question after the click.
I tried to put an if statement (but it seems a stupid idea) and it's working for a short time. Basically it says, if the child exists, reload the activity. When database has thousands of questions it'll work for a period, but will crash one day.
My problems:
First, I don't want to reload the activity n times to "find" a question which hasn't appear yet.
Second, I can't determine when the users see all the questions to show a message.
Here is the code:
mDatabase = FirebaseDatabase.getInstance().getReference().child("Category").child(category_key).child("Questions");
query = mDatabase.orderByChild("randomId").startAt(randomValue).limitToFirst(1);
#Override
protected void onStart() {
super.onStart();
FirebaseRecyclerAdapter<Questions, QuestionViewHolder>
firebaseRecyclerAdapter = new FirebaseRecyclerAdapter<Photos, QuestionViewHolder>(
Question.class,
R.layout.question_grid,
QuestionViewHolder.class,
query
) {
#Override
protected void populateViewHolder(final QuestionViewHolder viewHolder, final Question model, int position) {
final String question_key = getRef(position).getKey();
final String category_key = getIntent().getExtras().getString("category_id");
mDatabase.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.child(question_key).child("ViwedBy").hasChild(mAuth.getCurrentUser().getUid())) {
finish();
startActivity(getIntent());
} else {
viewHolder.setQuestion(model.getQuestion());{
#Override
public void onClick (View v){
mDatabaseLike.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
mDatabaseTest = FirebaseDatabase.getInstance().getReference().child("Category").child(category_key).child("Questions").child(question_key).child("ViewedBy").child(mAuth.getCurrentUser().getUid());
mDatabaseTest.setValue(true);
finish();
startActivity(getIntent());
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}
}
}
#Override
public void onCancelled (DatabaseError databaseError){
}
});
mQuestionsList.setAdapter(firebaseRecyclerAdapter);
}
Is there any smarter way to do it?
Extra question: Do I need to reload the entire activity or there is a way to reload only the RecyclerView?
This would be a straightforward approach to solving your problem. Your activity will no longer have to refresh itself, as that will be handled by your Adapter.
Structure your Database as such
rootNode
L ...category/questions...
L answeredQuestions
L userId
L randomQuestionId:true
L questionsForUser
L userId
L randomQuestionId:true
When your users answers a question :
add the questionId to answeredQuestions
remove the questionId from questionsForUser
call generateNewRandomQuestionForUser()
Replace your FirebaseRecyclerAdapter with a IndexedFirebaseRecyclerAdapter alike this:
new FirebaseIndexRecyclerAdapter<Question, QuestionHolder>(Question.class,
R.layout.question,
QuestionHolder.class,
keyRef,
dataRef);
where keyRef and dataRef are both
Query keyRef = FirebaseDatabase.getInstance().getReference().child("questionsForUser").child(userId);
Query DataRef = FirebaseDatabase.getInstance().getReference().child("Category").child(category_key).child("Questions");
and generateNewRandomQuestionForUser() is something like this:
public static void generateNewRandomQuestionForUser(final String userId, final String category_key) {
FirebaseDatabase.getInstance().getReference().child("answeredQuestions").child(userId).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
ArrayList<String> answeredQuestions = new ArrayList<String>();
for (DataSnapshot questionId : dataSnapshot.getChildren()) {
answeredQuestions.add(questionId.getKey());
}
FirebaseDatabase.getInstance().getReference().child("Category").child(category_key).child("Questions").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
ArrayList<String> availableQuestionKeys = new ArrayList<String>();
for (DataSnapshot questionSnapshot : dataSnapshot.getChildren()) {
availableQuestionKeys.add(questionSnapshot.getKey());
}
// Using answeredQuestions, availableQuestionKeys, you can user your own algorithm
// to select one at random that the user has not seen yet.
// Here you can also determine whether a user has seen all possible questions and update UI accordingly.
// Once you have your random question as keyOfRandomQuestion:
FirebaseDatabase.getInstance().getReference().child("questionsForUser").child(userId).child(keyOfRandomQuestion).setValue(true);
}
#Override
public void onCancelled(DatabaseError databaseError) {}
});
}
#Override
public void onCancelled(DatabaseError databaseError) {}
});
}
I am having trouble retrieving a List from the Firebase. I have no trouble storing it, but as soon as I try to cast dataSnapshot.getValue() to ArrayList my app crashes, giving an exception:
HashMap cannot be casted to ArrayList
But when I tried to cast it to a HashMap, it also crashes, giving exception:
ArrayList can't be casted to hashmap
Need help please! Here is the code that is creating the problem:
Fire.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
List<TaskDes> td = (ArrayList<TaskDes>) dataSnapshot.getValue()
notifyDataSetChanged();
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});
I want to retrieve all the data in the Firebase as one List. The class TaskDes contains three fields:
class TaskDes { // definition
boolean done
String taskDescription
String taskTitle
}
You need to create a GenericTypeIndicator object to pass as DataSnapshot.getValue() parameter.
Code:
GenericTypeIndicator<List<String>> t = new GenericTypeIndicator<List<String>>() {};
List<String> yourStringArray = dataSnapshot.getValue(t);
Your Model
public class TaskDes {
private boolean done;
private String taskDescription;
private String taskTitle;
public TaskDes() {
}
public boolean isDone() {
return done;
}
public void setDone(boolean done) {
this.done = done;
}
public String getTaskDescription() {
return taskDescription;
}
public void setTaskDescription(String taskDescription) {
this.taskDescription = taskDescription;
}
public String getTaskTitle() {
return taskTitle;
}
public void setTaskTitle(String taskTitle) {
this.taskTitle = taskTitle;
}
}
You need to create a GenericTypeIndicator object to pass as DataSnapshot.getValue() parameter.
In Activity
private static final String TAG=MainActivity.class.getSimpleName();
private FirebaseDatabase database;
private DatabaseReference myRef=null;
#Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
database=FirebaseDatabase.getInstance();
myRef=database.getReference("ADD_YOUR_REFERECE");
myRef.addValueEventListener(new ValueEventListener(){
#Override
public void onDataChange(DataSnapshot dataSnapshot){
/* This method is called once with the initial value and again whenever data at this location is updated.*/
long value=dataSnapshot.getChildrenCount();
Log.d(TAG,"no of children: "+value);
GenericTypeIndicator<List<TaskDes>> genericTypeIndicator =new GenericTypeIndicator<List<TaskDes>>(){};
List<TaskDes> taskDesList=dataSnapshot.getValue(genericTypeIndicator);
for(int i=0;i<taskDesList.size();i++){
Toast.makeText(MainActivity.this,"TaskTitle = "+taskDesList.get(i).getTaskTitle(),Toast.LENGTH_LONG).show();
}
}
#Override
public void onCancelled(DatabaseError error){
// Failed to read value
Log.w(TAG,"Failed to read value.",error.toException());
}
});
}
Make another item that contains a list for your item:
This is your item:
class TaskDes { // definition
boolean done
String taskDescription
String taskTitle
}
This is the list item
class TaskDesList { // definition
private ArreyList<TaskDes> yourlist
}
public TaskDesList(){
}
public ArrayList<TaskDes> getYourlist() {
return yourlist;
}
and when calling an EventListener
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
yourlist.clear();
taskDesList=dataSnapshot.getValue(TaskDesList.class);
if (taskDesList!=null) {
yourlist= taskDesList.getYourlist();
}
}
and now "yourlist" is a list that contains all of your "TaskDes" items
A bit late, but in case any one else needs this.
IF the list is inside another object.
The object
public class Question {
public Date date;
public String questionNumber;
public String questionText;
public QuestionType questionType;
public String multipleSelection1;
public String multipleSelection2;
public String multipleSelection3;
public Question() {
// Default constructor required for calls to DataSnapshot.getValue(User.class)
}
}
Then to get your array of question objects
GenericTypeIndicator<List<Question>> t = new GenericTypeIndicator<List<Question>>() {};
List<Question> questionList = dataSnapshot.getValue(t);
Apparently, the GenericTypeIndicator doesn't work for all List objects particularly when the object contains none primitive types like maps. So, if it didn't work for your use case as it didn't for me, try this alternate solution:
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
List<TaskDes> tDlist = new ArrayList<>();
for (DataSnapshot d: dataSnapshot.getChildren()){
TaskDes tD = d.getValue(TaskDes.class);
tDlist.add(tD);
}
notifyDataSetChanged();
}
As mentioned in the previous answers make sure your class( like TaskDes in this case) has a public constructor which is empty so the getValue method can deserialize correctly to your java class.