How to get users email address in Openfire / asmack? - android

I am developing a chat app for Android and I want to make a Profile option where I can show the selected friends profile like JID, Name, Email at first. I can get the roosters JID and Name but there is no getter for email... How can i query it ? This is how I got JID and Name:
Collection<RosterEntry> entries = roster.getEntries();
for (RosterEntry entry : entries) {
// Log.d(TAG, "User: " + entry.getUser());
String[] temp = entry.getUser().toString().split("\\#");
String name = entry.getName().toString();
String email = "az#azaz.lol"; // there is no getter at entry.getEmail ??
}
I am just guessing that this is not how get email from rosters...

User email addresses are not maintained in the roster. Rather, they are stored in the 'ofUser' table under the column, email. This information is stored at the time the openfire account is created and is not publicly accessible.

Related

How do you manage your android device token generated by FCM after token expired?

I'm developing a push notification app, do you have same issue:
My app generate a FCM device token and store it in a cloud database, so I can send notification messages to a device via FCM, and my database table looks like:
userid | device_token
Mary | xxxxxxxxxxxxxxxxxxxxxxxxxxxx // token1, from Mary's first device
John | yyyyyyyyyyyyyyyyyyyyyyyyyyyy
Mary | zzzzzzzzzzzzzzzzzzzzzzzzzzzz // token2, from Mary's second device
Mary | kkkkkkkkkkkkkkkkkkkkkkkkkkkk // token, from Mary's first device
.......
After Mary reinstalled this app from her first device, a new device token generated, and it is stored with token3.
How can I remove the expired device token token1, the only information I got may only be a pair of device token and an account name.
So how do you manage your device in this situation?
If "Mary" is using the same account to log in each time in your app, even if it is a new phone or reinstalled app why do you create a new token field inside the database? Why don't you always write inside the same token field so you always have access to this field. This will also send notifications only to the phone that your user is actually using right now. So each time when the user starts the app check token, if not equal write the new one inside your database. And from the server-side take those tokens and send notifications.
Am I missing something?
To do this, I would suggest using FirebaseAuth for the SignIn and SignUp process of your application. Then use generated uid as the field ID for the user inside the Realtime Database. You can get this uid with FirebaseAuth.getInstance().getCurrentUser().getUid(). So your user Mary will always have the same uid no matter what phone she uses. Always find the user inside the database with this uid and overwrite the existing Firebase token. This also means that your "users" will not be a single line field inside the database, but a more complex and better representation of a user. You can use model classes for this like:
public class User {
public long id = 0;
public long account_id = 0;
public String account_name = "";
public String first_name = "";
public String last_name = "";
public String email_address = "";
public String password = "";
public User() {
}
}
It's up to you on how to configure this. But using models is also helping you on posting and retrieving data, like this:
Creating new user:
DatabaseReference mDatabase = FirebaseDatabase.getInstance().getReference();
mDatabase.child("users").child(FirebaseAuth.getInstance().getCurrentUser().getUid()).setValue(user);
Retrieving data from the real-time database:
DatabaseReference database = FirebaseDatabase.getInstance().getReference();
DatabaseReference databaseUsers = database.child("users");
User myUser = null;
Query usersQuery = databaseUsers.orderByChild("username").equalTo(uid); //you can use any value to order as you want, or you don't have to, there is many options for this query
usersQuery.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChanged(#NonNull DataSnapshot snapshot) {
try {
for (DataSnapshot user : snapshot.getChildren()) {
myUser = user.getValue(User.class);
}
} catch (Exception e) {
e.printStackTrace();
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
Inspired by this: Firebase Cloud Messaging - Managing Registration Tokens
When a token generated:
if Mary logged in:
add the device to the "Mary" Device Group.
store the device group id and connect the device group id to "Mary"'s profile in database.
if app server need to send notification to Mary, just send to the Device Group, the benifit is that you don't need to check if the device token is valid or not, Firebase Cloud Messaging discards invalid device tokens.
if no one logged in:
do nothing or just store the device token.

Contacts: how do I know if it's an account that I can transfer the contacts to?

I want to show the user only the accounts to which he can transfer his contacts.
I can get all the accounts from the AccountsManager but
not all the accounts I receive can accept the contacts (such as WhatsApp..)
For getting all the accounts I'm using this code:
Account[] accounts = AccountManager.get(context).getAccounts();
For transfer all the contacts to the account I'm using this code:
ArrayList<ContentProviderOperation> contact = new ArrayList<>();
contact.add(ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI);
.withValue(ContactsContract.RawContacts.ACCOUNT_NAME, accountName);
.withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, accountType);
.build());
contact.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) .withValueBackReference(ContactsContract.RawContacts.Data.RAW_CONTACT_ID, 0)
.withValue(ContactsContract.RawContacts.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, firstName) .withValue(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME, lastName)
.build());
ContentProviderResult[] results = AppContext.get().getContentResolver().applyBatch(ContactsContract.AUTHORITY, contact);
Is there a way to know if this is an account that can accept the contacts and I can filter the list of accounts for the user?
Thanks for the help :)
Accounts that sync contacts must declare a SyncAdapter, with some properties such as if that SyncAdapter is meant to sync contacts or some other data (e.g. emails), and if that SyncAdapter is read-only or supports uploading new content to the server (supportsUploading).
To skip all accounts that don't support contacts at all, or do support contacts but are read-only (like Viber and Whatsapp):
final SyncAdapterType[] syncs = ContentResolver.getSyncAdapterTypes();
for (SyncAdapterType sync : syncs) {
Log.d(TAG, "found SyncAdapter: " + sync.accountType);
if (ContactsContract.AUTHORITY.equals(sync.authority)) {
Log.d(TAG, "found a SyncAdapter that supports contacts: " + sync.accountType);
if (sync.supportsUploading()) {
Log.d(TAG, "found a SyncAdapter that supports contacts and is not read-only: " + sync.accountType);
// we'll now get a list of all accounts under that accountType:
Account[] accounts = AccountManager.get(this).getAccountsByType(sync.accountType);
for (Account account : accounts) {
Log.d(TAG, account.type + " / " + account.name);
}
}
}
}
Feel free to explore the other good stuff in SyncAdapterType like the isUserVisible property that might be helpful as well.
UPDATE
Getting an app name from an account-type is tricky, as not all accounts/sync-adapters are linked to some user-visible app that has a user-friendly name.
However, I believe this can be done by getting the list of AuthenticatorTypes from AccountManager, like this:
AuthenticatorDescription[] ads = AccountManager.get(this).getAuthenticatorTypes();
You'll then need to iterate over the AuthenticatorDescriptions and match their type with the account-type you got from the above code.
When a match is found, you can get the packageName from the
AuthenticatorDescription, and then use this to get the app name:
PackageManager pm = getPackageManager();
String appName = (String) pm.getApplicationLabel(pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA));
This is not guaranteed to work for all apps, as not all will implement an authenticator.

