I'm trying to make a class with some methods to get user's info. I'm making it like libraries.
For example, the current logged in user has some data in firestore. Say I want to retrieve his username.
This is placed in the same activity where I want to retrieve the username.
String currentUserUsername;
private String getUserUsername(DocumentReference currentUserDocument) {
currentUserDocument.get().addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
#Override
public void onSuccess(DocumentSnapshot documentSnapshot) {
currentUserUsername = documentSnapshot.getString("username");
}
});
return currentUserUsername;
}
And I'm calling getUserUsername(currentUserDocument) after activity onCreate so I can use currentUserUsername anywhere I want in the code. But the problem is that I'm doing this in many activities. How can I make it like a public class like those libraries?
Related
I am working on an Android app with 2 types of users (doctors and patients), and I want each type to have their own UI. For eg, doctors must see ' Add days off' and patients must see ' Book appointment' . Somehow I don't get anywhere with whatever I try.
I also use Firebase Auth and Realtime Database which makes the user type retrieval kinda tricky. So far I've tried a lot of Async classes, methods, variables, shared preferences, retrieving data while on launcher splash screen.
The best I got is getting the user to login, it shows the good layout, then I start the app again and it shows the wrong layout. Somehow I noticed it just works on the second run, but not always so the behaviour is unpredictable to me at least. But at least the user type from the database is retrieved.
I have a class that extends Application, which checks if there's an user authenticated and then redirects the user to either LoginActivity, or MainMenuActivity.
I have created a method that retrieves the Firebase Auth user data from Realtime Database, looping through both Doctors and Patients 'children' until it finds the current user email and gets its type. Since Realtime Database is asynchronous, the methos gets an interface as an argument, and after the loop, the I call the interface's method, which sets a static boolean variable (isUserDoctor).
Before setting the content view (with 2 possible layouts), I call the function described before and it works the way I first mentioned, which is not good.
The method that retrives data
public void getUserType(final DataStatus dataStatus) {
currentUser = FirebaseAuth.getInstance().getCurrentUser();
currentUserEmail = currentUser.getEmail();
databaseReference = FirebaseDatabase.getInstance().getReference("Users");
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
currentUserType.clear();
FirebaseManager.isUserDoctor = false;
DataSnapshot allDoctors = dataSnapshot.child("Doctors");
DataSnapshot allPatients = dataSnapshot.child("Patients");
for (DataSnapshot ds : allDoctors.getChildren()) {
if (currentUserEmail.equals(Utils.decodeUserEmail(ds.getKey()))) {
currentUserType.add(ds.child("userType").getValue().toString());
} else {
for (DataSnapshot dsPacient : allPatients.getChildren()) {
if (currentUserEmail.equals(Utils.decodeUserEmail(dsPacient.getKey()))) {
currentUserType.add(dsPacient.child("userType").getValue().toString());
}
}
}
}
dataStatus.DataIsLoaded(currentUserType.get(0).toString());
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
The interface
public interface DataStatus {
void DataIsLoaded(String userType);
}
The method's call in Main Menu
FirebaseManager.getInstance().getUserType(new DataStatus() {
#Override
public void DataIsLoaded(String userType) {
if ("doctor".equals(userType))
FirebaseManager.isUserDoctor = true;
else
FirebaseManager.isUserDoctor = false;
}
});
if (FirebaseManager.isUserDoctor)
setContentView(R.layout.activity_main_menu_doctor);
else
setContentView(R.layout.activity_main_menu);
So if anyone has any ideas about how to show the proper layout and allow functions based on user role/type please share. What I basically need is to retrieve the userType from the current email just in time to set a variable needed throughout the whole app in order to hide/show certain views.
I am developing android chat app following this i am retriving the whole list of friends Then on the basis of their user id i retrive the user's data from the user data that is user name, user image and user status the databases are shown below.
and
So now what is the main problem, the main problem is by the following code:
#Override
protected void onBindViewHolder(FriendsFragment.friendsViewHolder holder, int position, Friends model) {
final String list_User_id=getRef(position).getKey();
mUserdatabase.child(list_User_id).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
UserName = dataSnapshot.child("name").getValue().toString();
friendsViewHolder.setName(UserName);
UserStatus = dataSnapshot.child("status").getValue().toString();
friendsViewHolder.setStatus(UserStatus);
thumb_img = dataSnapshot.child("thumb_img").getValue().toString();
friendsViewHolder.setThumbnail(thumb_img,getActivity());
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent prfile_Intent=new Intent(getActivity(),ProfileActivity.class);
prfile_Intent.putExtra("User_id",list_User_id);
startActivity(prfile_Intent);
}
});
it give me a recyclerView in result
in which only last element is show as shown in figure
i google it and also searching on Stackover flow but cannot find the solution from last 3 days.
A simillar is Question is asked but i cannot solve my problem from here
please help and donot down vote my question
thanks for help
addValueEventListener in the onBindViewHolder method is the very bad idea. You can make a list of user in your Fragment and pass that list into Adapter.
This is happening because the onBindViewHolder() method is called as many times as the number of items that are coming from your database. So in this case, everything is inside this method is also triggered. This means that you are attaching a listener on every onBindViewHolder() method call. There is no need for doing that. You can simply get the user name and all the other properties directly from the model object which is passed as an argument to this method like this:
String UserName = model.getUserName();
String UserStatus = model.getUserStatus();
//And so on for the other properties.
I have an existing array that I created locally and import to Firebase and my array looks like this.
These both elements are objects created that have some many information related to appointments.
Now i am trying to create a new element with the same form, for example:
2--
|__ And the object I have created in my app
I have only managed or eliminate the rest of the elements (with setValue(object))
Appointment newAppointment = new Appointment.Builder()
.fechacita(dateSelected)
.horacita(hourSelected)
.usertoken(mAuthManager.getCurrentUserId())
.oficina(centerSelected)
.build();
mDatabaseRef.child("LISTACITAS").setValue(newAppointment);
or create it with an ID that when recovering the data causes a crash in the application due to the deserialization of the objects that are not equal.
The Appointment object that I want to insert is
public class Appointment implements Parcelable {
private String fechacita;
private String horacita;
private Office oficina;
private String userID;
.....
}
The class is a normal Parcelable class that generates an object with her builder.
Please some help...
try this code
mDatabaseRef.push().setValue(incidentReportUser)
Write it this way (push() adds values instead of overriding).
Ans from here
UPDATE 1
if you want a series in key, not some random value, try this:
get the last key in the list using
Query dbQry = mDatabaseRef.orderByKey().limitToLast(1);
dbQry.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
int key = Integer.parseInt(dataSnapshot.getKey());
//Increment the key and add the object here using the earlier method
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
}
I have not checked this as of now, but you could get the idea
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
I'm migrating to Backendless from Parse and is currently trying to do something that was pretty obvious with Parse.
I'm creating a class:
#ParseClassName("UserPreferences")
public class UserPreferences extends ParseObject {
public ParseFile getBackground(){
return getParseFile("background.jpg");
}
public boolean getAudioStatus(){
return getBoolean("audio");
}
public void setAudioStatus(boolean status){
put("audio", status);
}
}
Now I want to assign this class to the currently logged in user as a pointer:
UserPreferences userPrefs = new UserPreferences();
userPrefs.setAudioStatus(true);
ParseUser user = ParseUser.getCurrentUser();
user.put("prefs", userPrefs);
userPrefs.saveInBackground()
user.saveInBackground(); //again, use SaveCallback
and to retrieve all values etc to be applied to local preferences:
ParseUser user = ParseUser.getCurrentUser();
UserPreferences userPrefs = user.getParseObject("prefs");
userPrefs.fetchInBackground();
This way, the user's data is always tied to himself and objectID etc isn't a problem.
Now I didn't work this out myself when using Parse. So unfortunately I can't really talk for this matter. I just hope someone more experienced see's what I'm doing and can relate this into translating it to Backendless SDK and workflow somehow?
You do not need to extend any specialized Backendless classes in the objects you save/load to/from Backendless. In the classes you can use either public fields or getter/setter properties. You do not need to use any annotations. Things are much simpler. If you have a class A which references class B (via a field or a javabean property), then on the backend, we will store A in a table called "A" and B in a table called "B". We will also create a relation between the two records on the backend.
There are two ways you could handle what you showed with Backendless:
Saving user object with preferences:
BackendlessUser user = Backendless.UserService.CurrentUser();
user.setProperty( "audioStatus", true );
user.setProperty( "backgroundImageUrl", url-to-background-jpg );
Backendless.UserService.save( user, asyncCallback );
This will result in creating two columns in the Users table: "audioStatus" and "backgroundFile". If, however, you want to have a separate table where all the preferences are, you could do this:
public class UserPreferences
{
// or use Java bean getter/setter instead of fields
public String backgroundImageUrl;
public boolean audioStatus;
}
UserPreferences prefs = new UserPreferences();
prefs.backgroundImageUrl = url-to-background-jpg;
prefs.audioStatus = true;
BackendlessUser user = Backendless.UserService.CurrentUser();
user.setProperty( "userPrefs", prefs );
Backendless.UserService.save( user, asyncCallback );
This will result in a secondary table created on the backend. The table will be called "UserPreferences" - just like the class name. Backendless will also create a relationship between the user object and the specific record in the UserPreferences table.
Retrieving user properties
If the user properties are not stored via a relation (see the first sample above), then they are loaded right away when the user logs in. Then you can get the properties with the getProperty method:
Backendless.UserService.login( userName, password, new AsyncCallback<BackendlessUser>()
{
#Override
public void handleResponse( BackendlessUser user )
{
boolean audioStatus = (boolean) user.getProperty( "audioStatus" );
String fileUrl = (String) user.getProperty( "backgroundImageUrl" );
}
#Override
public void handleFault( BackendlessFault backendlessFault )
{
}
});
If the preferences are stored in a related table, then you have several options to load them:
BackendlessUser user = Backendless.UserService.CurrentUser();
ArrayList<String> relations = new ArrayList<String>();
relations.add( "userPrefs" ); // name of the relation column in Users
Backendless.Data.of( BackendlessUser.class ).loadRelations( user, relations, new AsyncCallback<BackendlessUser>()
{
#Override
public void handleResponse( BackendlessUser user )
{
// user - object with loaded relations.
// now you can do this:
UserPreferences prefs = (UserPreferences)user.getProperty( "userPrefs" );
}
#Override
public void handleFault( BackendlessFault backendlessFault )
{
}
});
Hope this helps!
I have to pass some data related to user between to activities, data is
name, user id, user name, email
now to do this I have to put these values in Intent and pass to other activity.
Now there a two ways
1)
Create a DTO for User say UserDto and make it Serializable and pass it using intent
intent.putExtra("user",userDto);
2)
put all four different values in intent as
intent.putExtra("name",name);
intent.putExtra("userid",id);
intent.putExtra("username",username);
intent.putExtra("email",email);
which one of above is most optimized way,
Please recommend some other way of maintaining user throughout the application scope.
You can have one Application class in your project like:
public class MyApplication extends Application {
private User user;
#Override
public void onCreate() {
super.onCreate();
}
public void setUser(User user){
this.user=user;
}
public User getUser(){
return user;
}
}
Or you can have some static class or some interface to hold application state (I.E. your user object)
In app manifest
<application android:name="<-pkgname->.MyApplication" ......>
and at any activity in your application you can get it as
MyApplication myApp=(MyApplication)getApplicationContext();
User user=myApp.getUser();
You can store the data as a static variable. So the data will be maintain throughout the application scope.
The best practice is to store data in the Shared Preference.