I have a textView in my activity - say, "Username". It is supposed to be populated from a Firebase database. I am making the Firebase query in Asynctask so as not to block the activity. However that means that the TextView loads first, before the Firebase query is completely executed.
So what is the best way to refresh this textBox after the Firebase query is executed inside the AsyncTask and the username gets known?
I do not want to showprogressBar and block the activity while the data is being fetched from the database. That would defeat the purpose of doing it in AsyncTask.
Code for the AsyncTask is below
private class CheckUserLoginAndRetrieveDataFromFirebase extends AsyncTask <Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... voids) {
if (thisAppUser!=null) {
setUserDataForToday();
if (createNewNode) { //This is the first time the User is logging in
createUsersNodesForFirstTime();
}
}
return null;
}
Code for my Firebase Query in the AsyncTask is below
public static void setUserDataForToday() {
setProperDatabaseReference(); //This sets reference to user specific nodes in the database
myRef.child("dashboard").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Dashboard dashboard = dataSnapshot.getValue(Dashboard.class);
if (dataSnapshot.getChildrenCount() > 0) {
createNewNode = false;
if (dashboard.checkIfTodaysDateExistsInDatabase()) {
//An entry for todays date exists in database, so no data change needed
myDashboard = dashboard;
}
I hope this example will help you
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setUserDataForToday();
Log.d("MainActivity", "Process is not blocked");
}
public void setUserDataForToday() {
Log.d("MainActivity", "Called method");
DatabaseReference database = FirebaseDatabase.getInstance().getReference();
database.child("users").child("1").child("name").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
String userName = dataSnapshot.getValue(String.class);
Log.d("MainActivity", "Received value: " + dataSnapshot.getValue());
dataSnapshot.getKey();
TextView textView = (TextView) findViewById(R.id.textUserName);
textView.setText(userName);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.d("MainActivity", "DB error: " + databaseError.getMessage());
}
});
}
public void onClick(View v) {
setUserDataForToday();
}
}
If you are working with Android studio click tools>Firebase>Realtime Database and follow instructions. This will get you started. You probably want to click tools>firebase>authentication if you want to have users and if you want only certain users to access certain things configure rules for the database. Frank is correct no need for async task.
Related
So, I have an activity in my app where I need to take in the number of tickets for different ticket classes that are retrieved from the backend. The number of ticket classes is also variable. How do I take the user input in this case? Each time the countdown_btn or countup_btn is pressed, I need to update an array that holds the number of tickets the user has chosen. How do I do this when the number of ticket classes itself is dynamic?
If the button 'pledge' is clicked, I want to take the respective inputs from each of the views here and somehow communicate it to the next activity using intent.
My app's code:
public class RewardsAndPledgeActivity extends AppCompatActivity {
DatabaseReference mRewardsRef;
RecyclerView rewards_list;
String Artcall_id;
String reward_id[];
Integer counter = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_show_rewards);
/* -------- Obtain the Event ID of the item that the user has selected on the RecyclerView ------*/
Intent intent = getIntent();
Artcall_id = intent.getStringExtra("Artcall_id");
/* ----------------------------------------------------------------------------------------------*/
mRewardsRef = FirebaseDatabase.getInstance().getReference().child("Rewards").child(Artcall_id);
rewards_list = (RecyclerView) findViewById(R.id.reward_list);
rewards_list.setHasFixedSize(true);
rewards_list.setLayoutManager(new LinearLayoutManager(this));
}
#Override
protected void onStart() {
super.onStart();
FirebaseRecyclerAdapter<Reward_List, RewardsViewHolder> firebaseRecyclerAdapter = new FirebaseRecyclerAdapter<Reward_List, RewardsViewHolder>(
Reward_List.class,
R.layout.single_reward_item_layout,
RewardsAndPledgeActivity.RewardsViewHolder.class,
mRewardsRef
) {
#Override
protected void populateViewHolder(final RewardsViewHolder viewHolder, Reward_List model, int position) {
final String reward_id = getRef(position).getKey();
viewHolder.setReward_ticket_amount_txt(model.getReward_ticket_amount_txt());
viewHolder.setReward_ticket_amount_class_name(model.getReward_ticket_amount_class_name());
viewHolder.setReward_ticket_class_desc(model.getReward_ticket_class_desc());
viewHolder.countdown_btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Integer current_ticket_count = Integer.parseInt(viewHolder.ticket_counter.getText().toString());
if(current_ticket_count >0 ) {
viewHolder.ticket_counter.setText(String.valueOf(current_ticket_count - 1));
}
}
});
viewHolder.countup_btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Integer current_ticket_count = Integer.parseInt(viewHolder.ticket_counter.getText().toString());
viewHolder.ticket_counter.setText(String.valueOf(current_ticket_count + 1));
}
});
}
};
rewards_list.setAdapter(firebaseRecyclerAdapter);
}
}
My database:
Image of the activity:
Hello so I've been strugging for awhile now. I want to consult someone about my code. I want to apply
a coloring function to my app.
When the person presses the button when it's at its:
GREEN state it updates the value on the database to BEING HOUSEKEPT
YELLOW state when pressed sends READY FOR INSPECTION RoomStatus
RED state when pressed sends READY FOR HOUSEKEEPING RoomStatus
It was working earlier but when I tried to restrict the users that users who are Housekeepers can't access the RED STATE which are for House Keepers, I inserted somewhere in my code where I want to implement it.
I'm going over loops here can somebody tell me where I did wrong?
Here's my code:
Button room1;
private DatabaseReference mFirebaseDatabase, mFirebaseDatabase1, mFirebaseDatabase1room;
private FirebaseDatabase mFirebaseInstance;
private DatabaseReference referenceroom1;
private String roomStat;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_navi_to_scan2);
mFirebaseInstance = FirebaseDatabase.getInstance();
mFirebaseDatabase1 = mFirebaseInstance.getReference("Rooms");
mFirebaseDatabase = mFirebaseInstance.getReference("Users");
mFirebaseDatabase1room = mFirebaseInstance.getReference("Rooms").child("Room1");
referenceroom1 = mFirebaseDatabase1.child("Room1").child("RoomStatus");
room1 = (Button) findViewById(R.id.rm1Btn);
mFirebaseDatabase1.child("Room1").addValueEventListener(new ValueEventListener() { //attach listener
#Override
public void onDataChange(DataSnapshot dataSnapshot) { //something changed!
for (DataSnapshot locationSnapshot : dataSnapshot.getChildren()) {
String location = locationSnapshot.getValue().toString();
if (location.equals("READY FOR HOUSEKEEPING")) {
room1.setBackgroundColor(Color.GREEN);
roomStat = "Green";
} else if (location.equals("BEING HOUSEKEPT")) {
room1.setBackgroundColor(Color.YELLOW);
roomStat = "Yellow";
} else {
room1.setBackgroundColor(Color.RED);
roomStat = "Red";
}
if (roomStat.equals("Green")) {
room1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String message = "BEING HOUSEKEPT";
DatabaseReference reference = mFirebaseDatabase1.child("Room1").child("RoomStatus");
reference.setValue(message);
Intent next1 = new Intent(getApplicationContext(), ReaderActivity3.class);
startActivity(next1);
}
});
} else if (roomStat.equals("Yellow")) {
room1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String message = "READY FOR INSPECTION";
DatabaseReference reference = mFirebaseDatabase1.child("Room1").child("RoomStatus");
reference.setValue(message);
Intent next1 = new Intent(getApplicationContext(), ReaderActivity2.class);
startActivity(next1);
}
});
} else {
room1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String message = "READY FOR HOUSEKEEPING";
DatabaseReference reference = mFirebaseDatabase1.child("Room1").child("RoomStatus");
reference.setValue(message);
Intent next1 = new Intent(getApplicationContext(), ReaderActivity.class);
startActivity(next1);
//I ALSO WANT TO PUT A CONDITION HERE FETCHING userType from Structure
// mFirebaseDatabase = mFirebaseInstance.getReference("Users").child("userKey");
//but doing this would mean that I would have to put a listener inside, would that be okay? I tried when this
//was working at first but it didin't and now the whole thing is not working
}
});
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) { //update UI here if error occurred.
}
});
}
Here's my structure:
Can you help me identify what's the problem with how i implemented this?
I see nothing wrong, try debugging. Android is buggy nowadays, especially when you're connecting to a cloud database. In the left side of the run button the bug shaped one. Debug.
Or maybe you could try to show your location which is your string, to check if you pulled the right info from your database. You can use logs. A guide can be found here
https://developer.android.com/studio/debug/am-logcat.html
I need to give a custom login. I don't want to use login providers like google, facebook,etc. I need old school single data retrieval of users info(name and phone in my case) and if user data is found in the database then redirect to home page.I have tried something and it's not working.
java snippet
................................................
public class LoginActivity extends AppCompatActivity {
EditText editTextname;
EditText editTextphone;
Button buttonlogin;
Spinner spinnerdesignation;
DatabaseReference rootRef= FirebaseDatabase.getInstance().getReference();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
editTextname=(EditText)findViewById(R.id.name);
editTextphone=(EditText)findViewById(R.id.phonenumber);
spinnerdesignation=(Spinner)findViewById(R.id.designation);
buttonlogin=(Button)findViewById(R.id.login);
buttonlogin.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
findUser();
}
});
}
public void findUser(){
String designation=spinnerdesignation.getSelectedItem().toString();
if(designation=="Faculty"){
rootRef.child("Faculty").orderByChild("facultyName").equalTo(editTextname.toString()).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Map<String,String> map=dataSnapshot.getValue(Map.class);
String phoneNumber=map.get("facultyPhone");
if(phoneNumber==editTextphone.toString()){
Intent intent=new Intent(getApplicationContext(),FacultyActivity.class);
startActivity(intent);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}
}
database
-Root
-Faculty
-Kg5Qe482G7xEn9rYLXn
facultyDept:"computer science"
facultyDesignation: "HOD"
facultyEmail: "ajaskjfjaj#gmail.com"
facultyID: "-Kg5Qe482G7xEn9rYLXn"
facultyName: "john"
facultyPhone: "1234567891"
-Kg5QjXQIZeuwvHi22WH
-Student
-Kg-Jg1f68RXb4N47sbA
You should use String#equals method when comparing strings. Do not use ==.
I'm playing around with Firebase and Android and I'm storing my data online in Firebase. I have an activity with 3 EditTexts and a button and I want it to essentially check that the 3 values in the textboxes are in the database and if so, move onto the next activity.
These values are static and so I'm using the .addListenerForSingleValueEvent method and using it as an anonymous function. I want this to work even if the device is offline but if any of the values come back as null then I want it to reject moving to the next activity.
Is there any way to detect when Firebase has either retrieved a value from the database or retrieved null from the database? This way I could check each value consecutively and if any return null then reject changing activities.
The only other thing I could think to do is to nest the anonymous functions for each listener but that sounds like it would be a bad idea.
Any advice would be much appreciated. Thanks!
Well, i understand you want to check for values in your database before moving to the next activity. My advice is that
1) create an ArrayList of DatabaseReference that point to the data locations in firebase in your activity.
Arraylist<DatabaseReference> list = new ArrayList<>();
list.add(FirebaseDatabase.getInstance().getReference().child("my_child_node_1"):
list.add(FirebaseDatabase.getInstance().getReference().child("my_child_node_2"):
list.add(FirebaseDatabase.getInstance().getReference().child("my_child_node_3"):
2) create an interface and a call back method.
public static interface DataCallback {
static void onDataAdded(String string); //Use the necessary data type
}
3) use the interface to create a constructor for your Event listener.
public static class DataListener implements ValueEventListener {
private DataCallback dataCallback;
public DataListener(DataCallback dataCallback) {
this.dataCallback = dataCallback;
}
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String data = snapshot.getValue(String.class);
//This is step 4
if(dataCallback!=null) {
dataCallback.onContactAdded(data);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
}
4) Pass the value from the listener to your activity as follows inside onDataChange() method of the Listener
if(dataCallback!=null) {
dataCallback.onContactAdded(data);
}
5) implement the interface in your activity and override its callback method
public class MyActivity extends AppCompatActivity implements DataCallback{
private EditText edittext1;
private EditText edittext2;
private EditText edittext3;
private ArrayList<String> my_list;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//do stuff...
}
#Override
public void onDataAdded(String data) {
}
}
6) Instantiate and add the listener in your activity's onResume() method
#Override
public void onResume(){
super.onResume();
DataListener listener = new DataListener(this);
list[0].addListenerForSingleValueEvent(listener);
list[1].addListenerForSingleValueEvent(listener);
list[2].addListenerForSingleValueEvent(listener);
}
7) get the values from firebase in your activity inside the Callback method as follows
#Override
public void onDataAdded(String data){
my_list.add(data);
}
8) you can check if the values gotten from firebase match the values gotten from the EditText inside the OnClicklistener for you button.
if (button != null) {
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(my_list.contains(edittext1.getText().toString)){
if(my_list.contains(edittext.getText().toString)){
if(my_list.contains(edittext.getText().toString)){
startActivity(new intent(MyActivity.this, NextActivity.class))
}
}
}
}
});
}
9) remove the listeners inside the onPause() method.
#Override
public void onPause(){
super.onPause();
list[0].removeEventListener(listener);
list[1].removeEventListener(listener);
list[2].removeEventListener(listener);
}
My Firebase database structure is:
I want to retrieve the full name of some user, when I have its key.
My code:
public class ProfileActivity extends AppCompatActivity implements View.OnClickListener {
private FirebaseAuth firebaseAuth;
private TextView textView;
private Button logbutton,wantToDeliverButton,lookForButton;
private String userName;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_profile);
Firebase.setAndroidContext(this);textView = (TextView)findViewById(R.id.textView2);
Firebase usersRef = new Firebase("https://myfirstfirebaseauth.firebaseio.com");
firebaseAuth = FirebaseAuth.getInstance();
if (firebaseAuth.getCurrentUser() == null){
finish();
startActivity(new Intent(this,LoginActivity.class));
}
FirebaseUser user = firebaseAuth.getCurrentUser();
Firebase ref = usersRef.child("User").child(user.getUid());
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
userName = dataSnapshot.getValue(User.class).getFullName();
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});
textView.setText("welcome "+userName);
}
}
But it set the textView to null. I try to put Toast inside the onDataChange() method, but it doesn't work. It seems it doesn't even get inside the method.
The line FirebaseUser user = firebaseAuth.getCurrentUser(); is correct because if i'm writing textView.setText("welcome "+ user.getEmail()); - I really get the correct email.
How to solve this? Am I using the correct listener? I don't want to change anything in the database, just retrieve.
Edit: it goes to onCancelled().
You're mixing capabilities from the legacy 2.5.X Firebase SDK (Example: Firebase.setAndroidContext()) and the new 9.X.X SDK (Example: FirebaseAuth.getInstance()). That is almost certainly a recipe for failure. Rework your code to use only the new SDK. The Setup Guide is here.