adding user in roster list isn't working

I am creating an simple one to one chat app, I've done with the message send and receive. Now I am trying to show the status of the user to another(contacts) like "online/offline" etc. For that I have to use Presence and Roster.But I don't know where and how to use that, I mean the complete flow of subscription request and accept and after the subscription, the status of the users i.e. Online/Offline etc.
First of all you need to send and accept contact request
From Open-fire you can also do it from back-end
Steps :
First click on Users/Groups >> click on "UserName" >> click on roster >> add roster
Here i attach screen of steps
click on add new item
add roster
edit roster and select subscription both
then after you will get roster list using this code
ArrayList<RosterEntry> rosterLists = new ArrayList<>();
public List<RosterEntry> getFriendsList() throws SmackException.NotLoggedInException, InterruptedException, SmackException.NotConnectedException {
rosterLists = new ArrayList<>();
roster = Roster.getInstanceFor(Config.conn1);//connection object of AbstractXMPPConnection
if (!roster.isLoaded()) {
roster.reloadAndWait();
Log.e("Roster :", "Reload and wait");
}
Collection<RosterEntry> entries = roster.getEntries();
Log.e("Size of Roster :", entries.size() + "");
for (RosterEntry entry : entries) {
rosterLists.add(entry);
Log.d("Buddies", "Here: " + entry.toString());
Log.d("Buddies", "User: " + entry.getUser());//get userinfo
Log.d("Buddies", "User Name:" + entry.getName());//get username
Log.d("Buddies", "User Status: " + entry.getStatus());//get status of user
}
listAdapter = new FriendUserListAdapter(UserListActivity.this, rosterLists);
user_list.setAdapter(listAdapter);
return rosterLists;
}
what is the difference between subscription type both and from???
When any user add bot has his/her contact, then in the end of whole process, subscription status of ofRoster(openfire) table is set to ‘from’. The desired result of this process is ‘both’

