Firebase - retrieve data in Android - android

I have a data looks like this:
{
"courses" : {
"Business" : {
"-KOBuojCGl_KVNgCx6l3" : {
"courseCode" : "BUS2202",
"courseName" : "Business Mathematics"
},
"-KOCH9RvYkwIamb0oxi8" : {
"courseCode" : "BUS2302",
"courseName" : "Business Fundamentals"
}
},
"Computing & IT" : {
"-KOBukFDN8eDjzF77haS" : {
"courseCode" : "SDT2201",
"courseName" : "System Designs"
},
"-KOBuriS_C5njfhAkV_P" : {
"courseCode" : "SDT3201",
"courseName" : "Computer Project"
},
"-KOD-E81rtXhzEmSeRPx" : {
"courseCode" : "SDT2202",
"courseName" : "System Designs Year 2"
},
}
}
}
And an UI looks like this:
When user selects Business Fundamentals, textview1 should display BUS2302 and textview2 should display Business Fundamentals.
Codes I'm trying now:
public class MainActivity extends AppCompatActivity{
private TextView tv1, tv2;
private DatabaseReference mRef;
private String code, name;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRef = FirebaseDatabase.getInstance().getReference().child("courses").child("Business");
tv1 = (EditText) findViewById(R.id.textview1);
tv2 = (EditText) findViewById(R.id.textview2);
mRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
CourseDetails courseDetails = dataSnapshot.getValue(CourseDetails.class);
code = courseDetails.getCourseCode();
name = courseDetails.getCourseName();
tv1.setText(code);
tv2.setText(name);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}
CourseDetails class:
public class CourseDetails {
private String courseCode;
private String courseName;
public CourseDetails() {
}
public CourseDetails(String courseCode, String courseName) {
this.courseCode = courseCode;
this.courseName = courseName;
}
public String getCourseCode() {
return courseCode;
}
public void setCourseCode(String courseCode) {
this.courseCode = courseCode;
}
public String getCourseName() {
return courseName;
}
public void setCourseName(String courseName) {
this.courseName = courseName;
}
}
When I run the codes, both the textviews just blank, and no error message. When I changed mRef ValueEventListener to this:
mRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
tv1.setText(dataSnapshot.getValue().toString());
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
The whole JSON data printed out in textview1, so I know my data is there. But when I use getCourseCode() and getCourseName(), the textviews are blank. Any suggestions?
I have another question which the codes will be used to get the push key of a course, then only display the course code and name accordingly. The question can be found here

In your MainActivity for mRef it reference till node Business of the database which has further two children with keys which I think are generated using push. So, I think you have to iterate over it's children. Can you try something like below:
mRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
// for each children
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
CourseDetails courseDetails = snapshot.getValue(CourseDetails.class);
code = courseDetails.getCourseCode();
name = courseDetails.getCourseName();
tv1.setText(code);
tv2.setText(name);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
If this gives some result apart from null, then may have to work in mapping textViews with respective to key.

Related

How to retrieve nested data from firebase

This is the structure of data from my firebase:
I have problem to retrieve all "menukedai" data. By using the code below, data from "menukedai" didnt come out. For your information, the data of "menukedai" will come from the user.
This is my attempt:
foodDatabaseRef = FirebaseDatabase.getInstance().getReference("uploads").child("menukedai");
foodDatabaseRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot postSnapshot : dataSnapshot.getChildren()) {
foodmenu foodmenu = postSnapshot.getValue(foodmenu.class);
fooddata.add(foodmenu);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
Toast.makeText(foodlist.this, databaseError.getMessage(), Toast.LENGTH_SHORT).show();
}
});
This is my foodmenu class.
package com.example.trialfoodbuddy;
public class foodmenu {
private String Foodimage;
private String Foodname;
private CharSequence Foodprice;
public foodmenu(){
//empty constructor needed
}
public foodmenu(String foodimage, String foodname, CharSequence foodprice){
Foodimage = foodimage;
Foodname = foodname;
Foodprice = foodprice;
}
public String getFoodimage(){
return Foodimage;
}
public String getFoodname(){
return Foodname;
}
public CharSequence getFoodprice(){
return Foodprice;
}
public void setFoodimage(String foodimage){
Foodimage = foodimage;
}
public void setFoodname(String foodname){
Foodname = foodname;
}
public void setFoodprice(CharSequence foodprice){
Foodprice = foodprice;
}
}
I Believe you want to get the information nested under "menukedai" so you will need to add another loop for that information
foodDatabaseRef = FirebaseDatabase.getInstance().getReference("uploads");
foodDatabaseRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot uploadSnapshot : dataSnapshot.getChildren()) {
// this is where you actually getting the information
for(DataSnapshot menuItemSnapshot : uploadSnapshot.child("menukedai").getChildren()){
foodmenu foodmenu = menuItemSnapshot.getValue(foodmenu.class);
fooddata.add(foodmenu);
}
}
}
// Log the values and check them to make sure you getting the data you want if always nice so I added it for you here
Log.i("Values","My values are:"+foodmenu);
#Override
public void onCancelled(DatabaseError databaseError) {
Toast.makeText(foodlist.this, databaseError.getMessage(), Toast.LENGTH_SHORT).show();
}
});
Normally speaking, You should always use the variable names in your class in your Database so when you pulling the information, your constructor would know what value assign to which variable in your class.

