-
Notifications
You must be signed in to change notification settings - Fork 17
Users and installations
Mobile Messaging SDK employs specific terms in order to address different type of information that you can synchronize towards Infobip Platform. You will see User
and Installation
terms in the SDK similarly to what you can see at People section at Infobip Portal.
-
Installation
is a specific installation of your application. Each application installation on a device receives unique installation ID -pushRegistrationId
.pushRegistrationId
is a permanent ID assigned to the app once it’s launched up until the moment it’s uninstalled from the device. In this documentation, the terms 'installation' and 'push registration' are used interchangeably and denote the same concept. You can see it asMobile App Messaging (Push Notifications)
destination underContact Information
tab of a user profile. A single user can have zero or more installations of different applications. You can change some specific settings of each installation of a user, addCustom attributes
to it or do a remoteLogout
of a specific installation. -
User
represents a single person profile withStandard attributes
,Custom attributes
andTags
which you can set via the SDK.
Both user and installation objects are initialized once Mobile Messaging SDK is successfully started.
Installation
is a specific installation (or instance) of your application on a user's device. Standard attributes and their descriptions are available in docs, code - Installation. One user can have multiple installations.
You can get current installation details from server:
MobileMessaging.getInstance(context).fetchInstallation(object : ResultListener<Installation>() {
override fun onResult(result: Result<Installation, MobileMessagingError>) {
}
})
expand to see Java code
MobileMessaging.getInstance(context).fetchInstallation(new ResultListener<Installation>() {
@Override
public void onResult(Result<Installation, MobileMessagingError> result) {
}
});
All the current users installations are also available under user profile:
val user: User = ...
val installations: List<Installation> = user.getInstallations()
expand to see Java code
User user = ...;
List<Installation> installations = user.getInstallations();
Infobip creates an empty user profile as soon as device registers on the platform. Afterwards you should be able to find this user profile at Infobip Portal using for example pushRegistrationId
(or other attributes, such as phone number, in case the installation was personalized) provided via the SDK:
You can temporarily "disable" your installation if you don't want to receive push notifications:
val installation = Installation()
installation.isPushRegistrationEnabled = false
MobileMessaging.getInstance(context).saveInstallation(installation, object : ResultListener<Installation>() {
override fun onResult(result: Result<Installation, MobileMessagingError>) {
}
})
expand to see Java code
Installation installation = new Installation();
installation.setPushRegistrationEnabled(false);
MobileMessaging.getInstance(context).saveInstallation(installation, new ResultListener<Installation>() {
@Override
public void onResult(Result<Installation, MobileMessagingError> result) {
}
});
On the Infobip account, a single user profile can have one or more mobile devices with the application installed. You might want to mark one of these devices as the primary device and send push messages only to this device (e.g. receive bank authorization codes only on one device). To achieve this and similar use-cases, you can utilize the APIs provided by the Mobile Messaging SDK.
For this feature to work, the API request for sending the push notification must include a special parameter targetOnlyPrimaryDevices
set to true
. Parameters for sending a single push notification can be checked in the Infobip API Docs. With this parameter, push notifications will not be sent to any installations that are not marked as primary. This means that for this feature to work, both the mobile implementation and the API request parameter must be used in conjunction.
By default, all installations are marked as non-primary. To set a particular installation as primary, either the Contact Information API or the following Mobile Messaging SDK API can be used:
val installation = Installation()
installation.isPrimaryDevice = true
MobileMessaging.getInstance(context).saveInstallation(installation, object: ResultListener<Installation>() {
override fun onResult(result: Result<Installation, MobileMessagingError>) {
}
})
expand to see Java code
Installation installation = new Installation();
installation.setPrimaryDevice(true);
MobileMessaging.getInstance(context).saveInstallation(installation, new ResultListener<Installation>() {
@Override
public void onResult(Result<Installation, MobileMessagingError> result) {
}
});
You can set/reset primary setting for any other installation of a current user:
val pushRegId: String = < Push Registration ID of another installation >
MobileMessaging.getInstance(context).setInstallationAsPrimary(pushRegId, true, object: ResultListener<List<Installation>>() {
override fun onResult(result: Result<List<Installation>, MobileMessagingError>) {
}
})
expand to see Java code
String pushRegId = < Push Registration ID of another installation >;
MobileMessaging.getInstance(context).setInstallationAsPrimary(pushRegId, true, new ResultListener<List<Installation>>() {
@Override
public void onResult(Result<List<Installation>, MobileMessagingError> result) {
}
});
An Installation
can have custom attributes in the same way as User
does, so that you would be able to reach only a specific installation of a user.
val installation = Installation()
installation.setCustomAttribute("OneTimePasswords", CustomAttributeValue(true))
MobileMessaging.getInstance(context).saveInstallation(installation, object: ResultListener<Installation>() {
override fun onResult(result: Result<Installation, MobileMessagingError>) {
}
})
expand to see Java code
Installation installation = new Installation();
installation.setCustomAttribute("OneTimePasswords", new CustomAttributeValue(true));
MobileMessaging.getInstance(context).saveInstallation(installation, new ResultListener<Installation>() {
@Override
public void onResult(Result<Installation, MobileMessagingError> result) {
}
});
These custom attributes can be seen under push destination card on a portal:
You can provide additional user's data to the server, so that you will be able to send personalised targeted messages to exact user and have other nice features. Library supports a set of predefined attributes as well as custom ones.
You can always get current user data from server via the SDK API. The request produce an HTTP call, so make sure to handle failures if any.
MobileMessaging.getInstance(context).fetchUser(object: ResultListener<User>() {
override fun onResult(result: Result<User, MobileMessagingError>) {
}
})
expand to see Java code
MobileMessaging.getInstance(context).fetchUser(new MobileMessaging.ResultListener<User>() {
@Override
public void onResult(Result<User, MobileMessagingError> result) {
}
});
There are two types of user profiles: Lead
and Customer
:
Leads are profiles with the person`s name and contact information that has not been verified.
Leads are changed to Customers during personalization using the provided identifiers. If profile is already a Customer
, profile is updated with the information about the installation.
val type = user.type //LEAD or CUSTOMER
expand to see Java code
User.Type type = user.getType(); //LEAD or CUSTOMER
Each user can have External user ID
, Emails
and Phone numbers
. These fields are unique identifiers of a user profile on Infobip platform and provide capability to personalize any app installation with a user profile. The platform provides data grouping functions based on these parameters. For example, if two installations of a particular app will try to save the same External user ID
, then both of them will be collected under a single user. Phone number
, Email
and External user ID
are also widely used when targeting users with messages across different channels via Infobip platform.
Following restrictions apply:
- External User Id: any string, except any form of "null", "Null", "NULL" etc are not supported and would be considered as JSON
null
- Phone number: string, https://en.wikipedia.org/wiki/E.164, i.e.
"38516419710"
) - Email: string, format described in https://tools.ietf.org/html/rfc2822, i.e.
"[email protected]"
)
It is also possible to set User attributes on personalization using UserAttributes. It will override any existing values, so use carefully.
val userIdentity = UserIdentity()
userIdentity.externalUserId = "ExternalId"
// OR
// userIdentity.phones = HashSet(listOf("38516419710"))
// userIdentity.emails = HashSet(listOf("[email protected]"))
val userAttributes = UserAttributes()
//replaces existing values set to the person with provided ones
userAttributes.firstName = "John"
userAttributes.lastName = "Doe"
userAttributes.gender = UserAttributes.Gender.Male
userAttributes.birthday = SimpleDateFormat("yyyy-MM-dd").parse("1968-02-10")
MobileMessaging.getInstance(context).personalize(userIdentity, userAttributes, object:ResultListener<User>() {
override fun onResult(result:Result<User, MobileMessagingError>) {
}
})
expand to see Java code
UserIdentity userIdentity = new UserIdentity();
userIdentity.setExternalUserId("ExternalId");
// OR
// userIdentity.setPhones(new HashSet<>(Arrays.asList("38516419710"));
// userIdentity.setEmails(new HashSet<>(Arrays.asList("[email protected]"));
UserAttributes userAttributes = new UserAttributes();
//replaces existing values set to the person with provided ones
userAttributes.setFirstName("John");
userAttributes.setLastName("Doe");
userAttributes.setGender(User.Gender.Male);
userAttributes.setBirthday(new SimpleDateFormat("yyyy-MM-dd").parse("1968-02-10"));
MobileMessaging.getInstance(context).personalize(userIdentity, userAttributes, new ResultListener<User>() {
@Override
public void onResult(Result<User, MobileMessagingError> result) {
}
});
You can use External User ID to uniquely target your user. External User ID is meant to be an ID of a user in an external (non-Infobip) service. It can be any string and can be shared across different instances of your app, so that a user with multiple devices can still be targeted as a single user of your app. Notice: for externalUserId
any string values such as "null", "Null" or "NULL" are not supported and would be considered as JSON null
You can depersonalize
current installation to detach it from current user profile so that the user won't receive messages when targeted by any person attribute:
MobileMessaging.getInstance(context).depersonalize(object: ResultListener<SuccessPending>() {
override fun onResult(result: Result<SuccessPending, MobileMessagingError>) {
}
})
expand to see Java code
MobileMessaging.getInstance(context).depersonalize(new ResultListener<SuccessPending>() {
@Override
public void onResult(Result<SuccessPending, MobileMessagingError> result) {
}
});
You also can depersonalize any installation that is personalized with the current user (perform remote logout):
val pushRegId: String = < push reg id of another installation of user >
MobileMessaging.getInstance(context).depersonalizeInstallation(pushRegId, object: ResultListener<List<Installation>>() {
override fun onResult(result: Result<List<Installation>, MobileMessagingError>) {
}
})
expand to see Java code
String pushRegId = < push reg id of another installation of user >;
MobileMessaging.getInstance(context).depersonalizeInstallation(pushRegId, new ResultListener<List<Installation>>() {
@Override
public void onResult(Result<List<Installation>, MobileMessagingError> result) {
}
});
Q: When should I log out my users? A: Application users can (and probably should) be logged out if the app meets all the following conditions:
- you leverage user attributes functionality
- your application has "log out"/"sign out" feature
- you don't want a newly logged in (signed up) user to be targeted by other user's data (such as phone numbers, first name, custom attributes etc.) and receive personalized messages
- you want logged out (signed out) user to still receive broadcast notifications (if not, you need to disable push registration)
If you want previous personalization to be reset, in other words, depersonalize this particular installation, provide a special argument forceDepersonalize
:
val userIdentity = UserIdentity()
userIdentity.externalUserId = "ExternalId"
MobileMessaging.getInstance(context).personalize(userIdentity, null, true, object:ResultListener<User>() {
override fun onResult(result:Result<User, MobileMessagingError>) {
}
})
expand to see Java code
UserIdentity userIdentity = new UserIdentity();
userIdentity.setExternalUserId("ExternalId");
MobileMessaging.getInstance(context).personalize(userIdentity, null, true, new ResultListener<User>() {
@Override
public void onResult(Result<User, MobileMessagingError> result) {
}
});
If you want to do a personalization without promoting profile to Customer
you can set keepAsLead
parameter to true
.
MobileMessaging.getInstance(context).personalize(userIdentity = userIdentity, userAttributes = null, forceDepersonalize = false, keepAsLead = true)
expand to see Java code
MobileMessaging.getInstance(context).personalize(userIdentity, null, false, true);
You can set different standard attributes of a user, such as First name
, Last name
, Birthday
etc.:
val user = User()
user.firstName = "John"
user.lastName = "Doe"
user.gender = UserAttributes.Gender.Male
user.birthday = SimpleDateFormat("yyyy-MM-dd").parse("1968-02-10")
MobileMessaging.getInstance(context).saveUser(user, object: ResultListener<User>() {
override fun onResult(result: Result<User, MobileMessagingError>) {
}
})
expand to see Java code
User user = new User();
user.setFirstName("John");
user.setLastName("Doe");
user.setGender(User.Gender.Male);
user.setBirthday(new SimpleDateFormat("yyyy-MM-dd").parse("1968-02-10"));
MobileMessaging.getInstance(context).saveUser(user, new MobileMessaging.ResultListener<User>() {
@Override
public void onResult(Result<User, MobileMessagingError> result) {
}
});
Please note that saveUser()
may return a USER_MERGE_INTERRUPTED
error if you have provided an already existing Phone number, Email, or External User Id that are already taken by another existing user profile. In other words, that particular phone/email/externalUserId is a unique identifier of an already existing user, different from the one that this installation is currently personalized with. You can find more details about this, and other possible errors at Server errors. If you wish to personalize the app installation with another existing user, that is, merge current user with another one, please use our Personalize API or SDK method.
For editing any attributes of the existing user, perform fetchUser
first to get server data. Setting values to null (and saving user afterwards) will remove them from the user.
Apart from a list of standard attributes, each User
can have a set of custom ones. These are commonly used to cover any use-cases about targeting and segmentation, which are not covered by the platform out of the box. Custom attributes are key-value pairs. Keys are of string
type, values can be of string
, number
, boolean
, date
, datetime
or list of objects
data type.
Difference between date
and datetime
types is that usage of date
doesn't sync time to the server (e.g. "2020-11-30"), but with datetime
we provide timestamp as well that can be visible on web.
You can easily update custom attributes of a user with the same api:
val user = User()
user.setCustomAttribute("favouriteMeal", CustomAttributeValue("pizza"))
user.setCustomAttribute("bootSize", CustomAttributeValue(9))
user.setCustomAttribute("isSubscribed", CustomAttributeValue(true))
user.setCustomAttribute("installationDate", CustomAttributeValue(Date()))
user.setCustomAttribute("lastVisitDateTime", CustomAttributeValue(CustomAttributeValue.DateTime(Date())))
user.removeCustomAttribute("height") // this way data will be erased on server
// add list of objects as a custom attribute
val favsList: ArrayList<ListCustomAttributeItem> = ArrayList()
val listCustomAttributeItem1 = ListCustomAttributeItem.builder()
.putString("id", "1")
.putNumber("price", 99.99)
.putBoolean("sale", true)
.build()
val listCustomAttributeItem2 = ListCustomAttributeItem.builder()
.putString("id", "2")
.putNumber("price", 149.99)
.putBoolean("sale", false)
.build()
favsList.add(listCustomAttributeItem1)
favsList.add(listCustomAttributeItem2)
user.setListCustomAttribute("favsList", ListCustomAttributeValue(favsList))
// save data to server
MobileMessaging.getInstance(context).saveUser(user, object : ResultListener<User>() {
override fun onResult(result: Result<User, MobileMessagingError>) {
}
})
expand to see Java code
User user = new User();
user.setCustomAttribute("favouriteMeal", new CustomAttributeValue("pizza"));
user.setCustomAttribute("bootSize", new CustomAttributeValue(9));
user.setCustomAttribute("isSubscribed", new CustomAttributeValue(true));
user.setCustomAttribute("installationDate", new CustomAttributeValue(new Date()));
user.setCustomAttribute("lastVisitDateTime", new CustomAttributeValue(new CustomAttributeValue.DateTime(new Date())));
user.removeCustomAttribute("height"); // this way data will be erased on server
// add list of objects as a custom attribute
ArrayList<ListCustomAttributeItem> favsList = new ArrayList<>();
ListCustomAttributeItem listCustomAttributeItem1 = ListCustomAttributeItem.builder()
.putString("id", "1")
.putNumber("price", 99.99)
.putBoolean("sale", true)
.build();
ListCustomAttributeItem listCustomAttributeItem2 = ListCustomAttributeItem.builder()
.putString("id", "2")
.putNumber("price", 149.99)
.putBoolean("sale", false)
.build();
favsList.add(listCustomAttributeItem1);
favsList.add(listCustomAttributeItem2);
user.setListCustomAttribute("favsList", new ListCustomAttributeValue(favsList));
// save data to server
MobileMessaging.getInstance(context).saveUser(user, new MobileMessaging.ResultListener<User>() {
@Override
public void onResult(Result<User, MobileMessagingError> result) {
}
});
And you can get current values of the custom attributes as well:
val user = MobileMessaging.getInstance(context).user
val favoriteMeal = user!!.getCustomAttributeValue("favoriteMeal").stringValue()
val bootSize: Int = user.getCustomAttributeValue("bootSize").numberValue().toInt()
val isSubscribed = user.getCustomAttributeValue("isSubscribed").booleanValue()
val installationDate = user.getCustomAttributeValue("installationDate").dateValue()
val lastVisitDateTime = user.getCustomAttributeValue("lastVisitDateTime").dateTimeValue()
val favsList2 = user.getListCustomAttributeItems("favsList")
expand to see Java code
User user = MobileMessaging.getInstance(context).getUser();
String favoriteMeal = user.getCustomAttributeValue("favoriteMeal").stringValue();
Integer bootSize = user.getCustomAttributeValue("bootSize").numberValue().intValue();
Boolean isSubscribed = user.getCustomAttributeValue("isSubscribed").booleanValue();
Date installationDate = user.getCustomAttributeValue("installationDate").dateValue();
CustomAttributeValue.DateTime lastVisitDateTime = user.getCustomAttributeValue("lastVisitDateTime").dateTimeValue();
List<ListCustomAttributeItem> favsList2 = user.getListCustomAttributeItems("favsList");
With this data, you can segment users by using Segments and target them by their custom attribute values:
Detailed description on what list of objects is, some common use cases and how to set it on web are provided here. Mobile implementation specifics:
- as provided in the upper example of updating custom attributes, list of objects can be set as a custom attribute, but this type is more complex
- list of objects needs to be created on web
- it needs to have the same structure as on web when it's provided from SDK, otherwise error will be returned as an error response
- supported types are:
string
,number
,boolean
,date
anddatetime
You can add or remove Tags
from users based on their preferences or interests. Using Tags
you can easily segment users which are interested in any specific topic and send messages only to such users.
val user = User()
user.tags = HashSet(listOf("Promotions", "Transactions"))
MobileMessaging.getInstance(context).saveUser(user, object: MobileMessaging.ResultListener<User>() {
override fun onResult(result: Result<User, MobileMessagingError>) {
}
})
expand to see Java code
User user = new User();
user.setTags(new HashSet<>(Arrays.asList("Promotions", "Transactions"));
MobileMessaging.getInstance(context).saveUser(user, new MobileMessaging.ResultListener<User>() {
@Override
public void onResult(Result<User, MobileMessagingError> result) {
}
});
Afterwards you will see these tags in a user profile and will be able to segment such users when sending targeted messages or campaigns.
By default, user data is stored on a device, so it can be available even when the device is offline. Also, we store unreported user data, so we can automatically retry sending it to our server. In order to change default behaviour and disable storing user data, do as follows:
MobileMessaging.Builder(application)
.withoutStoringUserData()
.build()
expand to see Java code
new MobileMessaging.Builder(application)
.withoutStoringUserData()
.build();
If you have any questions or suggestions, feel free to send an email to [email protected] or create an issue.
- Library events
- Server errors
- Users and installations
- Messages and notifications management
- Inbox
Geofencing API- DEPRECATED- Android Manifest components
- Privacy settings
- In-app chat
- Infobip RTC calls and UI
- Backup rules