Context:
In my MainActivity I am trying to check if a value exists in the Firebase database, if it exists, it shows HomeActivity, but if it doesn't exist it will do something else. I mean, in the onStart () method, before the MainActivity is displayed and displayed to the user, the condition is checked. And if the condition is true, MainActivity should never be shown to user and HomeActivity is shown.
Problem:
I dont know why this is happening, but, if the value EXIST on firebase Database, my MainActivity is shown a few seconds and then HomeActivity is displayed. And what should happen as clarified above is that HomeActivity is shown to the user directly. I think that the method, addListenerForSingleValueEvent is the problem here, but I wouldn't know why.
Code:
#Override
protected void onStart() {
super.onStart();
DatabaseReference ref = FirebaseDatabase.getInstance().getReference().child("Users").child("Person").child(mAuth.getCurrentUser().getUid());
ref.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot data: dataSnapshot.getChildren()){
if(data.exists()){
Intent intent = new Intent (MainActivity.this, HomeActivity.class);
startActivity(intent);
MainActivity.this.finish();
}else{
FirebaseUser user = mAuth.getCurrentUser();
if(user!=null){
Intent intent = new Intent(MainActivity.this, RegistrarseActivity.class);
startActivity(intent);
}
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
}
Related
I have a method in my FollowersActivity class getFriendsAttendingEvent(); which returns the number of users that adhere to two specific criteria. Now, those users populate a list when I click on a TextView which I have in my Adapter class PostAdapter.
I need to get that number (quantity) of users that are in the list and I want to put it in the TextView in my PostAdapter class. I want to do something like holder.textView.setText(*list.size()), but how can I get that number from my FollowersActivity over to my PostAdapter class?
I know from the Adapter class I transfer data between the two classes by using Intent, but to go the other way around, would I have to create an interface or something? SharedPreferences perhaps? I don't know...
How would I send this line, String number = String.valueOf(mIdList.size()); over to my PostAdapter? This is the number that I need.
FollowersActivity
private void getFriendsAttendingEvent() {
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Attending Event").child(mPostId);
reference.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
mIdList.clear();
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
mIdList.add(snapshot.getKey());
}
DatabaseReference reference1 = FirebaseDatabase.getInstance().getReference("Following").child(mFirebaseUser.getUid());
reference1.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
mIdList1.clear();
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
for (String id : mIdList) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if (Objects.equals(snapshot.getKey(), id)) {
mIdList1.add(snapshot.getKey());
}
}
}
}
if (mIdList1.size() > 0) {
String number = String.valueOf(mIdList.size());
Log.d("NUMBEROFUSERS", number);
showUsers();
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
PostAdapter
#Override
public void onBindViewHolder(#NonNull final ViewHolder holder, int position) {
mFirebaseUser = FirebaseAuth.getInstance().getCurrentUser();
final Post post = mPost.get(position);
holder.friendsAttendingEvent.setOnClickListener(v -> {
Intent intent = new Intent(mContext, FollowersActivity.class);
intent.putExtra("id", post.getPostid());
intent.putExtra("postid", post.getPostid());
intent.putExtra("publisherid", post.getPublisher());
intent.putExtra("title", "Friends Attending");
mContext.startActivity(intent);
});
So what I have understood so far is that,
You have a PostAdapter (that displays data related to a post just like in most of the social media applications) and this Adapter has a TextView that represents the number of followers.
So, the navigation structure might be like this:
PostAdpater --- (Click on the TextView) ---> FollowersActivity
By Clicking the TextView representing the number of followers we shift to the FollowersActivity, and there you might be displaying the details of Followers. But the problem is, that you are fetching the data on the FollowersActivity where as you required it before the navigation on the PostAdapter.
The Only Simple Solution that I am able to figure out is that you move your query function getFriendsAttendingEvent() from FollowersActivity to PostAdapter, fetch the count of followers in the adapter and then pass that count to the FollowersActivity through Intent in case you do not want to re fetch data.
PostAdapter -------> FollowersActivity
(count required here) (fetching here)
PostAdapter -------> FollowersActivity
(fetch count here) (pass data here through Intent of refetch it)
Please tell me if didn't understood the problem correctly i might come up with a better solution
I have an activity in which I'm getting the data from Firebase database and showing multiple markers on the map. In onMarkerClick, I want the user to go to another activity that have details about the marker that was tapped. On first tap on the marker, it shows the title only and on second tap it goes to the other activity after doing Firebase database query to get the id for that marker so that the correct details will be provided about the tapped marker.
The problem is when I tap on any marker the first time, and then If I click on any other marker, the opened activity opens up the details of the marker that was tapped first.
If I tap on the same marker twice, it works fine. But when I come back to the map activity, tapping on any marker first time, will open up the details for the marker that was previously tapped.
What can be done to do the correct query inside onMarkerClick.
Here's the code.
#Override
public boolean onMarkerClick(Marker marker) {
eventTitle = marker.getTitle();
q = database.getReference("events")
.orderByChild("event_title")
.equalTo(marker.getTitle());
q.addValueEventListener(vel);
Intent intent = new Intent(NearbyEventsActivity.this, EventDetailActivity.class);
Bundle bundle = new Bundle();
bundle.putString("eventid", eventid);
intent.putExtras(bundle);
if (eventid != null) {
startActivity(intent);
}
return false;
}
ValueEventListener vel = new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
Event e = snapshot.getValue(Event.class);
eventid = e.getEvent_id();
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
};
The problem is when I tap on any marker the first time, and then If I click on any other marker, the opened activity opens up the details of the marker that was tapped first.
Firebase query executes asyncronously. Your ValueEventListener will not be called immediately.
Use your secound Activity start code inside onDataChange method.
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
Event e = snapshot.getValue(Event.class);
eventid = e.getEvent_id();
}
Intent intent = new Intent(NearbyEventsActivity.this, EventDetailActivity.class);
Bundle bundle = new Bundle();
bundle.putString("eventid", eventid);
intent.putExtras(bundle);
if (eventid != null) {
startActivity(intent);
}
}
Is there any way to pull data from firebase where the code is? I currently have valueEventListeners, but they all run after the code below them, thus invalidating the following code. I want to be able to pull a value exactly where the code is, not later.
As of yet, I have not found anything online about this.
A good example of my problems in the code:
public void onItemClick(AdapterView<?> l, View v, final int position, long id) {
FirebaseAuth mAuth = FirebaseAuth.getInstance();
FirebaseUser user = mAuth.getCurrentUser();
final String uid = user.getUid();
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
cCESnapshot = dataSnapshot.child(uid).child("currChallenges").child(challengeList.get(position));
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
Intent intent = new Intent();
intent.setClass(this, ChallengeView.class);
intent.putExtra("snapshot", cCESnapshot.toString());
intent.putExtra("name", challengeList.get(position));
startActivity(intent);
}
cCESnapshot is null because the intent runs before the valueEventListener.
The onDataChange() is asynchronous, so the only way to use the retrieved data is inside onDataChange(), example:
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
cCESnapshot = dataSnapshot.child(uid).child("currChallenges").child(challengeList.get(position));
Intent intent = new Intent();
intent.setClass(this, ChallengeView.class);
intent.putExtra("snapshot", cCESnapshot.toString());
intent.putExtra("name", challengeList.get(position));
startActivity(intent);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
This is an asynchronous operation, when the data will arrive, the onDataChange callback will be triggered. Your startActivty code will be executed sequentially and this is why you get no value in cCESnapshot.
Move the startActivity code inside the listener.
But be careful, because each time the onItemClick click listener will be called, you'll add a value event listener. That way, you'll have multiple calls to onDataChange in each click and so multiple startActivities.
Instead, i recommend using addListenerForSingleValueEvent which will be triggered only after a single change in data.
I want to retrieve data continuously from firebase realtime database. I have made a service for that purpose but, the service do not stops on calling stopService. I want to stop service when i got the appropriate data. Please help.
I tried
Intent intent = new Intent(MainActivity.this,BackgroundSoundService.class);
stopService(intent);
But this didn't not work. What else i need to do to stop this service?
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
IniTializeSpeech(getApplicationContext());
mDatabase = FirebaseDatabase.getInstance().getReference();
mDatabase.child("objectsData").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
String ss =(String) dataSnapshot.getValue();
Log.i("OnDataChange",ss);
t1.speak(dataSnapshot.getValue().toString(), TextToSpeech.QUEUE_FLUSH, null);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
return Service.START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
}
If you're only interested in getting the data once, you can instead use addListenerForSingleValueEvent:
mDatabase.child("objectsData").addListenerForSingleValueEvent(...
If you have a more complex condition, you can use your current code to register. But to later stop the event listener from responding to data changes, you need to remove that listener.
To do this, you first keep a reference to the listener when you register it:
ValueEventListener myListener = mDatabase.child("objectsData").addValueEventListener(...
And then you can later remove it with:
mDatabase.child("objectsData").removeEventListener(myListener)
When a user makes an account with firebase on my android app, they then need to be directed to a screen where they can add some separate information like username, for example. The app knows to switch the activity through an AuthStateListener, so when an account is made or someone signs in the code here is executed (no intents are changed here right now, keep reading to see why):
mAuthListener = new FirebaseAuth.AuthStateListener() {
#Override
public void onAuthStateChanged(#NonNull FirebaseAuth firebaseAuth) {
FirebaseUser user = firebaseAuth.getCurrentUser();
if (user != null) {
// User is signed in
Log.d(TAG, "onAuthStateChanged:signed_in:" + user.getUid());
userID = user.getUid();
toastMessage("User has signed in: " + user.getEmail());
} else {
// User is signed out
Log.d(TAG, "onAuthStateChanged:signed_out");
}
// ...
}
};
In the if block where it is checking to see if user does not equal to null, this is where I need to change the intent to another activity where they will enter their username. Basically the logic is, if the user already has a username and they are just signing in then they will be directed to the home screen activity, and if they are signing up they need to be directed to the activity where they make a username. To know which activity I need to send them to I need to have the code look in the firebase database and see if their account has a username already or not. I cannot figure out how to read data from the firebase in this situation, it seems as if the only way to read from the database (according to others) is through an onDataChange methods like so:
mRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Log.d(TAG, "This: "+dataSnapshot.getValue());
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
which uses dataSnapshots. the problem with this is this code is only fired when data is added to the database, therefor this method will not execute any code when a user is simply signing up and has never added a username to the database. How can I query to see data from the database just to check if a certain user has any data there?
OnDatachange is fired in all of cases, if user add data, remove data, change data ect.
To check is user already have username do this inside OnDatachange:
if(dataSnapshot.exists()){
//GO TO OTHER ACTIVITY
]else{
//GO TO SET USER DATA ACTIVITY
]
See this exemple of one of my implementations:
if (user !=null){
DatabaseReference myRef = database.getReference("users").child(user.getUid()).child("user_bio");
myRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()){
bio.setText(dataSnapshot.getValue(String.class));
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
In this exemple if user_bio exists then set text to userbio if not do nothing. In the first time that user log in in my app this method do nothing but when user add bio this method set the bio text in userbio text. but if i want to show some text if user hasnt bio i simply add na else and set text to the bio for exemple:
if (user !=null){
DatabaseReference myRef = database.getReference("users").child(user.getUid()).child("user_bio");
myRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()){
bio.setText(dataSnapshot.getValue(String.class));
}else{
bio.setText("no user bio");
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
Have you try to use addValueEventListener inside onCreate method?
If you run an activity while the listener inside onCreate method it will fired once when you open an activity. So i think you shouldn't have a problem here.