How can I get the push id for a firebase database element so as to display it in the listView

I am making a to-do app, indeed my first firebase app. I have successfully implemented everything with a single text view(todo) under the firebase UID, by creating an array of the push id that returns the push ID when an element is clicked in the List view.
Here was my previous data structure:
Old data Structure
I am stuck with the problem that how can I get the push IDs of elements so that I can reach them and display them in my ListView.
This is the structure that I am trying to fetch :
New data structure
Here is the code that I use for adding and deleting data in the old
Structure
public void Upload(View v) {
String userId = myRootRef.push().getKey();
firebaseUniqueID =mAuth.getCurrentUser().getUid();
todoToUpload=todoEditText.getText().toString();
myRootRef.child(firebaseUniqueID).child(userId).setValue(todoToUpload);
startActivity(new Intent(AddTodo.this,showTodo.class));
Here's the code I use for adding and deleting:
FirebaseAuth mAuth;
FirebaseDatabase mDataBase= FirebaseDatabase.getInstance();
DatabaseReference myRootRef=mDataBase.getReference();
DatabaseReference userRef;
ListView listView;int pos;
private ArrayAdapter<String> adapter;
ArrayList<String> mTodo=new ArrayList<>();
ArrayList<String> keysList = new ArrayList<>();
adapter=new ArrayAdapter<String>(this,R.layout.custom_list_layout,R.id.tood,mTodo);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
pos=position;
AlertDialog.Builder mBuilder=new AlertDialog.Builder(showTodo.this);
View mView=getLayoutInflater().inflate(R.layout.custom_dialog_show,null);
Todo=mView.findViewById(R.id.todo);
Delete=mView.findViewById(R.id.delete);
Done=mView.findViewById(R.id.done);
closer=mView.findViewById(R.id.dialog_close);
mBuilder.setView(mView);
final AlertDialog dailog=mBuilder.create();
myRootRef.child(firebaseUniqueID).child(keysList.get(position)).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
todoOpened=dataSnapshot.getValue(String.class);
Todo.setText(todoOpened);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Delete.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(Done.isChecked())
{
mTodo.remove(pos);
adapter.notifyDataSetChanged();
//new code below
myRootRef.getRoot().child(firebaseUniqueID).child(keysList.get(pos)).removeValue();
keysList.remove(pos);
dailog.dismiss();
}
}
});
myRootRef.child(firebaseUniqueID)
.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot firebaseUniqueID : dataSnapshot.getChildren()) {
keysList.add(firebaseUniqueID.getKey());
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
/*handle errors*/
}
});
userRef.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
String value= dataSnapshot.getValue(String.class);
mTodo.add(value);
adapter.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) {
}
});
Here's the JSON file for the old and new structures
{
"Z2H2ZkX56fYv3WKxE3a3nCaa8Q63" : {
"-LNPyZIkX8-uDDGeX-pN" : {
"Time" : "22:56",
"Todo" : "play"
},
"-LNPze7ppG1L0qFukZO-" : {
"Priority" : "High",
"Time" : "22:56",
"TimeSet" : "09:56",
"Todo" : "play till the sun goes down"
},
"-LNPzhBDDtHv_XSIERX_" : {
"Priority" : "High",
"Time" : "22:56",
"TimeSet" : "09:56",
"Todo" : "play till the sun goes ddawdawdawdwown"
}
}
}
{
"Z2H2ZkX56fYv3WKxE3a3nCaa8Q63" : {
"-LNQRCZSsYVPqn0tWghZ" : "play in the evening",
"-LNQRrLliVSxWBHcEIrv" : "I want to shine like a sun"
}
}
You get the key of a DataSnapshot by calling its getKey() method. So for example:
public void onDataChange(DataSnapshot dataSnapshot) {
todoOpened=dataSnapshot.getValue(String.class);
String key = dataSnapshot.getKey();
Todo.setText(key + ": "+ todoOpened);
}
you can display list as per your new structure dsplayed in :https://i.stack.imgur.com/E4DXI.png
FirebaseRecyclerOptions<Messages> options =
new FirebaseRecyclerOptions.Builder<"Your Class Name">()
.setQuery(mMessageThread.child("messages").limitToLast(500), "Your Class Name".class)
.setLifecycleOwner(this)
.build();
use this with firebase adapter.
Then get ToDo text and display it.

onClick update to firebase database not working