Combine FirebaseAuth UserInfo from ProviderData into one comprehensive User

After signing in through Google and logging the data pulled from the FirebaseAuth user, this is how Firebase has you draw a user's account information:
To get the profile information retrieved from the sign-in providers linked to a user, use the getProviderData method.
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
if (user != null) {
for (UserInfo profile : user.getProviderData()) {
// Id of the provider (ex: google.com)
String providerId = profile.getProviderId();
// UID specific to the provider
String uid = profile.getUid();
// Name, email address, and profile photo Url
String name = profile.getDisplayName();
String email = profile.getEmail();
Uri photoUrl = profile.getPhotoUrl();
};
}
When I log the information pulled from each profile I get the following couple incomplete data sets:
06-08 12:48:12.851 14400-14400/com.example.app D/MainActivity: providerId: firebase, uid: 1***************2, name: null, email: d**********y#gmail.com, url: null
06-08 12:48:12.851 14400-14400/com.example.app D/MainActivity: providerId: google.com, uid: 1************5, name: D*******y, email: null, url: https://lh4.googleusercontent.com/.../photo.jpg
Is there a standard means of combining user information and storing it as a more accessible data set? FirebaseAuth (at least in this example) doesn't seem to be the most clean-cut way to retrieve user information at runtime.
There is no other way to get providerData for a currentUser. I assume you prefer to lookup data by some key such as providerId instead of traversing that list. You can always duplicate this data in realtime database using structure that you prefer such as a key/value map.

Getting "$XMPPErrorException: XMPPError: forbidden - auth" error while creating MultiUserChat

