I'm developing an Android app in Android Studio which lists events based on categories (music, sport, business, theatre). Every event has a name, description, location and time. This is how the events are stored in Firebase when a user posts events through my application:
How can I retrieve e.g. all childs and its contents in the Music category? I have four String arrays to display events (currently manually) like this:
String[] name = {"Eminem","Rihanna"};
String[] desc = {"Concert","Live Show"};
String[] location = {"Miami","Florida"};
String[] time = {"bllablla","bllablla"};
I want to populate the string arrays automatically from firebase, however I'm not sure how to get contents for every child element from Music element? If needed, I can post the Java code which populates the database as well.
Edit: I've tried this:
DatabaseReference info = FirebaseDatabase.getInstance().getReference("Events").child("Music");
info.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot val: dataSnapshot.getChildren()) {
// Retreive all Music childs and then retreive all data of them childs?
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
There is probably no easier solution than to download all of your music data, loop through all children and create corresponding arrays manually -
1) Create a class to map your firebase music record to -
class MusicRecord{
String date;
String eventDescription;
String eventName;
String location;
}
2) Load data, loop through children, retrieve MusicRecords and populate your arrays
protected void loadData(){
DatabaseReference ref = FirebaseDatabase.getInstance().getReference("Events").child("Music");
ref.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
Iterable<DataSnapshot> recordsSnaphots = dataSnapshot.getChildren();
int count = (int) dataSnapshot.getChildrenCount();
int i = 0;
String[] names = new String[count];
String[] descriptions = new String[count];
String[] locations = new String[count];
String[] times = new String[count];
for(DataSnapshot recordSnapshot: recordsSnaphots){
MusicRecord record = recordSnapshot.getValue(MusicRecord.class);
if(record != null) {
names[i] = record.eventName;
descriptions[i] = record.eventDescription;
locations[i] = record.location;
times[i] = record.date;
i++;
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
Based on your post, you'll have to do several things :
Create a model
You'll have to create a POJO that describes the structure of the data you have in your Firebase realtime database. In your case, create a class FirebaseEvent that has a Date and three Strings (eventDescription,eventName,location).
Instantiate your class
Based on your last snippet, instantiate your class with the data from your Firebase realtime database. Firebase API is still a bit tedious with this, but this is yet the most common way to do it
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
GenericTypeIndicator<HashMap<String,FirebaseEvent>> ti =
new GenericTypeIndicator<HashMap<String,FirebaseEvent>>() {};
HashMap<String,FirebaseEvent> retrievedEvents = childSnapshot.getValue(ti);
}
Now, what you have is a HashMap with keys like "Eminem" and "Rihanna" and the corresponding value that is a FirebaseEvent.
I choose to use an ArrayList for a dynamic data structure.
I also took a snapshot of my database:
public class MainActivity extends AppCompatActivity {
List<String> name= new ArrayList<String>();
List<String> location= new ArrayList<String>();
List<String> date= new ArrayList<String>();
private DatabaseReference mDatabase;
public static final String TAG= "YOUR-TAG-NAME";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDatabase = FirebaseDatabase.getInstance().getReference().child("Events").child("Music");
// Read from the database
mDatabase.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.
for (DataSnapshot values: dataSnapshot.getChildren()) {
//query for the parent of the date "Eminem"
String key = values.getKey().toString();
name.add(key);
//query for location in the music category
date.add(values.child("location").getValue().toString());
//query for date in the music category
date.add(values.child("date").getValue().toString());
}
}
#Override
public void onCancelled(DatabaseError error) {
// Failed to read value
Log.w(TAG, "Failed to read value.", error.toException());
}
});
}
}
Related
I use Firebase Realtime Database and LiveData with ViewModel in Android and I would like to constantly update the query.
Here is the ViewModel class:
public class ViewModel_MainActivity extends ViewModel {
/*
LiveData with Database query for the Firebase node "Ratings"
*/
private static long currentTimeMillisRating = System.currentTimeMillis();
private static double pastMinuteForDisplayingRatings = 1;
private static long pastTimeMillisRatings = System.currentTimeMillis() - (long) (pastMinuteForDisplayingRatings * 60 * 60 * 1000);
private static final Query QUERY_RATINGS =
FirebaseDatabase.getInstance(DB_SQLite_Firebase_Entries.FIREBASE_URL).getReference().child(DB_SQLite_Firebase_Entries.FIREBASE_NODE_RATINGS).orderByChild(DB_SQLite_Firebase_Entries.FIREBASE_RATINGDATEINMILLISECONDS).endAt(pastTimeMillisRatings);
private final LiveData_FirebaseRating liveData_firebaseRating = new LiveData_FirebaseRating(QUERY_RATINGS);
#NonNull
public LiveData_FirebaseRating getDataSnapshotLiveData_FirebaseRating() {
Log.e("LogTag_ViMo", "pastTimeMillisRatings: " + pastTimeMillisRatings);
return liveData_firebaseRating;
}
}
Here is the LiveData class:
public class LiveData_FirebaseRating extends LiveData<DataSnapshot> {
private static final String LOG_TAG = "LiveData_FirebaseRating";
private Query query;
private final LiveData_FirebaseRating.MyValueEventListener listener = new LiveData_FirebaseRating.MyValueEventListener();
DataSnapshot currentDataSnapShotFromFirebase;
public LiveData_FirebaseRating(Query query) {
this.query = query;
}
public LiveData_FirebaseRating(DatabaseReference ref) {
this.query = ref;
}
public void changeQuery(Query newQuery) {
this.query = newQuery;
}
public DataSnapshot getCurrentDataSnapShotFromFirebase() {
return currentDataSnapShotFromFirebase;
}
public void setCurrentDataSnapShotFromFirebase(DataSnapshot currentDataSnapShotFromFirebase) {
this.currentDataSnapShotFromFirebase = currentDataSnapShotFromFirebase;
}
#Override
protected void onActive() {
Log.d(LOG_TAG, "onActive");
query.addValueEventListener(listener);
}
#Override
protected void onInactive() {
Log.d(LOG_TAG, "onInactive");
query.removeEventListener(listener);
}
private class MyValueEventListener implements ValueEventListener {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
setValue(dataSnapshot);
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.e(LOG_TAG, "Can't listen to query " + query, databaseError.toException());
}
}
}
And here is the part of the main activity, where the live data and view model are created and observed:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
View view = binding.getRoot();
setContentView(view);
/*
Initiate View Model with LiveData for Firebase
*/
rootRef_Firebase = FirebaseDatabase.getInstance(DB_SQLite_Firebase_Entries.FIREBASE_URL).getReference();
viewModel = new ViewModelProvider(this).get(ViewModel_MainActivity.class);
liveData_firebaseRating = viewModel.getDataSnapshotLiveData_FirebaseRating();
liveData_firebaseRating.observe(this, new Observer<DataSnapshot>() {
#Override
public void onChanged(#Nullable DataSnapshot dataSnapshot) {
liveData_firebaseRating.setCurrentDataSnapShotFromFirebase(dataSnapshot);
if(liveData_firebaseRating.getCurrentDataSnapShotFromFirebase()!=null) {
//Do something with the dataSnapshot of the query
}
}// end onChange
}); //end observe
}
So my problem lies in the non-updating of the QUERY_RATINGS in the class ViewModel_MainActivity . What I want is to return all the nodes from the FIREBASE_NODE_RATINGS whose at attribute FIREBASE_RATINGDATEINMILLISECONDS is older than 1 Minute (meaning that the entry was created at least 1 Minute before the current time slot). How can I do that such that I always get these nodes?
Firebase Query objects are immutable, and their parameters are fixed values. So there is no way to update the existing query, nor is there a "one minute ago" value that automatically updates.
The options I can quickly think off:
Create a new query frequently to capture the new full range of relevant nodes.
Create a new query frequently to capture only the new nodes (by combining startAt and endAt) and merge them with the results you already have.
Remove the condition from the query, and perform the filtering in your application code.
Based on what I know, I'd probably start with the third option as it seems the simplest.
I created tabbed activity for my project. I have three tabs which are Paid , Unpaid and Item Posted
I want to classify every of them based on the status. I have created the coding but I'm not sure on how to implement the method inside my coding. I want only order that have "PAID" as their status will be shown up inside my PaidFrag.
PaidFrag:
databaseReference = FirebaseDatabase.getInstance().getReference("Order");
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
orderList = new ArrayList<>();
for (DataSnapshot orderSnapshot : dataSnapshot.getChildren()) {
for (DataSnapshot ds : orderSnapshot.getChildren()) {
Order order = ds.getValue(Order.class);
if (order.getStatus().equals("UNPAID")) ;
orderList.add(ds.getValue(Order.class));
}
}
psOrderAdapter PsOrderAdapter = new psOrderAdapter(orderList);
recyclerView.setAdapter(PsOrderAdapter);
}
}
public void onBindViewHolder(#NonNull MyViewHolder myViewHolder, final int i) {
myViewHolder.name.setText("Name : " + orderList.get(i).getName());
myViewHolder.status.setText("Status : " + orderList.get(i).getStatus());
myViewHolder.total.setText("Total Price : RM " + orderList.get(i).getTotal());
myViewHolder.address.setText("Address : " + orderList.get(i).getAddress());
myViewHolder.dateTime.setText("Order ID :" + orderList.get(i).getOrder_id());
myViewHolder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String cust_id = orderList.get(i).getCust_id();
String oid = orderList.get(i).getOrder_id();
String status = orderList.get(i).getStatus();
String courier = orderList.get(i).getCourier();
String track = orderList.get(i).getTrackingNum();
String num = orderList.get(i).getPhone();
Intent intent = new Intent(context, updateStatus.class);
intent.putExtra("cust_id",cust_id);
intent.putExtra("order_id",oid);
intent.putExtra("status",status);
intent.putExtra("courier", courier);
intent.putExtra("trackingNum",track);
intent.putExtra("phone",num);
context.startActivity(intent);
}
});
It sounds like you're looking for a Firebase Database query, which limits what nodes are returns from the database:
databaseReference = FirebaseDatabase.getInstance().getReference("Order");
Query query = databaseReference.orderByChild("status").equalTo("PAID");
query.addValueEventListener(new ValueEventListener() {
...
You'll need to make sure that the status and PAID strings match the exact key and value that you have in your database.
For more on this, see the Firebase documentation on ordering and filtering data.
Im retrieving a UID from sqlite and using that uid to fetch data from firebase but the problem is its only fetching the values of the first UID and not after that
Code
String userId = null;
Cursor csr = myDBHlpr.getAllQuestions4();
while (csr.moveToNext()) {
userId = csr.getString(csr.getColumnIndex(KEY_USER_ID));
}
final String uid = userId;
mUsersDatabase.child(userId).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
mName = dataSnapshot.child("Name").getValue().toString();
String mStatus = dataSnapshot.child("Status").getValue().toString();
String mDisplayImage = dataSnapshot.child("Image").getValue().toString();
mUsers.add(new IdHelper(mName, mStatus, mDisplayImage));
mAdapter.notifyDataSetChanged();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
The table has multiple rows with different UIDs and firebase too has multiple UID data... I have crosschecked multiple times. But still only the one item is fetched. Why is that? should i retrieve sqlite data is a string []?
Database ref is perfect and the problem according to me is that im fetching only one data as userid and im thinking it stops there so only one IDs data is getting fetched from firebase. Anyways can someone help me out please
Edit
public Cursor getAllQuestions4() {
return this.getWritableDatabase().query(TABLE_ID_DATA,null,null,null,null,null,null);
}
I guess your problem is the while loop. You are only using the last userId. So change your code as follows (please notice the change of the last bracket of your while loop):
String userId = null;
Cursor csr = myDBHlpr.getAllQuestions4();
while (csr.moveToNext())
{
userId = csr.getString(csr.getColumnIndex(KEY_USER_ID));
final String uid = userId;
mUsersDatabase.child(userId).addValueEventListener(new ValueEventListener()
{
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
mName = dataSnapshot.child("Name").getValue().toString();
String mStatus = dataSnapshot.child("Status").getValue().toString();
String mDisplayImage = dataSnapshot.child("Image").getValue().toString();
mUsers.add(new IdHelper(mName, mStatus, mDisplayImage));
mAdapter.notifyDataSetChanged();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
I am using Firebase with my Android application. I am trying to use Firebase as a NOSQL database and this is my data retrieval object.
public class FirebaseManager {
private static final String DB_REF = "mainframeradio";
private static final String STREAM_REF = "streams";
public static List<MediaStream> getMediaStreams(Context context) {
final List<MediaStream> mediaStreams = new ArrayList<>();
FirebaseDatabase db = FirebaseDatabase.getInstance();
DatabaseReference dbRef = db.getReference(STREAM_REF);
dbRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Map<String, Object> streams = (Map<String, Object>) dataSnapshot.getValue();
if (!streams.isEmpty()) {
for (Object stream : streams.values()) {
String protocol = (String) ((Map) stream).get("protocol");
String host = (String) ((Map) stream).get("host");
int port = (int) ((Map) stream).get("port");
String media = (String) ((Map) stream).get("media");
String metadata = (String) ((Map) stream).get("metadata");
String streamName = (String) ((Map) stream).get("streamName");
MediaStream mediaStream = new MediaStream(protocol, host, port, media, metadata, streamName);
mediaStreams.add(mediaStream);
}
} else {
L.d("No media streams found on the server.");
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
L.w("Couldn't read the stream info from Firebase.");
}
});
return mediaStreams;
}
}
The thing is the event does not get triggered from the activity I am calling it from.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_player);
// Set components.
this.playerView = findViewById(R.id.playerView);
this.songTitleTextView = findViewById(R.id.songTitleTextView);
this.albumArt = findViewById(R.id.albumArt);
// Hide both the navigation and status bar (immersive).
ViewManager.setFullscreenImmersive(getWindow());
List<MediaStream> mediaStreams = FirebaseManager.getMediaStreams(this);
System.out.print(mediaStreams);
}
All I want to do is retrieve the data from firebase. This is the database.
Any help would be appreciated.
Try this to retrieve the data:
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("streams");
reference.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot datas: dataSnapshot.getChildren()){
String hosts=datas.child("host").getValue().toString();
String medias=datas.child("media").getValue().toString();
String metadata=datas.child("metadata").getValue().toString();
String ports=datas.child("port").getValue().toString();
String protocol=datas.child("protocol").getValue().toString();
String steamname=datas.child("streamName").getValue().toString();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
the datasnapshot is streams,you then will be able to iterate inside the child 0 and get the data
I am new in Firebase and that's my first App using Firebase.
My App got 15 different Scores and I separate them with a Spinner. Each time a different score is selected, it shoult be re-sorted.
It works, it always shows the correct scores but not Ordered.
Database:
My Code:
FirebaseDatabase database;
DatabaseReference databaseReference;
Query myQuery;
database = FirebaseDatabase.getInstance();
databaseReference = database.getReference().getRef().child("Users");
for (int i = 0; i < spinner.getCount(); i++) {
int x = i+1;
if (i == spinner.getSelectedItemPosition()) {
prefsEdit.putInt("selectedScore", x).apply();
myQuery = databaseReference.orderByChild("score"+possibleScores.get(i));
downloadScores();
break;
}
}
public void downloadScores() {
myQuery.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
users.clear();
for (DataSnapshot post : dataSnapshot.getChildren()) {
Users user = post.getValue(Users.class);
users.add(user);
}
UsersList scoreAdapter = new UsersList(HighscoreActivity.this, users);
scoreList.setAdapter(scoreAdapter);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
And that's my result. For example Score 6
I tried to use this too
myQuery = databaseReference.child(firebaseAuth.getUid()).child("highscores").orderByChild("score"+possibleScores.get(i));
and got this error:
com.google.firebase.database.DatabaseException: Can't convert object of type java.lang.Long to type com.example.user.app.Users
So what I overlook?
Thanks a lot