I am new to Android but I am attempting to build an app that would allow a User to add other users to a Group .
I have made a User and Group class, and I am trying to add a user to this group . . I am hoping that maybe someone here can point me in the right direction.
At the moment I have a User object and I am attempting to add this to a List within my Group object. Is this how users would be managed for an android app with user groups?
I feel like there is something obvious I am missing!
I am using Firebase Realtime Database also and need to be able to store users added to a particular group so it is consistent on all users devices.
e.g. User 1 adds User 2 to Group A, both User1 and User 2 will see on their device that User 2 is in Group A
Code below:
Group Class
public class Group {
public List<User> memberList = new List<User>() {....};
public Group() {
}
public Group(List<User> users) {
this.memberList = users;
}
public void addMember(User member) {
this.memberList.add(member);
}
public List<User> getMemberList() {
return memberList;
}
}
Main Class
User user = new User(uId, name);
Group group = new Group();
group.addMember(user);
groupsDatabase.child("test_group").push().setValue(group.memberList.get(0));
Related
I want to search data from firebase. whenever a user type anything in the searchview it will search the related data. For example if user input the name of company it should show data related to that company, OR if user input price it should show data related to that specific price. My Recyclerview is working fine. I'm getting data but it only search data according to company name.
Here is My Code
private void getData(String query) {
Query firebaseSearchQuery = myRef.orderByChild("companyName").startAt(query).endAt("\uf8ff");
FirebaseRecyclerOptions<Package> options = new FirebaseRecyclerOptions
.Builder<Package>().setQuery(firebaseSearchQuery, Package.class).build();
final FirebaseRecyclerAdapter<Package, PackagesViewHolder> firebaseRecyclerAdapter =
new FirebaseRecyclerAdapter<Package, PackagesViewHolder>(options) {
#Override
protected void onBindViewHolder(#NonNull PackagesViewHolder packagesViewHolder, int i, #NonNull Package aPackage){
packagesViewHolder.setDetails(getApplicationContext(), packagesViewHolder, i, aPackage.getPackageName()/*, aPackage.getPackageType()*/, aPackage.getCompanyName(), aPackage.getData()
, aPackage.getOnNetMinutes(), aPackage.getOffNetMinutes(), aPackage.getSms()
, aPackage.getPrice(), aPackage.getValidity()
, aPackage.getSubscriptionCode(), aPackage.getUnsubCode()
, aPackage.getRemainingDataCode(), aPackage.getInfo()
/*, aPackage.getTermsAndConditions()*/);
}
#NonNull
#Override
public PackagesViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_layout, parent, false);
PackagesViewHolder packagesViewHolder = new PackagesViewHolder(view, SearchActivity.this);
return packagesViewHolder;
}
};
recyclerView.setAdapter(firebaseRecyclerAdapter);
firebaseRecyclerAdapter.startListening();
}
There is no built-in operator on Firebase to search across all properties of a node. If your app requires such functionality, you might want to consider using a different/additional database for that, such as using Algolia for the searches and Firebase for the realtime sync.
Alternatively, you can build your own search structure inside of Firebase, as I've shown in my answer here: How to query based on multiple conditions in Firebase?
Also see:
Google Firestore: Query on substring of a property value (text search)
How to query firebase for property with specific value inside all children
How to perform sql "LIKE" operation on firebase?
Angularfire: How to access an item by one of it's properties?
You need to add an extra attribute to the database for example:
price-name : "18 comp"
And then do :
Query firebaseQuery = myRef.orderByChild("price-name").startAt(query).endAt("\uf8ff");
There is no or clause in firebase Realtime Database. The above is an alternative to be able to achieve that.
my current app takes customer details, sends them to a real time firebase database, a switch activity button takes the user to a customer information page where it displays all data in the database, i am wondering if its possible to update specific users without using authentication to log in as its the shop owner using this app not customers.
All videos i have found use the firebase authentication which allows for user details to be updated, but my app lists all database data as no specfic logged in user.
below is my class that recieves the database information and displays it on screen
public class CustomerDataRetrieved extends AppCompatActivity {
private ListView listView;
DatabaseReference databaseReference;
Firebase firebase;
List<CustomerName> customerNameList;
public static final String Database_Path = "Customer Details";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_customer_data_retrieved);
listView = (ListView) findViewById(R.id.list_view);
firebase = new Firebase(Firebase_Server_URL);
databaseReference = FirebaseDatabase.getInstance().getReference(Database_Path);
customerNameList = new ArrayList<>();
}
#Override
protected void onStart() {
super.onStart();
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot customerSnapshot : dataSnapshot.getChildren()) {
CustomerName customers = customerSnapshot.getValue(CustomerName.class);
customerNameList.add(customers);
}
CustomerInfoAdapter customerInfoAdapter = new CustomerInfoAdapter(CustomerDataRetrieved.this,customerNameList);
listView.setAdapter(customerInfoAdapter);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
}
If this helps, this is an image of my Customer Information activity which uses a listview to display all the data from the database, and i am wondering if its possible to update specific information from each user if required through my app, for instance if the customers quoted price changes, or contact number has changed
In order to update a specific node in the database you need to know something that identifies that node. When storing user data that is typically the UID of the user. But if you're not using Firebase Authentication, it can be anything else that identifies the user(s) whose node you want to update.
In addition to to knowing the path, you must also have permission to update the node. This is why you often see Firebase Authentication's UID being used, as it allows securing access to the data based on who the user is. If you're not using Firebase Authentication, you'll have to come up with a different scheme to protect your data.
I am developing an android application where older kids can pick up younger kids and walk to school. With the application the authenticated (email and password) younger kid can choose between three adresses to get picked up. As of right now my realtime database looks like this:
I want to retrieve the different addresses and the users who picked the addresses. I am thinking I have to use recyclerview to get the data, but I am unsure on if it is possible to do with my database structure.
Using the FirebaseUI database package makes it simple to bind data from the Firebase Realtime Database to your app's UI. Specifically using FirebaseUI with indexed data is applicable for your current database structure.
For example, you'd use something similar to:
// keyQuery - the Firebase location containing the list of keys to be found in dataRef
// dataRef - the Firebase location to watch for data changes. Each key found at
// keyRef's location represents a list item.
Query keyQuery = FirebaseDatabase.getInstance().getReference("/Addresses/Street 10/users");
DatabaseReference dataRef = FirebaseDatabase.getInstance().getReference("/User");
FirebaseRecyclerOptions<User> options = new FirebaseRecyclerOptions.Builder<User>()
.setIndexedQuery(keyQuery, dataRef, User.class)
.build();
Where your User class is:
public class User {
private String username;
public User() {}
public String getUsername() {
return this.username;
}
public void setUsername(String username) {
this.username = username;
}
// ...
}
You can then use the above created options variable to create a FirebaseRecyclerAdapter instance and then call startListening() on it*.
Using FirebaseUI in this way will automatically handle matching the keys under /Addresses/Street 10/users to the /User node.
* Version 2.x of FirebaseUI uses FirebaseIndexRecyclerAdapter instead and starts listening automatically so doesn't require a startListening() call. The above example is applicable for version 3.0, see FirebaseUI 3.0 upgrade guide.
Following on from my previous answer, this one should accommodate your requirement to create a list of all addresses and their associated users, which may be closer to what you're looking for.
Again you can use the FirebaseUI database package to simplify the RecyclerView creation.
You'll need to start denormalizing your data, so your data structure should also include usernames in the addresses node:
{
"Addresses" : {
"Street 10" : {
"name" : "Street 10",
"users" : {
"VAzdMWafK6cyhmJnOI4br5xiQg93" : "John"
}
}
},
"User" : {
"VAzdMWafK6cyhmJnOI4br5xiQg93" : {
"username" : "John",
"address" : "Street 10"
}
}
}
Note: you only need to add user IDs to their chosen address (and remove the node if they change selection), so don't use "VAzdMWafK6cyhmJnOI4br5xiQg93" : false for addresses the user has not selected as this could cause confusion.
Then you can use:
Query query = FirebaseDatabase.getInstance().getReference("/Addresses");
FirebaseRecyclerOptions<Address> options = new FirebaseRecyclerOptions.Builder<Address>()
.setQuery(query, Address.class)
.build();
Where Address is something like:
public class Address {
private String name;
private Map<String, String> users;
public Address() {}
public Map<String, String> getUsers() {
return this.users;
}
// ...
}
And create a FirebaseRecyclerAdapter instance from the options variable. Then when binding the viewholder in the adapter, you can access the users map to list each user that has selected this address, without the need to load the entire User object unnecessarily.
This pattern is called denormalization and is the suggested approach when using NoSQL databases (like Firebase Realtime Database). The main downside to this is data duplication: so for example, when a user changes their selected address, you'll need to change:
The address value under the user, and
the users list under the address.
Likewise, if a user is allowed to change their username, you'll need to update the username under their chosen address as well as in the user's node.
For details on dealing with this, see this answer which explains a number of methods (although the examples are in JavaScript, the premise still applies).
What approach is Whatsapp using to show an "Invite" button for contacts which are not on Whatsapp?
I also want to show a button in Contact list view for only those which don't exist in my app in Firebase database.
I am using Custom BaseAdapter to show contacts in List View.
Can you please help me in understanding how Whatsapp Contact is working?
My Question is not duplicate as that is to read contact list only. I want to show 'Invite' button also as per firebase data.
Thanks!
Well I am not confident what exactly whatsapp is using but as I can the contacts that are not on whatsapp appear in the last. So you can dump the contact list from your firebase Db then query the contacts in the device and make two arraylist in which one is having contact list present in your app means your app users then another is the new users then merge them and show in the Recyclerview or Listview as per your requirement and for invite button you can use different cell layout which contais a button by setting any bool in array list and check it in your base adapter or you can also set its visibility in the same cell as per data in your arraylist.
First of All you have to get the all contacts from clients device,
Note : You Have to Check For Contacts Permissions by your self & don't Forgot to add Permissions Manifest.
Call initData() in onCreate or After Checking Permissions.
here is the code to get Contacts from Clients Device.
private void initData() {
Cursor cursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,null,null,null);
while(Objects.requireNonNull(cursor).moveToNext()){
String name = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String number = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
// Finds the contact in our database through the Firebase Query to know whether that contact is using our app or not.
findUsers(number);
}
}
While Getting Each Contact one by one from clients device, simultaneously we will trigger the firebase query to check whether that contact is using our app or not.
So we are using "findUser" Method to check whether that contact is using our app or not.
private void findUsers(final String number){
Query query = FirebaseDatabase.getInstance().getReference()
.child("User")
.orderByChild("phone")
.equalTo(number);
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
if (snapshot.getValue() != null){
Map<String, Object> map = (Map<String, Object>) snapshot.getValue();
// this will print whole map of contacts who is using our app from clients contacts.
Log.d("ContactSync", snapshot.getValue().toString());
// so you can use any value from map to add it in your Recycler View.
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
Log.d("ContactSync", error.getMessage());
}
});
}
Here is how my database structure looks like.
Thanks for reading this answer,
I hope this will be helpful!
Currently I'm using Parse.com in order to create multiple ParseUsers. This works perfectly and each user can login individually. However from here I want to expand my app to allow Users to create groups of users and therefore have data that is only relevant and shared between these Users. This will mean that when the User logs in, they can see a List of the groups they are members of and from there can share data simply just to those users of that individual group. What would be the best way to tackle this and does anybody have any examples or tutorials that I could follow in order to understand this concept?
I've considered creating a Group class and then making this store User's IDs in an array and then allow each User to store an array of the Group IDs that they're currently members of. I'm just not really sure how to broach this issue.
Thanks in advance!
I ended up doing as shown below:
ParseQuery<ParseRole> query = ParseRole.getQuery();
Intent intent = getActivity().getIntent();
String groupId = intent.getStringExtra("groupId");
query.whereEqualTo("objectId", groupId);
groupUsers = new ArrayList<String>();
query.findInBackground(new FindCallback<ParseRole>() {
#Override
public void done(List<ParseRole> objects, ParseException e) {
if(e == null) {
for(ParseRole role : objects) {
ParseRelation<ParseUser> usersRelation = role.getRelation("users");
ParseQuery<ParseUser> usersQuery = usersRelation.getQuery();
usersQuery.findInBackground(new FindCallback<ParseUser>() {
#Override
public void done(List<ParseUser> objects, ParseException e) {
for(ParseUser user : objects) {
groupUsers.add(user.getUsername());
}
}
});
}
} else {
Toast.makeText(getActivity(), "ERROR", Toast.LENGTH_SHORT).show();
}
}
});
I passed in the group ID from the Intent that sent me to that Fragment that I was checking and then populated my ListView with the list that I've returned from the query on the Parse database with the specific group ID. I hope this helps anyone else who had the same issue as me. Good luck!
Since you probably want to use it for security as well as making it easier for code/users, look at the Roles security feature.
You can add/remove Users from Roles, and assign ACL permissions to Roles instead of Users. This way when people are added-to/removed-from the Role the permissions don't require any changes.
Initially there was a limit to the number of Roles you were allowed to create based on account type, but this restriction was removed last year I believe.