I've created a login connection succesfully for XMPP with Smack Api(4.1.4). Now i'm trying to create MultiUserChat using,
try {
String myMUCName = "TestGroup";
String myMUCService = "conference.(my local ip)";
String myMUCfullName = myMUCName + "#" + myMUCService;
String userName = "Test5";
MultiUserChatManager manager = MultiUserChatManager.getInstanceFor(connection);
MultiUserChat muc = manager.getMultiUserChat(myMUCfullName);
muc.create(userName);
Log.d(LOCAL_TAG, "createGroupChat -- Group CEATED Successfully ");
Form form = muc.getConfigurationForm();
Form submitForm = form.createAnswerForm();
List<FormField> fields = form.getFields();
Log.d(LOCAL_TAG, "createGroupChat -- fields.size(): "+fields.size());
for (int i = 0; i < fields.size(); i++) {
FormField field = (FormField) fields.get(i);
if (!FormField.Type.hidden.equals(field.getType()) && field.getVariable() != null) {
submitForm.setDefaultAnswer(field.getVariable());
}
}
List owners = new ArrayList();
owners.add(userName); //Own user
owners.add("Test7"); //Another user
submitForm.setAnswer("muc#roomconfig_roomowners", owners);
submitForm.setAnswer("muc#roomconfig_publicroom", true);
submitForm.setAnswer("muc#roomconfig_persistentroom", true);
muc.sendConfigurationForm(new Form(DataForm.Type.submit));
//muc.sendConfigurationForm(submitForm);
Log.d(LOCAL_TAG, "createGroupChat -- Sent Configuration");
muc.join(TestGroup);
Log.d(LOCAL_TAG, "createGroupChat -- Group Joined Successfully -- owners.size(): "+owners.size());
But while creating the group i'm getting an exception as
"org.jivesoftware.smack.XMPPException$XMPPErrorException: XMPPError: forbidden - auth".
Hope so, this exception occurs at the code
muc.sendConfigurationForm(submitForm);
which is commented in this for that reason. Because i didn't get the log after that code. To fix that, I have changed that code to
muc.sendConfigurationForm(new Form(DataForm.Type.submit));
which fixes that exception and created me a group, because i could see the log as printed and can see my group in the open fire. But i do know how my selected users for the group gets added, by doing like this, since owners list(or submit form) is not included in this at anywhere. I don't know what's happening in this and I'm not sure that i'm doing right. Plz suggest me to how to proceed. Thanks in advance.
Try this code:
Form form = muc.getConfigurationForm().createAnswerForm();
// Create a new form to submit based on the original form
form.setAnswer("muc#roomconfig_passwordprotectedroom", false);
form.setAnswer("muc#roomconfig_roomname",myMUCName);
form.setAnswer("muc#roomconfig_persistentroom", true);
form.setAnswer("muc#roomconfig_changesubject", true);
form.setAnswer("muc#roomconfig_publicroom",true);
form.setAnswer("muc#roomconfig_allowinvites",true);
form.setAnswer("muc#roomconfig_membersonly",false);
form.setAnswer("muc#roomconfig_moderatedroom",false);
// Sets the new owner of the room
List<String> owners = new ArrayList<String>();
//Be carefull: if members does not exists, it brokes!
owners.add(userName +"#"+"(my local ip or server name placeholder)");
form.setAnswer("muc#roomconfig_roomowners", owners);
// Send the completed form
muc.sendConfigurationForm(form);
System.out.println("MUC is now registered");
muc.join(userName );
Right now, if all it's ok, you'll join the Room as userName and userName will be also the owner.
You'll can check Owners of a MUC programmatically by
muc.getOwners() //List<Affiliate>, for each Affialiate you'll have to affiliate.getJid().toString()
You can invite people by this line of code:
muc.invite(user, "Invite");
And then, if you want to see them "forever",
muc.grantMembership(user);
so you'll be able to see membership with
muc.getMembers();
Please pay attention:
Affiliate: user with a defined role (Onwer, Admin, Member, Outcast) in a MUC
Occupants: user ONLINE in a MUC
Not all Occupants can have a role, not all Affiliates are automatically be occupants.
More, you can't be sure an Affiliate ever joined the groupchat.
Flux it's something like:
Muc Creation by User1
(optional) Muc Invitation by User1 to any user he desire (example: User2, User4)
(optional) Muc Affiliate assignation by User1 to any existant user he desire (example: User3, User4)
User2 and User4 will recive, when online, a invitation to accept/reject
User3 and User4 will not recive nothing, but they will have a role in the MUC.
User2, User3, User4 need to register IQProviders to get IQ Stanzas and then listners for each MUC to recive Invitations, another to recive Messages (and or other events).
For SMACK 4.3.4 and above.
multiUserChatManager = MultiUserChatManager.getInstanceFor(connection);
multiUserChat = multiUserChatManager.getMultiUserChat(JidCreate.entityBareFrom(roomJID));
multiUserChat.create(Resourcepart.from(nickname));
Form form = multiUserChat.getConfigurationForm();
Form submitForm = form.createAnswerForm(); submitForm.getField("muc#roomconfig_publicroom").addValue("1");
submitForm.getField("muc#roomconfig_enablelogging").addValue("1");
submitForm.getField("x-muc#roomconfig_reservednick").addValue("0");
submitForm.getField("x-muc#roomconfig_canchangenick").addValue("0");
submitForm.getField("x-muc#roomconfig_registration").addValue("0");
submitForm.getField("muc#roomconfig_passwordprotectedroom").addValue("0");
submitForm.getField("muc#roomconfig_roomname").addValue(roomName);
submitForm.getField("muc#roomconfig_whois").addValue("participants");
submitForm.getField("muc#roomconfig_membersonly").addValue("1");
submitForm.getField("muc#roomconfig_persistentroom").addValue("1");
multiUserChat.sendConfigurationForm(submitForm);
This is how you can send the room configuration from and create room (MUC).

Categories

Resources