I'm trying to update the identity value of the user with onClick method of the update button but it is not working and no value is being updated.
Here is my activity (I used the Query to get to the user unique ID):
public class Update extends AppCompatActivity {
EditText identity;
DatabaseReference ref;
Button update;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_check);
update = (Button) findViewById(R.id.button_update);
identity = (EditText) findViewById(R.id.edit_text_identity);
mStorageRef = FirebaseStorage.getInstance().getReference("uploads");
String key = getIntent().getExtras().get("androidId").toString();
final Query userQuery = FirebaseDatabase.getInstance().getReference().child("Users").orderByChild("androidId");
userQuery.equalTo(key).addListenerForSingleValueEvent(
new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot foodSnapshot: dataSnapshot.getChildren()) {
final String userUID = foodSnapshot.getKey();
ref = FirebaseDatabase.getInstance().getReference().child(userUID);
identity.setText(getIntent().getStringExtra("identity"));
update.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ref.child("identity").setValue("noo");
}
});
}
}
#Override
public void onCancelled(DatabaseError databaseError) {}
}
);
}
}
My database structure is like:
{
"Users" : {
"uid1" : {
"name" : "Josh",
"identity": "yes"
},
"uid2" : {
"name" : "June",
"identity": "no"
}
}
}
And there is no error showing in the logcat. What might be the problem here?
The problem here is that the ref you've used is not pointing exactly to the node you want to be updated. You can use this to do so:
update.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference().child("Users").child(uidYouWant);
rootRef.child("identity").setValue("noo");
}
});
Also to get the uidYouWant instead of using query you can go though all the nodes to get the one you want, using orderByChild() and equalTo() directly like this:
ref.orderByChild("androidID").equalTo(key).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for(DataSnapshot data: dataSnapshot.getChildren()){
// do what you want to
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});

A new text should be displayed in textview every time the app launches

I have a textview in MainActivity.java. There are 5 strings (sentences) which are stored in firebase database. What I want is every time the MainActivity.java launches, a new string should be fetched from the database and must be displayed in the textview. But it only fetches the first string. I am not sure how to make this work! Is there any workaround? Any Help is appreciated.
MainActivity.java
public class Gridshow extends AppCompatActivity{
TextView myText;
private DatabaseReference database;
#Override
protected void onCreate(Bundle SavedInstanceState) {
super.onCreate(SavedInstanceState);
myText = (TextView) findViewById(R.id.Attri);
database = FirebaseDatabase.getInstance().getReference("StringList");
database.child("String1").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String sentName = dataSnapshot.getValue(String.class);
myText.setText(sentName);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
Sample son file:
{
"StringList" : {
"String1" : "Valley Rovers",
"String2" : "John Murphy",
"String3" : "Hello all",
"String4" : "See you all",
"String5" : "Hey all"
}
}
The problem is that you're directly saying to FB to retrieve just the first string in here:
database.child("String1").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String sentName = dataSnapshot.getValue(String.class);
myText.setText(sentName);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
You should retrieve the whole list and randomly choose the new string:
ArrayList<String> stringList = new ArrayList<>();
database.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Map<String, String> entries = (Map<String, String>) dataSnapshot.getValue();
stringList.addAll(entries.values());
selectString(stringList);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
public void selectString(ArrayList<String> list){
Random ran = new Random();
int x = ran.nextInt(list.size());
myText.setText(list.get(x));
}
use this
database = FirebaseDatabase.getInstance().getReference().child("StringList");
database.addValueEventListener(new ValueEventListener()
{
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String sentName = dataSnapshot.getValue(String.class);
myText.setText(sentName);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Well, in this line:
database.child("String1").addValueEventListener
You are fetching just String1. You should instead use something like this:
database.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(int i = 0;i<dataSnapshot.getChildren().size();i++){
if(i==positionOfStringYouWant){
String sentName = dataSnapshot.getValue(String.class);
myText.setText(sentName);
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});

Populate textView from firebase database

I am trying to populate a TextView from a firebase database. Here is the sample json file.
{
"Player" : {
"Club" : "Valley Rovers",
"Name" : "John Murphy"
}
}
Here is my android code:
public class MainActivity extends AppCompatActivity {
private TextView mPlayer;
private DatabaseReference mDatabase;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mPlayer = (TextView) findViewById(R.id.player);;
mDatabase = FirebaseDatabase.getInstance().getReference("Player").child("Name");
final String player = mDatabase.push().getKey();
mDatabase.child("Name").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
// Check for null
if (player == null) {
Log.e(TAG, "User data is null!");
return;
}
mPlayer.setText(player);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
I want to add the name John Murphy to the firebase database and doing so the TextView mPlayer will populate with John Murphy.
You are getting the child "Name" twice on your code (leading to Player/Name/Name). Remove it from the mDatabase initialization:
mDatabase = FirebaseDatabase.getInstance().getReference("Player");
And you're never really getting the value from the DataSnapshot received. To do so, use this:
mDatabase.child("Name").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String playerName = dataSnapshot.getValue(String.class);
mPlayer.setText(playerName);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
In case someone wants to use POJO approach to this problem in future, follow the example below:
Remove the child("Name") from mDatabase.child("Name").addValueEventListener(new ValueEventListener()
unless you want to fetch the "Name" child only. Also remember to effect the correction made on mDatabase initialization.
mDatabase.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
// String playerName = dataSnapshot.getValue(String.class);
PlayerModel playerModel = dataSnapshot.getValue(PlayerModel.class);
((TextView)findViewById(R.id.textviewName)).setText(playerModel.getName());
((TextView)findViewById(R.id.textviewClub)).setText(playerModel.getClub());
// mPlayer.setText(playerName);
}

Categories

Resources