Anda di halaman 1dari 117

M800SDK User Manual for Android

M800 SDK Android User Guide


v. 141

Contents
M800 SDK Android User Guide v. 141
Contents
Introduction
Glossary
How to Import the M800SDK
How to Configure the M800SDK
Step-by-step guide:
Sign-up Module
Introduction
Pre-requisites
How to implement sign-up
Sign up as a White Label User
Sign up as a SDK user
After a successful sign up
Connection Module
Introduction
Pre-requisites
How to implement
More on Connection Management
Contact Sync Module
Introduction
Pre-requisites
How to implement
Get M800 contact list
Get M800 native contact list
Start contact sync manually
Sync roster
Add M800 contact
Remove M800 contact
Register roster event listener
Find M800 contact by phone number.
Find M800 contact by JID
Presence (Last Seen)
Call Module
Introduction
How to implement
Making an outgoing on-net call (VOIP VOIP call)
To make an outgoing off-net call (VOIP PSTN call)
Receiving an incoming call
IM Push Notification
Remote Notification
To reject a call silently from an incoming call notification bundle
To handle a missed call notification
How to Configure M800ClientConfiguration
Steps to provide a comprehensive call experience
Support the mute and speaker feature
Play a sound locally to notify user the call is connected
Play a sound locally to notify user he/she has sent a DTMF (dual tone multi frequency) tone over the call
Dim screen when users face is close to the screen.
Work closely with network status.
Work closely with native phone status.
Responsive UI to the in-call events
Incoming call notifications.
Missed call notifications.
Call history management.
Use Third Party Push Service
IM Module
Introduction
Pre-requisites
How to Implement
Single User Chat Room(SUC)
Single User Chat Room(SUC) Creation
Monitor Single User Chat Room(SUC) Activity
Retrieve Single User Chat Room(SUC)
Single User Chat Room(SUC) Deletion
Retrieve Participants In Single User Chat Room(SUC)
Multi User Chat Room(MUC)

Multi User Chat Room(MUC) Creation


Monitor Multi User Chat Room(MUC) Activity
Retrieve Multi User Chat Room(MUC)
Retrieve Participants In Multi User Chat Room(MUC)
Multi User Chat Room(MUC) Synchronization
Multi User Chat Room(MUC) Participants Management
Leave Multi User Chat Room(MUC)
Multi User Chat Room(MUC) Property Management
System Chat Room
Monitor System Chat Room Activity
Retrieve System Chat Room
SMS Chat Room
Create SMS Chat Room
Monitor SMS Chat Room Activity
Retrieve SMS Chat Room
Delete SMS Chat Room
Retrieve Chat Participants in SMS Chat Room
Messaging
Introduction
Send text message
Send SMS message
Send audio message
Send image message
Send video message
Send ephemeral message
Register message listener
Set media file upload progress listener
Get historical chat messages and statistics
Retrieve message data
Manage ephemeral message
Remove chat messages
Forward chat message
Read chat message
Send chat state
Monitor chat state changes
Credit Module
Introduction to Credit Module
Pre-requisites
How to Implement
Contact Management
Introduction
How to implement
Add Contact
Remove contact
Add or Remove Contact Callback
Rate Table Module
Introduction
Pre-requisites
How to implement
To retrieve an instance of the RateManager:
To listen for change event in the Rate Table:
To update the RateManagers data from server:
To check if the RateManagers data is up-to-date:
To retrieves rates:
Find User Module
Introduction
How to Implement
Find user by phone number/JID
Find User by PIN
Find User by Recommendation
Find User by Location
Report and Block User
User Profile Module
Introduction
How to Implement
Retrieve current user profile
Retrieve Name
Retrieve Status
Retrieve Gender
Retrieve Birthday
Retrieve Email Address
Retrieve Profile Image

Retrieve Cover Image


Retrieve Caller Video
Update current user profile
Update Name
Update Status
Update Gender
Update Birthday
Update Email Address
Update Profile Image
Update Cover Image
Update Caller Video
Delete Profile Image
Delete Cover Image
Delete Caller Video
User Preference
Introduction
How to Implement
Retrieve / Modify User Preference
Language
Recommendation
Find users by Pin/Phone
Find users by location
My video caller ID visibility
Other's video caller ID visibility
Presence
Displayed Receipt
Message notifications
Monitor User Preference Update Activity
User Preference Synchronization

Introduction
The M800 SDK is a Java library for Android which enables developers to leverage M800's global voice and messaging platform.
The M800 SDK allows the developer to easily add voice and messaging functionality to an Android app, so that app users can make phone calls,
chat, retrieve contact lists, find users, and more.
This guide demonstrates the key APIs of the SDK. Previous development experience with Java and the Android platform is assumed.

Glossary
JID

A unique identifier for end users. JID stands for Jabber Identifier. For
example: +106565_demo01@demo.m800-api.com.

On-net call

This is a call using a data connection between two M800 apps.


On-net calls are peer-to-peer calls to/from other SDK-based clients.

Off-net call

This is a call from M800 to a number on another network. Off-net


calls are calls to landline or mobile numbers.

PSTN

The public switched telephone network, i.e. the regular telephone


network.

How to Import the M800SDK


Place the M800SDK.aar file and M800PhoneVerification.aar/M800PhoneVerification_testbed.aar files in your project directory.
Add following dependencies for M800SDK in your projects gradle file:

// M800 SDK dependencies


compile 'com.google.guava:guava:18.0'
compile 'com.google.code.gson:gson:2.3.1'
compile 'com.google.code.findbugs:jsr305:2.0.3'
compile 'com.google.android.gms:play-services:7.0.0'
compile 'com.googlecode.libphonenumber:libphonenumber:7.0.4'
compile 'com.infstory:proguard-annotations:1.0.1'
compile 'com.fasterxml.jackson.core:jackson-core:2.4.1'
compile 'com.fasterxml.jackson.core:jackson-annotations:2.4.1'
compile 'com.fasterxml.jackson.core:jackson-databind:2.4.1'
// M800 SDK
compile (name: 'M800SDK', ext: 'aar') { transitive = true }

Add following dependencies for Phone Verification in your projects gradle file:

Production environment:

//M800 Phone Verification SDK


compile (name: 'M800PhoneVerification', ext: 'aar')

Testbed environment:

//M800 Phone Verification SDK


compile(name: 'M800PhoneVerification_testbed', ext: 'aar')

Note that the size of M800SDK library is large. If the total method count of the application reaches 64k, you will need enable in the your projects
gradle file:
Add following dependencies for M800SDK in your projects gradle file:

// Multidex library
compile com.android.support:multidex:1.0.1'

Add the configuration also to enable multiDexEnabled

android {
compileSdkVersion 21
buildToolsVersion "22.0.1"
defaultConfig {
minSdkVersion 16
targetSdkVersion 21
versionCode 1
versionName "1.0"
multiDexEnabled true
}
}

Add the following meta-data in your projects AndroidManifest.xml file:


Production environment:

<!--This meta-data is invalid if users are signed up as SDK users.-->


<meta-data
android:name="com.m800.signup.user"
android:value="whitelabel"
tools:replace="android:value" />

Testbed environment:

<meta-data
android:name="com.m800.signup.server"
android:value="testbed"
tools:replace="android:value"/>

<!--This meta-data is invalid if users are signed up as SDK users.-->


<meta-data
android:name="com.m800.signup.user"
android:value="whitelabel"
tools:replace="android:value" />

Include the following files if you have ProGuard enabled in your project:

proguardFile 'M800SDK-proguard-rules.pro'
proguardFile 'annotations.pro'

How to Configure the M800SDK


To connect your app to M800, you need to generate a capabilities signature or capsig to set your authorization levels on our network. To generate
the capsig, use your application secret which was provided when you sign up and specify the capabilities and expiry.
To initialize services, you should also add the following keys in your AndroidManifest.xml
1. Developer Key (supplied by M800)
2. Application Key (supplied by M800)
3. Application Identifier (supplied by M800)
4. Application Version: 1.0.0 (default value)
5. Capabilities: incoming, outgoing (default value)
6. Expiry (in seconds)
7. Carrier Name (supplied by M800)
8. Application Secret (supplied by M800)
9. Developer Secret (supplied by M800)

Then implement these with M800SDKConfiguration as follows:

// Configure M800SDK
M800SDKConfiguration configuration = M800SDK.newConfiguration();
PreferenceUtil.fillInConfigurationWithPreference(configuration, this);
configuration.setCertificateFileForCall(mM800CertificateFile);
configuration.setCertificateFileForIM(mM800CertificateFile);
M800SDK.setConfiguration(configuration);

Step-by-step guide:
When using AndroidManifest.xml, copy the meta-data codes below into your AndroidManifest.xml.
Place your code values in the appropriate space; values represented here would of course be supplied by M800:

<meta-data
android:name="com.m800.application.key"
android:value="Your Application Key" />
<meta-data
android:name="com.m800.application.secret"
android:value="Your Application Secret" />
<meta-data
android:name="com.m800.application.identifier"
android:value="Your Application Identifier" />
<meta-data
android:name="com.m800.application.version"
android:value="1.0.0"/>
<meta-data
android:name="com.m800.carrier.name"
android:value="Your Carrier Identifier" />
<meta-data
android:name="com.m800.developer.key"
android:value="Your Developer Key" />
<meta-data
android:name="com.m800.developer.secret"
android:value="Your Developer Secret" />
<meta-data
android:name="com.m800.capabilities"
android:value="incoming,outgoing"/>
<meta-data
android:name="com.m800.expiration"
android:value="100000"/>

Prepare the M800Certificate File (mM800CertificateFile). In the demo app project, the source certificate file is named as cacert.crt and
placed in the /asset.
To see the full implementation, you should go to the ApplicationClass.java and look into the method :

private void copyCertificateFromAsset() {


String filename = "cacert.crt";
mM800CertificateFile = copyFileFromAsset(filename);
if (mM800CertificateFile != null) {
Log.d(TAG, "Certificate for IM:" + mM800CertificateFile.getAbsolutePath());
}
}

Get a new M800SDKConfiguration object from M800SDK.newConfiguration().

M800SDKConfiguration configuration = M800SDK.newConfiguration();

Fill the keys, mentioned in Step 1, into the M800SDKConfiguration object. In the demo project, we used a helper class, PreferenceUtil, to
fill the keys. You may go to this class to reference the full implementation.

PreferenceUtil.fillInConfigurationWithPreference(configuration, this);

Provide the M800Certificate File from Step 2 to the M800SDKConfiguration object by

configuration.setCertificateFileForCall(mM800CertificateFile);
configuration.setCertificateFileForIM(mM800CertificateFile);

Finally, set the M800SDKConfiguration object for M800SDK.

M800SDK.setConfiguration(configuration);

Note. You will need to set all of the following permissions in your manifest.xml file:

<uses-permission
<uses-permission
<uses-permission
<uses-permission
<uses-permission
<uses-permission
<uses-permission
<uses-permission
<uses-permission
<uses-permission
<uses-permission
<uses-permission
<uses-permission

android:name="android.permission.ACCESS_WIFI_STATE" />
android:name="android.permission.ACCESS_NETWORK_STATE" />
android:name="android.permission.READ_PHONE_STATE" />
android:name="android.permission.INTERNET" />
android:name="android.permission.RECORD_AUDIO" />
android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
android:name="android.permission.GET_TASKS" />
android:name="android.permission.WAKE_LOCK" />
android:name="android.permission.BROADCAST_STICKY" />
android:name="android.permission.CHANGE_NETWORK_STATE" />
android:name="android.permission.CHANGE_WIFI_STATE" />
android:name="android.permission.READ_CONTACTS" />

You will need additional permissions for M800PhoneVerification SDK. Please refer to the corresponding user manual.

Sign-up Module
Introduction
The sign-up Module lets a 1st time user sign-up to the M800 server. A successful sign-up allows the end user to log in and out from the app in the
future.

Pre-requisites
Before sign-up, a user needs to be verified. Please consult the M800 Phone Verification SDKs user manual, for details on how to implement
phone verification. The M800 Phone Verification SDK is a separate product from the M800 SDK in this user guide.

How to implement sign-up


After configuring M800SDK, user has to sign up before connecting to M800SDK.
To see if user has signed up to M800SDK, you can invoke

M800SDK.getInstance().hasUserSignedUp()

If the method above returns false, user hasnt signed up, the sign up mechanism is crucial before connecting to M800SDK. Please
invoke M800SDK.getInstance().getManagement().signup(...) to start sign up.

Sign up as a White Label User


We provide two signup methods for you to use, the first one is signup with verification request ID. You should always use this signup API if
possible.

/**
* Sign up user with your verified phone number, requestId and display name.
*
* @param phoneNumber
*
The phone number that to be registered. Numeric digits only.
* @param regionCode
*
The region code of user's region. 2-letters. For example, hk if the
user's region is Hong Kong.
* @param displayName
*
The display name of user.
* @param language
*
The {@link com.m800.sdk.IM800Management.M800Language} object. The
preferred language of this user. Language will be applied
*
in the push string.
* @param callback
*
The {@link M800ManagementCallback} interface to handle result of
operation.
*/
public void signup(final String displayName, final String phoneNumber, final String
regionCode, final String requestId, final M800Language language, final
M800ManagementCallback callback);

We also provide another API that can signup without verification request ID.
If the provided phone number is never registered before, the signup will be successful, but the user need to verify his/her phone number later
when he/she wants to use any paid functions of M800SDK like offnet call, SMS chat.
If the provided phone number is registered before and is signing up with the same device, the signup will be successful and the user will remain
her/his previous verification status.
If the provided phone number is registered before and user is switching device, the signup will be failed with error, indicating that the user need to
verify his/her phone number again.
To verify user's phone number, please use M800 Verification SDK and the signup API above.

/**
* Sign up user with your phone number.
*
*
* @param phoneNumber
*
The phone number that to be registered. Numeric digits only.
* @param regionCode
*
The region code of user's region. 2-letters. For example, 'hk' if the
user's region is Hong Kong.
* @param displayName
*
The display name of user, optional
* @param language
*
The {@link com.m800.sdk.IM800Management.M800Language} object. The
preferred language of this user. Language will be applied
*
in the push string.
* @param callback
*
The {@link M800ManagementCallback} interface to handle result of
operation.
*/
void signup(final String displayName, final String phoneNumber, final String
regionCode, final M800Language language, final M800ManagementCallback callback);

Take the demo project as an example, user verification information is saved as a VerificationInfo object. Please refer to the class Verificat
ionManager.java.

private void signUpAfterVerified(VerificationInfo verificationInfo){


M800SDK.getInstance().getManagement().signup(
verificationInfo.displayName,
verificationInfo.number,
verificationInfo.countryCode.getCountyCode(),
verificationInfo.record.getRequestId(),
IM800Management.M800Language.M800LanguageEnglish,
new IM800Management.M800ManagementCallback() {
@Override
public void complete(boolean isSuccess, M800Error error, Bundle
userInfo) {
if (isSuccess) {
connectAfterSignup();
} else {
//Implement your own sign up failure handling mechanism.
}
}
}
});
}

Sign up as a SDK user


To sign up as a SDK user, you would have no meta-data set as described below

<!--This meta-data is invalid if users are signed up as SDK users.-->


<meta-data android:name="com.m800.signup.user" android:value="whitelabel"
tools:replace="android:value" />

Invoke the following method to sign up:

/**
* Sign up user with your network id and display name.
*
* @param sourceNetworkId
* The id of source network to be registered, {0-1, a-z} only.
* @param displayName
* The display name of source network.
* @param language
* The preferred language of this user. Language will be applied in the push string
* @param callback
* The interface to handle result of operation.
* @throws IllegalStateException
* sourceNetworkId is illegal that should be alphanumeric and the length is not
greater than the value defined by
* M800SDK_MaxSourceNetworkIdLength
*/
public void signup(String sourceNetworkId, String displayName, M800Language language,
M800ManagementCallback callback);

After a successful sign up


After a successful sign up, you can get current users phone number by the following API:

M800SDK.getInstance().getUsername();

After a successful sign up, You can get current users JID (M800 unique identifier) by the following API:

M800SDK.getInstance().getUserJID();

After a successful sign up, please connect to M800 server in order to use the M800SDK provided features. Connection details are
provided in the Connection section.

Connection Module
Introduction
The Connect Module allows the app to manage the connection to M800 servers. Specfically, the module lets the app perform the following:
Connect to M800 server.
Disconnect from M800 server.
Check connection status.
Go online.
Go offline.
Sign out current user.

Pre-requisites
Successful sign-up should have been completed before connecting to M800 servers.

How to implement
After signing up to the M800SDK, connection with M800 Server must be established before using the IM and Call features.
1. To check if the user has signed up, please follow Step 1 in the previous session (Sign Up to M800SDK).
2. To check the connection state, please invoke M800SDK.getInstance().getManagement().getConnectionState().

/**
* This enumeration contains states that represents connection status of
* Management module
*/
public static enum M800ManagementConnectionState {
M800ManagementConnectionDisconnected, /** < Disconnected */
M800ManagementConnectionConnecting, /** < Connecting */
M800ManagementConnectionConnected, /** < Connected */
}

An alternative method is M800SDK.getInstance().getManagement().isConnected().


3. Invoke M800SDK.getInstance().getManagement().connect() to connect to the M800SDK server.

/**
* Connect to management server with current user stored in system.
*
*/
public void connect();

4. Implement the IM800Management.M800ManagementConnectionListener interface to monitor the connectivity with M800SDK server.

/**
* This listener can receive events while connection is changed to connected or
disconnected
* @see com.m800.sdk.IM800Management.M800ManagementConnectionState
*/
public static interface M800ManagementConnectionListener {
/**
* Client is connected to M800 servers.
*/
public void onConnectedToM800();
/**
* Client is disconnected from M800 servers with error.
* If error is NotAuthorized, then need to kick user from system and signup new
user again.
* @param error The reason why is disconnected.
*
*/
public void onDisconnectedFromM800(M800Error error);
}

5. For the full implementation of connection management, please refer to the ApplicationClass.java in the demo project as an example.
Implement IM800Management.M800ManagementConnectionListener interface to monitor the connectivity:

public class ApplicationClass extends MultiDexApplication implements


IM800Management.M800ManagementConnectionListener {
@Override
public void onCreate() {
super.onCreate();

M800SDK.getInstance().getManagement().addConnectionListener (this);
}
@Override
public void onConnectedToM800() {}
@Override
public void onDisconnectedFromM800(M800Error error) {
//Do disconnection handling
if
(M800SDK.getInstance().getManagement().needKickUserForError(error)){
kickUser(error);
}
}
}

Invoke M800SDK.getInstance().getManagement().connect() to trigger connection.

6. To disconnect from M800 server, please invoke M800SDK.getInstance().getManagement().disconnect().

More on Connection Management


This section introduces more features that are supported in the connection module.
1. To update the server user is active with the M800SDK/application, please invoke M800SDK.getInstance().getManagement().goOnline().
Custom status can be added also when going online. M800SDK.getInstance().getManagement().goOnline(String status).
2. To update the server user is inactive with the M800SDK/application, please invoke M800SDK.getInstance().getManagement().goOffline()
3. To clear user data as logout from the M800 server, please invoke M800SDK.getInstance().getManagement().clearAllUserData()
Below is an example.

private void logoutUser() {


final Runnable logoutTask = new Runnable() {
@Override
public void run() {
M800SDK.getInstance().getManagement().clearAllUserData();
}
};
new Thread(logoutTask).start();
}

4. User may receive an M800Error object in the following two cases:


A disconnection event from the listener IM800Management.M800ManagementConnectionListener. onDisconnectedFromM800(
M800Errorerror). See section Connect to M800SDK 5.a.
A connection attempt failure from listener IM800Management.M800ManagementConnectionListener.onDisconnectedFromM800(
M800Error error) when the application is trying to connect to the M800 server. See section Connect to M800SDK 5.b.
The reason of connection failure may due to user invalidation. Please do the checking by invoking M800SDK.getInstance().getManagement
().needKickUserForError(M800Error) with the given M800Error object to see if user should be logout from M800 server.

/**
* Checks whether is the error to kick user out from app.
*
* @param error The given error from M800 callbacks.
* @return If true, means the user is invalid, need to kick user out.
* Otherwise if false, means the current user is still valid and can be continued to
use.
*/
public boolean needKickUserForError(M800Error error);

If result is positive, please proceed to user data clean up as introduced in point 3.


5. Swap Device.
When user has signed up with the same phone number on a new device, M800 server invalidates the user on the older device. On the
older device, user will receive the connection error, an M800Error object with M800ErrorCode.Not Authorized as descripted in point 4. Plea
se do the checking by invoking
M800SDK.getInstance().getManagement().needKickUserForError(M800Error) with the given M800Error object to see if user should be
logout from M800 server for confirmation. Finally, follow the step in point 3 to clear the user sign up data.
6. Custom Notifications.
The connection module supports custom notifications sent from M800 server. Developer need to implement and manage their own M800No
tificationListener object and register to the M800SDK by invoking
M800SDK.getInstance().getManagement().addNotificationListener(M800NotificationListener listener).

Contact Sync Module


Introduction
After user signs up and connects to M800 server for the first time, M800 SDK performs contact sync automatically.
1. SDK gathers and sends a list of all native contacts to the M800 server. By native contact, we mean a contact inside the devices address
book. Upon receipt of the list, M800 server returns a list of M800 users found in the native contacts. The information will saved so that
user can know who are using the same application and add them as M800 contacts easily.
2. SDK uses Roster to represent a list of people (M800 contacts) the user is connected to. SDK queries roster from M800 server and saves
the query result, which is a list of user's M800 contacts.
In short, contact sync contains two parts, one is to sync native contacts, the other is to sync roster. The contact sync is complete after all M800
contacts' information is retrieved from server and added to the SDKs database.

Every M800 contact has its unique JID (Jabber Identifier). JID is represented in two parts. The text before @ is the phone number with country
code prefix. The text after @ is the carrier name.
After contact sync is completed, if an M800 contact is a native contact, it can be searched by JID or phone number. If the M800Contact is not in
native phone book, it can only be searched by JID.

Pre-requisites
Successful sign-up and connection to M800 server.

How to implement
Get M800 contact list
class GetContactsTask extends AsyncTask<Void, Void, List<IM800Contact>> {
@Override
protected List<IM800Contact> doInBackground(Void... params) {
return M800SDK.getInstance().getContactManager().getM800Contacts();
}
@Override
protected void onPostExecute(List<IM800Contact> contacts) {
// Update UI
}
}

Get M800 native contact list

class GetContactsTask extends AsyncTask<Void, Void, List<IM800NativeContact>> {


@Override
protected List<IM800NativeContact> doInBackground(Void... params) {
return M800SDK.getInstance().getContactManager().getM800NativeContacts();
}
@Override
protected void onPostExecute(List<IM800NativeContact> contacts) {
// Update UI
}
}

Start contact sync manually


M800 SDK will do contact sync automatically in the following scenarios:
After user signup.
After app initializes M800SDK, it will start to observe native address book changes. If it detects any phone number or email address ch
anges, it will start contact sync.
You might want to do contact sync when app launches or at fixed rate of time apart from auto sync.

M800SDK.getInstance().getContactManager().startSyncNativeAddressBook(boolean
fullSync);

There is a limitation of how frequent M800 SDK can do contact sync, the default value is 1 minute. You can change this value.
Note. Dont set this value too low, contact sync is very memory and network bandwidth consuming.

M800SDK.getInstance().getContactManager().setMinimumContactSyncTimeInterval(millis);

To find out whether SDK is in synchronizing native contacts:

M800SDK.getInstance().getContactManager().isNativeAddressBookSyncInProgress();

Sync roster
You can sync roster without sync native contacts.

M800SDK.getInstance().getContactManager().queryM800ContactRoster();

Add M800 contact


To add an M800 contact, user needs to send an add contact request to an M800 user. The M800 user can choose to accept or decline the
request. Before the recipient takes any action, user can cancel the request.
If the M800 user accepts the add contact request, both sides will receive a new contact roster push and they become friends of each other.

// Sender side: Create a request


M800AddContactRequest request = <a new request>;
// Sender side : Send the request
M800SDK.getInstance().getContactManager().requestAddM800Contact(request);
// Sender side : Cancel the request
String recipientJID = <...>;
M800SDK.getInstance().getContactManager().cancelM800AddContactRequest(recipientJID );
// Recipient side
String requesterJID = <...>;
// Recipient side : Accept the request
M800SDK.getInstance().getContactManager().acceptM800AddContactRequest(requesterJID);
// Recipient side : Decline the request
M800SDK.getInstance().getContactManager().declineM800AddContactRequest(requesterJID);

To retrieve add contact requests:

// Get a list of requests


M800SDK.getInstance().getContactManager().getM800AddContactRequests(<direction>);
// Get one request
M800SDK.getInstance().getContactManager().getAddContactRequest(<JID>, <direction>);
// Get requests count
M800SDK.getInstance().getContactManager().getAddContactRequestsCount(<direction>);

Remove M800 contact


If user removes an M800 user from his/her contact list, the M800 user will not be notified and still can see current user as his/her contact.

M800SDK.getInstance().getContactManager().removeM800Contact(<JID>);

Register roster event listener


SDK will receive several kinds of roster push events:
1.
2.
3.
4.

New contact added


Contact removed
Add friend request
Contact profile changed

To listener to the roster activities and push events, implement the following listener:

M800SDK.getInstance().getContactManager().addContactChangeListener(this);
M800SDK.getInstance().getContactManager().removeContactChangeListener(this);

@Override
public void onQueryRosterStart() {
// Called when SDK starts to query roster
}
@Override
public void onContactSyncCompleted(boolean hasChange) {
// Called when SDK receives roster push or roster query response
}
@Override
public void onContactSyncError(IM800ContactManager.Error error) {
// Called when error happens during contact sync
}
@Override
public void onNewAddContactRequest(M800AddContactRequest request) {
// Called when SDK receives a new add contact request
}
@Override
public void onAddContactRequestComplete(String jid, M800AddContactRequest.Direction
direction, boolean isAccepted) {
// Called when an add contact request is being accepted/declined/cancelled
}

Find M800 contact by phone number.


Note: Result will only contain M800 contacts that are also in users native address book.

M800SDK.getInstance().getContactManager().findM800ContactByPhoneNumber(phone#);

Find M800 contact by JID


M800SDK.getInstance().getContactManager().findM800ContactByJID(JID);

Presence (Last Seen)


User can send online and offline messages to M800 server so that the server can store it as his/her presence information. In user preference
module, user can turn off the share presence function so no other user can see his/her presence.
To send online message:

// Connect to M800 and send online message


M800SDK.getInstance().getLifeCycleManager().applicationWillEnterForeground();

To send offline message:

// Send offline message immediately


M800SDK.getInstance().getManagement().goOffline();
// Disconnect from M800 and send offline messages after 10 minutes
M800SDK.getInstance().getLifeCycleManager().applicationDidEnterBackground();

User can query his/her contacts presence information:

M800SDK.getInstance().getContactManager().queryLastSeen(JID, true, new


IM800ContactManager.QueryLastSeenCallback() {
@Override
public void onComplete(String JID, IM800ContactManager.UserPresence presence, Date
date) {
}
@Override
public void onError(String JID, M800Error error) {
}
});

M800 server will also push current users contact presence information, to listen to the presence changes:

M800SDK.getInstance().getContactManager().addUserPresenceListener(new
IM800ContactManager.UserPresenceListener() {
@Override
public void onPresenceChanged(String JID, IM800ContactManager.UserPresence
presence) {
}
});

Call Module
Introduction
M800SDK provides functionality to initiate and handle calls.
There are three major models which facilities the call feature: M800Client, M800ClientConfiguration and M800Call.
M800Client manages the call engine of M800SDK, creates and preserve call objects from the initialization of user action or incoming call
bundles. It provides APIs for the application to listen for the call engine status via M800ClientDelegate listener.
To get the M800Client singleton from M800SDK, please invoke
M800SDK.getInstance().getRealtimeClient().
M800ClientConfiguration configures the call engine setting. For example, it configures the threshold of packet loss, the ring-back tone
and the hold tone.
M800SDK creates a default M800ClientConfiguration configuration for M800Client during SDK initialization. To get the current M800ClientC
onfiguration setting from M800Client, please invoke M800SDK.getInstance().getRealtimeClient().getCurrentConfiguration().

Developer may provide the customized M800ClientConfiguration configuration to M800Client and restart it, see M800Client.start(M800Clien
tConfiguration configuration):

/**
* Starts client with a new configuration.
* @param configuration
* A new configuration contains username, password, resources and so on.
*/
void start(M800ClientConfiguration configuration);

M800Call represents a VOIP call managed by M800Client. It provides information of a call. It manages the in-call activities of a call. For
example, it provides APIs to answer if it is an incoming call and to terminate the call.
M800Call also updates the application the call status and events. To listen for the status of a M800Call object. See

/**
* Adds delegate to handle evens of this call session.
* @param delegate To listener to call event.
*/
void addCallDelegate(M800CallDelegate delegate);

To understand more about the call module, the best way is to look into the class description, Java Documentation, on the package
com.m800.msme.api.

How to implement
In this section, we are going to descript the step-by-step procedure for how to use the main features provided by M800 call engine.

Making an outgoing on-net call (VOIP VOIP call)


Get the M800Client instance from M800SDK.
See com.m800.uimenu.RealtimeMenuActivity from the demo project.

M800Client realtimeClient = M800SDK.getInstance().getRealtimeClient();

Create an outgoing call object by M800Client.

M800OutgoingCall call = realtimeClient.createCall(userName, displayName, carrier,


null, "");

Please check the Java Documentation for the full description of input parameters. And refer to com.m800.uimenu.RealtimeMenuActivity
from the demo project for solid implementation.

/**
* Makes a call to given receiver which maybe phone number or user id.
* If receiver is a phone number, it is an offnet call.
* If receiver is user id (JID), it is an onnet call.
* @param username e.g. "+85288888888", the phone number or the username of JID
* @param carrier e.g. "maaii.com", the carrier of JID. i.e. existence of {@code
carrier} determines this is a Off-net call.
* @param display the encode display name with Base64 of user (the caller). This is
sent to the receiver as part of the incoming call notification information.
* @param userInfo Put caller extra info. e.g. name, social info, etc.
* @param callID A random id used to distinguish the {@link M800Call} object.
* @return A {@link M800OutgoingCall} made by the information provided.
*/
@Nullable
M800OutgoingCall createCall(String username, String display, String carrier,
Map<String, String> userInfo,
String callID);

Note: The display name should have encoded with Base64.


Present your own UI for the call.
Invoke dial

call.dial();

Add listener M800CallDelegate to the outgoing call object.


See com.m800.phonecall.CallScreenActivity from the demo project.

public class CallScreenActivity extends Activity implements OnClickListener,


M800CallDelegate {
@Override
public void onStart() {
super.onStart();
String callID = getIntent().getExtras().getString(EXTRA_KEY_CALL_ID);
mCall = M800SDK.getInstance().getRealtimeClient().getCall(callID);
mCall.addCallDelegate(this);
}
//Your own implementations
}

Work closely with call events from the implemented M800CallDelegate.


See com.m800.phonecall.CallScreenActivity from the demo project.
When the callee answers your call, you will receive the callBeginTalking events from M800CallDelegate.

/**
* Event: call is talking.
* @param call The call.
*/
void callBeginTalking(M800Call call);

The event indicates the call has started and you are talking with the callee.
After a certain period, you will receive a callTerminated event when the call ends. The termination would be triggered by either the callees
or your action to stop the call, the network failure or some other failure reasons.

/**
* Event: call is ended for some reasons.
* @param call The call.
*/
void callTerminated(M800Call call, int status, Map<String,String>
userInfo);

Otherwise, if the callee rejects your call, you will receive the callTerminated event from M800CallDelegate directly.
Get the M800Client instance from M800SDK.
See com.m800.uimenu.RealtimeMenuActivity from the demo project.

To make an outgoing off-net call (VOIP PSTN call)


Get the M800Client instance from M800SDK.
See com.m800.uimenu.RealtimeMenuActivity from the demo project.

M800OutgoingCall call = realtimeClient.createCall(userName, displayName, carrier,


null, "");

Create an outgoing call object by M800Client.


Please be reminded that no carrier should be provided.

M800OutgoingCall call = realtimeClient.createCall(userName, displayName, null, null,


"");

Please check the Java Documentation for the full description of input parameters. And refer to com.m800.uimenu.RealtimeMenuActivity
from the demo project for solid implementation.

/**
* Makes a call to given receiver which maybe phone number or user id.
* If receiver is a phone number, it is an offnet call.
* If receiver is user id (JID), it is an onnet call.
* @param username e.g. "+85288888888", the phone number or the username of JID
* @param carrier e.g. "maaii.com", the carrier of JID. i.e. existence of {@code
carrier} determines this is a Off-net call.
* @param display the encode display name with Base64 of user (the caller). This is
sent to the receiver as part of the incoming call notification information.
* @param userInfo Put caller extra info. e.g. name, social info, etc.
* @param callID A random id used to distinguish the {@link M800Call} object.
* @return A {@link M800OutgoingCall} made by the information provided.
*/
@Nullable
M800OutgoingCall createCall(String username, String display, String carrier,
Map<String, String> userInfo,
String callID);

Note: The display name should have encoded with Base64.


Present your own UI for the call.
Invoke dial.

call.dial();

Add listener M800CallDelegate to the outgoing call object. See com.m800.phonecall.CallScreenActivity from the demo project

public class CallScreenActivity extends Activity implements OnClickListener,


M800CallDelegate {
@Override
public void onStart() {
super.onStart();
String callID = getIntent().getExtras().getString(EXTRA_KEY_CALL_ID);
mCall = M800SDK.getInstance().getRealtimeClient().getCall(callID);
mCall.addCallDelegate(this);
}
//Your own implementations
}

Work closely with call events from the implemented M800CallDelegate.


See com.m800.phonecall.CallScreenActivity from the demo project.
When the callee answers your call, you will receive the callBeginTalking events from M800CallDelegate.

/**
* Event: call is talking.
* @param call The call.
*/
void callBeginTalking(M800Call call);

The event indicates the call has started and you are talking with the callee.
After a certain period, you will receive a callTerminated event when the call ends. The termination would be triggered by either the callees
or your action to stop the call, the network failure or some other failure reasons.

/**
* Event: call is ended for some reasons.
* @param call The call.
*/
void callTerminated(M800Call call, int status, Map<String,String> userInfo);

Otherwise, if the callee rejects your call, you will receive the callTerminated event from M800CallDelegate directly.

/**
* Event: call is ended for some reasons.
* @param call The call.
*/
void callTerminated(M800Call call, int status, Map<String,String> userInfo);

The int status tells the call termination reason.

Receiving an incoming call


Incoming call notification bundles arrive the device via two channels, IM Push notifications and Remote Notifications:

IM Push Notification
The bundle is received internally via M800SDK connection module. It is broadcasted to the application level once it is received.
To listen for the IM Push Notifications for call, please register a BroadcastReceiver for the IntentFilter
M800CallNotification.getIntentFilterForM800CallNotifications(Context).
Please see com.m800.service.AppM800Service as an example:

@Override
public void onCreate() {
super.onCreate();
BroadcastReceiver mCallNotificationReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
//Implement your own code
}
};
LocalBroadcastManager.getInstance(this).registerReceiver(mCallNotificationReceiver,
M800CallNotification.getIntentFilterForM800CallNotifications(this));
}

Remote Notification

Received and configured by the application. For example, the incoming call notification will be received as GCM. Developer should
configure and implement the GCM service on application level.
To handle the incoming call notification bundles:
When incoming call notification bundle is received from Step 1, please provide it to the M800Client instance by invoking M800Client.catch
RemoteNotification(bundle). You may look into com.m800.service.GcmIntentService for reference.

/**
* Handle M800 Call notifications from GCM or M800 Push Service
* @param intent
*/
public static void onHandleCallNotification(Context context, Intent intent){
Bundle bundle = intent.getExtras();
M800Client client = M800SDK.getInstance().getRealtimeClient();
if (client != null) {
// Handle incoming push call
M800IncomingCall call = client.catchRemoteNotification(bundle);
if (null != call) {
//Start call UI
}
}
}

With the returned M800IncomingCall object from M800IncomingCall call = client.catchRemoteNotification(bundle);, application may now work
with the incoming call.
Present your own UI to work with the incoming call. For example, provide a button on screen for call answering and provide a button for
call rejecting.
Do the same as in the section To make an outgoing off-net call (VOIP PSTN call) step 6, implemented M800CallDelegate to listen for
the call
To reject the call, invoke M800IncomingCall.reject(Stringreason).
To answer the call, invoke M800IncomingCall.answer().
Note. The M800IncomingCall.callId() is different from the call ID from the incoming call notification bundle. If you want to match the call ID from
the incoming call notification bundle, follow the below steps:
Check if this is a push call by M800Call.isPuchCall().
If it is a push call, you can use M800Call.getPushCallId() to match with the incoming call notification bundle.

To reject a call silently from an incoming call notification bundle


It is not the best practice to create an incoming call object and notify the user regardless to the device status.
The application should decide when to procced the incoming call or to reject the call silently. Invoke the method below to reject the call when user
is busy with another call, either the native PSTN call or M800 call:
M800Client.rejectCallSinceBusyWithRemoteNotification(Bundle bundle)
You will receive a missed call notification afterwards.

To handle a missed call notification


The missed call notification bundle handling is same as incoming call notification bundle handling. The step To receive an incoming call
step 1 receives missed call notification bundle also.
Same as To receive an incoming call step 2, pass the bundle to M800Client by invoking client.catchRemoteNotification(bundle);.
However, this time you will not get any M800IncomingCall object from the method.
If there is already the M800IncomingCall object created from the incoming call bundle, with the implemented M800CallDelegate added to
the M800IncomingCall object, you will receive the callTerminated event from M800CallDelegate.

/**
* Event: call is ended for some reasons.
* @param call The call.
*/
void callTerminated(M800Call call, int status, Map<String,String>
userInfo);

The int status tells the call termination reason, that the caller has cancelled the call.

How to Configure M800ClientConfiguration


The M800ClientConfiguration allows user to customize to customize the call. Here we introduce some of the parameters that are commonly
configured.
Set packet loss threshold.

/**
* Sets the threshold while packet is lost.
* After that, the call would be teminated automatically.
*
* @param threshold The seconds for lossing packet.
*/
public abstract void setPacketLossThreshold(int threshold);

The communication packets keep transporting along the conversation. If there is no packet arrived to the device for the defined packet loss
threshold, the M800 call engine will determine this call as disconnected.
The communication packets keep transporting along the conversation. If there is no packet arrived to the device for the defined packet loss
threshold, the M800 call engine will determine this call as disconnected.
Reconnection configurations.
Set support reconnection

/**
*
* @param support {@value true} means the M800 call engine will attempt to restart a
call if it is disconnected.
*/
public abstract void setSupportCallReconnection(boolean support);

Set this value to be true so that the M800 call engine will attempt to restart a call if it is disconnected.
Set reconnection packet loss threshold

/**
* To set the delay to start call reconnection after network resume.
* <p>
* i.e. The total threshold in {@link
M800ClientConfiguration#getPacketLossThreshold()} should be longer than ((1 + {@link
M800ClientConfiguration#callReconnectionMaxRetries()})* ({@link
M800ClientConfiguration#callReconnectionPacketLossThresholdInMs()} + {@link
M800ClientConfiguration#callReconnectionTimeoutInSec()}))
* @param milliseconds The delay in milliseconds to start call reconnection after
network resume.
*
*/
public abstract void setCallReconnectionPacketLossThresholdInMs(int milliseconds);

To set the time delay starting call reconnection after network resumes.
Set reconnection maximum retries

/**
* To set the maximum number of reconnection retries.
* <p>
* i.e. The total maximum number of reconnection attempts = 1 + {@link
M800ClientConfiguration#callReconnectionMaxRetries()}
* @param retries
*/
public abstract void setCallReconnectionMaxRetries(int retries);

To set the timeout in second for each reconnection attempt.


Set hold tone

/**
* Set the hold tone to be played to the remote party if you hold the call.
* @param holdToneFilePath the file path of hold tone.
*/
public abstract void setHoldTone(String holdToneFilePath);

The hold tone is played to the remote party when you hold the call.
Set ring back tone

/**
* Set the ring back tone to be played locally when the user is dialing out a call.
* @param ringbackTonePath the file path of ring back tone.
*/
public abstract void setRingbackTone(String ringbackTonePath);

The ring back tone will be played locally when the user is dialing out a call. You have to enable this feature also by

/**
* Set the flag to enable playing ring back tone locally.
* @param support
*/
public abstract void setSupportPlayRingbackToneInEngine(boolean
support);

Steps to provide a comprehensive call experience


Support the mute and speaker feature
In addition of the basic features provided by M800Call, you can enhance the call by M800Audio.
M800Audio provides the feature such as mute/unmute, switching the audio channel to speaker, etc.
The CallScreenActivity.java from demo project shows the example to mute the audio channel during a call:

M800Audio am = M800SDK.getInstance().getRealtimeClient().getAudioManager();
if (am.isMute()){
am.unmute();
this.buttonMute.setText("Mute");
} else {
am.mute();
this.buttonMute.setText("Unmute");
}

Play a sound locally to notify user the call is connected


Place the connected.mp3 file in the res/raw directory of your project. You may copy this audio file from the demo project at the same
directory res/raw. Or, you may also provide your own audio file, but please be reminded that the file should be named as connected.mp3.
When the call event M800CallDelegate.callBeginTalking() of the call is trigged, you may play the sound by invoking M800Audio.playDiscon
nect(). The CallScreenActivity.java from demo project shows the example:

@Override
public void callBeginTalking(M800Call call) {
//Your own implemetation
M800Audio am = M800SDK.getInstance().getRealtimeClient().getAudioManager();
if (am != null) {
am.playDisconnect();
}
}

Play a sound locally to notify user he/she has sent a DTMF (dual tone multi
frequency) tone over the call
Place the dtmf_1024.mp3 file in the res/raw directory of your project. You may copy this audio file from the demo project at the same
directory res/raw. Or, you may also provide your own audio file, but please be reminded that the file should be named as dtmf_1024.mp3.
The CallScreenActivity.java from demo project demonstrates how to send a DTMF tone over the call.

private void pressDTMF(String key) {


mCall.sendDTMF(key);
//Your own implemetation
}

When the method of call M800Call.sendDTMF(String key) is invoked, with the presence of the dtmf_1024.mp3 file in the res/raw directory, the
DTMF tone would be played automatically.

Dim screen when users face is close to the screen.


It is a common behavior of the mobile devices that the screen dims when users face is close to the device during a call conversation. This
implementation is to prevent from any unexpected touch events.
To apply this logic, Proximity Sensor is used. Check http://developer.android.com/guide/topics/sensors/sensors_position.html#sensors-po
s-prox
The proximity sensor is usually used to determine how far away a person's head is from the face of a handset device (for example, when a
user is making or receiving a call). Most proximity sensors return the absolute distance, in cm, but some return only near and far values.
The following code shows you how to use the proximity sensor:

public class SensorActivity extends Activity implements SensorEventListener {


private SensorManager mSensorManager;
private Sensor mProximity;
@Override
public final void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Get an instance of the sensor service, and use that to get an instance of
// a particular sensor.
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mProximity = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
}
@Override
public final void onAccuracyChanged(Sensor sensor, int accuracy) {
// Do something here if sensor accuracy changes.
}
@Override
public final void onSensorChanged(SensorEvent event) {
float distance = event.values[0];
// Do something with this sensor data.
}
@Override
protected void onResume() {
// Register a listener for the sensor.
super.onResume();
mSensorManager.registerListener(this, mProximity,
SensorManager.SENSOR_DELAY_NORMAL);
}
@Override
protected void onPause() {
// Be sure to unregister the sensor when the activity pauses.
super.onPause();
mSensorManager.unregisterListener(this);
}
}

When you receive the event, you should apply your own logic to dim the screen. For example, simply display a black screen on top of the
current Activity as to hide the buttons in UI. Below is the example how to handle the sensor event:

@Override
public final void onSensorChanged(SensorEvent event) {
float distance = event.values[0];
// Do something with this sensor data.
if (event.sensor.getType() == Sensor.TYPE_PROXIMITY) {
// values[0]: Proximity sensor distance measured in centimeters
if (distance > 0) {
Log.d(DEBUG_TAG, "<onSensorChanged> Restoring screen brightness");
} else {
Log.d(DEBUG_TAG, "<onSensorChanged> Dimming screen");
}
}
}

Work closely with network status.


The VOIP call relies on network. You should check the network status before making any outgoing call by the M800 call engine. If no
network is subscripted, you should show to the user a correct notification about the reason why call cannot be established.
The following snippet shows how to use the ConnectivityManager to query the active network and determine if it has Internet connectivity.
(Ref. http://developer.android.com/training/monitoring-device-state/connectivity-monitoring.html )

ConnectivityManager cm =
(ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
boolean isConnected = activeNetwork != null &&
activeNetwork.isConnectedOrConnecting();

Work closely with native phone status.


The VOIP calls should never interrupt PSTN call. The application should always regard to the instant native phone status when making an
outgoing VOIP call or receiving an incoming VOIP call.
To work with the phone status, add the following permission in AndroidManufest.xml.

<uses-permission android:name="android.permission.READ_PHONE_STATE" />

The following snippet shows how to get the phone status.

private TelephonyManager telephonyManager =


(TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
int callState = telephonyManager.getCallState();

If the call state equals to TelephonyManager.CALL_STATE_IDLE, it means that the phone is idle of call. The application can establish a
VOIP call at that moment.
Otherwise, if the phone is not idle of call while the application receives an incoming call notification bundle, the application should reject the
call by providing the bundle to the M800Client instance:
M800Client.rejectCallSinceBusyWithRemoteNotification(Bundle bundle). See the class GcmIntentService.java of demo project for full
implementation.
User attempts to make an outgoing VOIP call, the application should not create any M800Call object; instead, return user the response with

call failure reason.


The application should also listen for the native phone status changes when it is undergoing a VOIP call.
The following snippet shows how to listen for the phone status changes.

public class NativePhoneManager extends PhoneStateListener{


private TelephonyManager telephonyManager;
public NativePhoneManager(Context context) {
if(context != null) {
telephonyManager = (TelephonyManager)
context.getSystemService(Context.TELEPHONY_SERVICE);
telephonyManager.listen(this,
PhoneStateListener.LISTEN_CALL_STATE |
PhoneStateListener.LISTEN_DATA_ACTIVITY);
}
}

/**
* Hang-up or hold VOIP call when incoming GSM call immediately
*/
@Override
public void onCallStateChanged(int state, String incomingNumber) {
//Your implementation when the call state changes.
}
}

When a PSTN call interrupts the VOIP call, the application may decide to terminate the VOIP call or just hold the call. Consider also when
the PSTN call terminates, should the application resume the call screen and un-hold the call for user.

Responsive UI to the in-call events


Since there is the API to add the M800CallDelegate listener to a M800Call object, the application is able to display responsive UI during a
call conversation.
Developer may get the instant call state by either invoking M800Call.callState() or from the events of M800CallDelegate. Such as
M800CallDelegate.callReconnecting(M800Call call, int attempts, boolean isPeerReconnecting),
M800CallDelegate.callBeginTalking(M800Call call),
M800CallDelegate .callTerminated(M800Call call, final int status, Map<String, String> userInfo), etc.
Developers should decide their own action for each events, for example,
Show an Answer Call button when it is an incoming call waiting the user to answer.
Remove the Answer Call button when an incoming call has been answered.
Display the time elapsed for the call conversation.
Display the Hold button with correct status. For example, when you receive the M800CallDelegate.callHoldByRemote(M800Call
call) event , you should disable the Hold button since only one party can hold the call at the same time.
Check also the events M800CallDelegate.callHoldByLocal(M800Call call), M800CallDelegate.callUnholdByRemote(M800Call
call), M800CallDelegate.callUnholdByLocal(M800Call call), etc.
Display the connection health status of call by handling M800CallDelegate.networkQualityReport(M800Call call, long
qualityLevel) .
Last but not least, remove the call screen when a call is terminated.
CallScreenActivity.java demonstrates some of the event handling cases.

Incoming call notifications.


Apply your own logic to notify the user there is an incoming call to the device.
Possible methodologies:
Ringer

Vibration
System notification
Incoming call screen when device is locked
Etc.

Missed call notifications.


Apply your own logic to notify the user there was a missed call to the device. Possible methodologies:
System notification
Call history
Etc.

Call history management.


There is sufficient information that allows the application to develop its own call history. Developer may make use of the following data to
store the call history information. Such as,
incoming call notification bundles,
the missed call notification bundles,
the call started talking events from M800Call objects,
Call terminated events from M800Call objects, etc.
With the data stored, the application may also apply their own business logic to display the call history.
Support audio input/output from blue tooth device.
The M800 call engine supports calls over a blue tooth device. To enable this feature, please add the permission in AndroidManufest.xml.

<uses-permission android:name="android.permission.BLUETOOTH"/>

Use Third Party Push Service


After your APP established M800 connection using M800SDK, it can receive several kinds of push messages including IM messages, system
push messages and call push messages. If the app is killed either by user or system, the M800 connection will also be terminated and the user
will not be able to receive any push. There are two ways to prevent this from happening:
1. Keep your app process always alive in background.
If your app process is always alive, it can then keep the M800 connection always alive.
However, we dont suggest you to do so because, first, keeping a long live process is very troublesome and will consume extra
device battery and memory; second, keeping a long live M800 connection is wasting both server and client resources.
2. Use a third party push service.
There are some third party push services available in the market that can help M800 server send messages to your APP without
establishing M800 connection. Currently, we support Google Cloud Messaging (GCM) and JPush. It is recommended that you
choose one or both of the services to receive push messages when your app goes to background.
To integrate a third party push service into your app, please visit
Google Cloud Messaging (GCM)
https://developers.google.com/cloud-messaging/
JPush
https://www.jpush.cn/common
After creating an account in the push service website, you need to provide your server API key to M800 server and put the APP API key inside
your APP.
A unique Registration ID will be created for your APP on each device. You need to upload the Registration ID to M800 server after sign up.
GCM example:

String regID =
GoogleCloudMessaging.getInstance(context).register(<GCM_APP_API_KEY>);
M800SDK.getInstance().getManagement().updatePushToken(regId,
IM800Management.PushType.GCM,
new M800ManagementCallback() {
@Override
public void complete(boolean isSuccess, M800Error error, Bundle userInfo) {
if (isSuccess) {
// Successfully uploaded
} else {
// Failed
}
}
});

JPush example:

String regID = JPushInterface.getRegistrationID(context);


M800SDK.getInstance().getManagement().updatePushToken(regID,
IM800Management.PushType.JPUSH,
new IM800Management.M800ManagementCallback() {
@Override
public void complete(boolean isSuccess, M800Error error, Bundle userInfo)
{
if (isSuccess) {
// Successfully uploaded
} else {
// Failed
}
}
});

After uploading the Registration ID to M800 server, your APP should be able to receive push via
GCMBroadcastReceiver or JPushBroadcastReceiver you implemented.
When receives any M800 push messages, you need to first start M800 connection. After that, you need to pass
the push message to M800 Realtime Client to see if it is an incoming call push or missed call push.
Please refer to com.m800.service.GCMIntentService for example.

IM Module
Introduction
The IM module in the m800SDK provides functionality to run single and multiple-user chat rooms in your app. There are two core features:
1-to-1 Chat. The single user chat (SUC) function allows a single user to send a message to another single user. The sent message can include
text, image, audio, location etc.
Group Chat. The multi-user chat (MUC) features allows a single user to send a message to a group of users. The sent message can include text,
image, audio, location, etc (same as 1-to-1 chat).
To enable IM features, you need a list of M800 contact. The contact list provides a set of JID with which you can to create a chat room. After the
chat room is created by one JID for SUC or multi JID for MUC, a message can be sent to the chat room. A chat room view controller should be
built and listening to the message changes from the SDK.
Note: this guide does not describe in detail how to build a chat room UI.

Pre-requisites
Successfully completed contact sync

How to Implement
Single User Chat Room(SUC)
As a start point...
Please get an instance of IM800SingleUserChatRoomManager from M800SDK.

IM800SingleUserChatRoomManager sucManager =
M800SDK.getInstance().getSingleUserChatRoomManager();

Single User Chat Room(SUC) Creation


Please invoke createChatRoom() to start SUC Creation.

/**
* Create single user chat room.
* If the chat room is already existed, it will return this chat room.
*
* @param jid The jid of member
* @param callback The {@link CreateSingleUserChatRoomCallback}
whose {@link CreateSingleUserChatRoomCallback#complete(String, String)}
method will be called if the request is success, otherwise {@link
CreateSingleUserChatRoomCallback#error(String,
M800ChatRoomError, String)} method will be called.
*/
void createChatRoom(String jid, CreateSingleUserChatRoomCallback callback);
/**
* Callback for use with {@link IM800SingleUserChatRoomManager#createChatRoom(String,
CreateSingleUserChatRoomCallback)} to get the create/retrieve chat room result.
*
* If roomId is null, it will return {@link
M800ChatRoomError#INVALID_PARAMETER} from provided callback.
*
*/
interface CreateSingleUserChatRoomCallback {
/**
* Called on the main thread of the process to report that the chat room is
created/retrieved.
*
* @param roomId multi chat room ID
* @param jid The jid of member
*/
void complete(String roomId, String jid);
/**
* Called
chat room.
*
* @param
* @param
* @param
*/

on the main thread of the process to report that fail to create single

jid The jid of member


error simplified error result
message detail error result

void error(String jid, M800ChatRoomError error, String message);


}

Take the demo project as an example; please refer to the class ChatRoomApiDemoCreateSUCActivity.java.

sucManager.createChatRoom(
selectedJid,
new IM800SingleUserChatRoomManager.CreateSingleUserChatRoomCallback() {
@Override
public void complete(String roomId, String jid) {
//If success, a related roomId will be return here.
}
@Override
public void error(String jid, M800ChatRoomError error, String message) {
//If failure, please read the error message to find the reason.
}
}
);

To create SUC, it just creates a related data in local database; it doesnt need to send request to server. That mean, SDK will not validate
the provided JID (Definition of Jabber Identifier). As long as, the provided JID is not empty, it must be return success result. If it returns
failure result, please check if the provided JID is not empty. (Please note that, if the JID is not existed, related chat room impossible to
receive any message from server.)
If the SUC is already created for given JID, it will return the existing chat room ID.

Monitor Single User Chat Room(SUC) Activity


SDK has provided two modes to monitor SUC Activity; one is monitoring all SUC Activity.

/**
* Register a listener that listeners events of all single user chat rooms.
*
* @param listener a listener implements {@link IM800SingleUserChatRoomListener}
* @throws NullPointerException if listener is null
*/
void addChatRoomListener(IM800SingleUserChatRoomListener listener);

Another one is monitoring specified SUC Activity.

/**
* Register a listener that listeners events of a single user chat room.
*
* @param roomID single user chat room ID
* @param listener a listener implements {@link IM800SingleUserChatRoomListener}
* @throws NullPointerException if listener is null
* @throws IllegalStateException if roomID is null or empty
*/
void addChatRoomListener(String roomID, IM800SingleUserChatRoomListener listener);

Both of them are using the same listener.

/**
* Callback for use with {@link
IM800SingleUserChatRoomManager#addChatRoomListener(IM800SingleUserChatRoomListener)}
to monitor the activity of all single chat room.
* Callback for use with {@link
IM800SingleUserChatRoomManager#addChatRoomListener(String,
IM800SingleUserChatRoomListener)} to monitor the activity of specified single
chat room.
*/
public interface IM800SingleUserChatRoomListener {
/**
* Called on the main thread of the process to report that a new single chat room
has been created.
*
* @param roomId single user chat room ID
*/
void onChatRoomCreated(String roomId);
/**
* Called on the main thread of the process to report that an existing single chat
room has been removed from local database.
*
* @param roomId single user chat room ID
*/
void onChatRoomRemoved(String roomId);
/**
* Called on the main thread of the process to report that chat activity occurs.
*
* @param roomId single user chat room ID
* @param lastUpdateTime last chat time
*/
void onLastUpdateTimeChanged(String roomId, Date lastUpdateTime);
}

Take the demo project as an example. Please refer to the class ChatRoomListFragment.java.

IM800SingleUserChatRoomListener mySUCListener = new IM800SingleUserChatRoomListener()


{
@Override
public void onChatRoomCreated(String roomId) {
//Invoked when any new SUC created in local database.
}
@Override
public void onChatRoomRemoved(String roomId) {
//Invoked when any new SUC removed in local database.
}
@Override
public void onLastUpdateTimeChanged(String roomId, Date lastUpdateTime) {
//Invoked when any SUC has chat activity.
}
};
sucManager.addChatRoomListener(mySUCListener);

We recommend that you keep the reference object of the listener, since developer needs it to stop related monitoring.
To stop monitoring SUC Activity, please invoke removeChatRoomListener() to stop monitor SUC activity.

/**
* Unregister a single user chat room listener.
*
* @param listener a listener previously registered
* @throws NullPointerException if listener is null
*/
void removeChatRoomListener(IM800SingleUserChatRoomListener listener);

We recommend that, if developers no longer need to monitor SUC Activity, please do not forget to invoke removeChatRoomListener() t
o stop monitoring:

sucManager.removeChatRoomListener(mySUCListener);

To stop all SUC Activity monitoring, invoke clearChatRoomListeners():

/**
* Unregister all single user chat room listeners.
*/
void clearChatRoomListeners();

Like so:

sucManager.clearChatRoomListeners();

Retrieve Single User Chat Room(SUC)


To retrieve all SUC, please invoke getChatRooms().

/**
* Get all single user chat rooms.
*
* @return list of single user chat rooms
*/
@NonNull
List<IM800SingleUserChatRoom> getChatRooms();

Take the demo project as an example. Please refer to the class ChatRoomListFragment.java.

List<IM800SingleUserChatRoom> chatRooms = sucManager.getChatRooms();

The above method will query from local database with the sequence descending order of last chat time, and return full list of SUC model
objects.

To retrieve specified SUC model objects, SDK has provided two ways for this query. One is to retrieve SUC model object by JID:

/**
* Obtain specific single user chat room.
*
* @param jid The jid of member
* @return single user chat room if found, null otherwise.
*/
IM800SingleUserChatRoom getChatRoomByJID(String jid);

Another way to retrieve SUC model object, by roomID:

/**
* Obtain specific single user chat room.
*
* @param roomId single chat room ID
* @return single user chat room if found, null otherwise.
*/
IM800SingleUserChatRoom getChatRoomById(String roomId);

Since the above retrieval methods are related to database query action, we recommend that, developer should invoke these methods in
a background thread, thus avoid blocking the main thread.

Single User Chat Room(SUC) Deletion

To remove the SUC related data from local database, please invoke deleteChatRoom() to start SUC Deletion.

/**
* Delete the chat room and all related data in local database.
*
* @param roomId single chat room ID
* @return true if this chat room was deleted, false otherwise.
*/
boolean deleteChatRoom(String roomId);

This method will return true if the related SUC was found and deleted, return false otherwise.
Take the demo project as an example; please refer to the class ChatRoomListFragment.java.

sucManager.deleteChatRoom(roomId);

Since the above deletion method related to database delete action, we recommend that, developer should invoke this methods in
background thread, thus avoid block the main thread process.

Retrieve Participants In Single User Chat Room(SUC)


To retrieve participants in specified SUC, please invoke getParticipants().

/**
* Get participants in a single user chat room.
*
* @param roomId single chat room ID
* @return participant list including current user and the other participant
*/
@NonNull
List<IM800SingleUserChatRoomParticipant> getParticipants(String roomId);

The above method will query from local database, and return full list of SUC Participant model objects.
Since the above retrieval methods are related to database query action, we recommend that, developer should invoke this method on a
background thread, thus avoid blocking the main thread process.

Multi User Chat Room(MUC)


As a starting point...
Please get an instance of IM800MultiUserChatRoomManager from M800SDK:

IM800MultiUserChatRoomManager mucManager =
M800SDK.getInstance().getMultiUserChatRoomManager();

Multi User Chat Room(MUC) Creation


Please invoke createChatRoom() to start MUC Creation.

/**
* Create multi user chat room
* Title cannot be empty
* Please at least invite two members
*
* @param title The title of chat room
* @param jids JID the unique identifier of an M800 user, the members will be
invite.
* @param callback an asynchronous callback of create chat room result,
*
{@link CreateMultiUserChatRoomCallback#complete(String, String,
String[])} method will be called if the request is success,
*
otherwise {@link CreateMultiUserChatRoomCallback#error(String,
String[], M800ChatRoomError, String)} method will be called.
*/
void createChatRoom(String title, String[] jids, CreateMultiUserChatRoomCallback
callback);

interface CreateMultiUserChatRoomCallback {
/**
* Called when create-chat-room request is accepted by server.
*
* <p>Please note when this callback is invoked, the group chat room is not
created in client SDK yet.
* To monitor chat room creation event, register a listener to listen {@link
IM800MultiUserChatRoomListener#onChatRoomCreated(String)}.</p>
* <p>This callback is called on application's main thread.</p>
*
* @param roomId multi chat room ID
* @param title The title of chat room
* @param jids JID the unique identifier of an M800 user, the members will be
invite.
*/
void complete(String roomId, String title, String[] jids);
/**
* Called when create chat room is finished with error.
*
* <p>This callback is called on application's main thread.</p>
*
* @param title The title of chat room
* @param jids JID the unique identifier of an M800 user, the members will be
invite.
* @param error simplified error result
* @param message detail error result
*/
void error(String title, String[] jids, M800ChatRoomError error, String message)
}

Compare with SUC creation, MUC creation has different workflow. Even if the request is success, it will not create the related data in local
database immediately. Until receive a MUC invitation message from server, it would insert this related data into local database. To monitor when
the related MUC created, please see addChatRoomListener().
Use the following API to get maximum number of group chat room members allowed in one room.

mucManager.getMaxParticipantNum()

Monitor Multi User Chat Room(MUC) Activity


Please invoke addChatRoomListener() to start monitor MUC activity.
SDK has provided two modes to monitor MUC Activity; one is monitoring all MUC Activity.

/**
* Register a listener that listeners events of all multi user chat rooms.
*
* @param listener a listener implements {@link IM800MultiUserChatRoomListener}
* @throws NullPointerException if listener is null
*/
void addChatRoomListener(IM800MultiUserChatRoomListener listener);

Another one is monitoring specified MUC Activity.

/**
* Register a listener that listeners events of a multi user chat room.
*
* @param roomId multi user chat room ID
* @param listener a listener implements {@link IM800MultiUserChatRoomListener}
* @throws NullPointerException if listener is null
* @throws IllegalStateException if roomID is null or empty
*/
void addChatRoomListener(String roomId, IM800MultiUserChatRoomListener listener);

Both of them are using the same listener.

/**
* Callback for use with {@link
IM800MultiUserChatRoomManager#addChatRoomListener(IM800MultiUserChatRoomListener)} to
monitor the activity of all multi chat room.
* Callback for use with {@link
IM800MultiUserChatRoomManager#addChatRoomListener(String,
IM800MultiUserChatRoomListener)} to monitor the activity of specified multi chat room.
*/
public interface IM800MultiUserChatRoomListener
{
/**
* Called on the main thread of the process to report that a new multi chat room
has been created.
*
* @param roomId multi user chat room ID
*/
void onChatRoomCreated(String roomId);
/**
* Called on the main thread of the process to report that an existing multi chat

room has been removed from local database.


*
* @param roomId multi user chat room ID
*/
void onChatRoomRemoved(String roomId);
/**
* Called on the main thread of the process to report that chat activity occurs.
*
* @param roomId multi user chat room ID
* @param lastUpdateTime last chat time
*/
void onLastUpdateTimeChanged(String roomId, Date lastUpdateTime);
/**
* Called on the main thread of the process to report that chat room name is
updated.
*
* @param roomId multi user chat room ID
* @param newName the updated chat room name
*/
void onGroupNameChanged(String roomId, String newName);
/**
* Called on the main thread of the process to report that chat room icon is
updated.
*
* @param roomId multi user chat room ID
*/
void onGroupImageChanged(String roomId);
/**
* Called on the main thread of the process to report that chat room theme id is
updated.
*
* @param roomId multi user chat room ID
* @param themeId The theme Id of chat room, which is defined by client side. Just
a string value to let client side setup corresponding theme for chat room.
*/
void onGroupThemeChanged(String roomId, String themeId);
/**
* Called on the main thread of the process to report that an new participant has
been invited into chat room.
*
* @param roomId multi user chat room ID
* @param joinedMember related participant
*/
void onMemberJoined(String roomId, IM800MultiUserChatRoomParticipant
joinedMember);
/**
* Called on the main thread of the process to report that an existing participant

has been left from chat room.


*
* @param roomId multi user chat room ID
* @param leftMember related participant
*/
void onMemberLeft(String roomId, IM800MultiUserChatRoomParticipant leftMember);
/**
* Called on the main thread of the process to report that one participant has
been promoted to administrator.
* Called on the main thread of the process to report that one participant has
been demoted to member.
*
* @param roomId multi user chat room ID
* @param member related participant
*/
void onRoleChanged(String roomId, IM800MultiUserChatRoomParticipant member);
/**
* Called on the main thread of the process to report that current user has been
left from chat room.
*
* @param roomId multi user chat room ID
*/

void onCurrentUserLeft(String roomId);


}

We recommend that you keep the reference object of the listener, since developer needs it to stop related monitoring.
To stop monitoring MUC Activity, please invoke removeChatRoomListener() to stop monitor MUC activity.

/**
* Unregister a multi user chat room listener.
*
* @param listener a listener previously registered
* @throws NullPointerException if listener is null
*/
void removeChatRoomListener(IM800MultiUserChatRoomListener listener);

We recommend that, if developers don't need to monitoring MUC Activity any more, please don't forget invoke removeChatRoomListener() to
stop monitoring.
To stop all SUC Activity monitoring, please invoke clearChatRoomListeners() to stop monitor all SUC activity.

/**
* Unregister all multi user chat room listeners.
*/
void clearChatRoomListeners();

Retrieve Multi User Chat Room(MUC)


To retrieve all MUC, please invoke getChatRooms(), this method will query from local database with the sequence descending order of last chat
time, and return full list of MUC model objects.

/**
* Get all multi user chat rooms.
*
* @return list of multi user chat room.
*/
List<IM800MultiUserChatRoom> getChatRooms();

To retrieve specified MUC model objects, please invoke getChatRoomById().

/**
* Obtain specific multi user chat room.
*
* @param roomId multi chat room ID
* @return multi user chat room if found, null otherwise.
*/
IM800MultiUserChatRoom getChatRoomById(String roomId);

Since the above retrieval methods are related to database query action, we recommend that, developer should invoke these methods in a

background thread, thus avoid blocking the main thread.

Retrieve Participants In Multi User Chat Room(MUC)


To retrieve full list of active members in specified MUC, please invoke getMembers().

/**
* Get active participants whose role are {@link
com.m800.sdk.chat.muc.IM800MultiUserChatRoomParticipant.Role#Member} in a multi user
chat room.
*
* @param roomId multi user chat room ID
* @return list of all active participants whose role are {@link
com.m800.sdk.chat.muc.IM800MultiUserChatRoomParticipant.Role#Member}
*/
List<IM800MultiUserChatRoomParticipant> getMembers(String roomId);

To retrieve full list of active administrators in specified MUC, please invoke getAdministrators().

/**
* Get active participants whose role are {@link
com.m800.sdk.chat.muc.IM800MultiUserChatRoomParticipant.Role#Admin} in a multi user
chat room.
*
* @param roomId multi user chat room ID
* @return list of all active participants whose role are {@link
com.m800.sdk.chat.muc.IM800MultiUserChatRoomParticipant.Role#Admin}
*/
List<IM800MultiUserChatRoomParticipant> getAdministrators(String roomId);

To retrieve participants by JID, please invoke getAdministrators().

/**
* Find a participant, which is already joined a multi user chat room or joined some
time in the past.
*
* @param jid JID the unique identifier of an M800 user
* @param roomId multi user chat room ID
* @return participant if found, null otherwise.
*/
IM800MultiUserChatRoomParticipant findParticipant(String jid, String roomId);

Multi User Chat Room(MUC) Synchronization


When you reinstall the application, you may lost all of the MUC data in local database. So, you need this API to recover all of the MUC data
(message is not included). Please invoke syncData().

/**
* Request to start group chat room data synchronization task.
* <p>
*
If synchronization task is executed once, and force is not set to true, no
synchronization task will be executed.
*
Only one synchronization task will be executed at one time, no duplicate
request allowed.
* </p>
*
* @param force force update
*/
void syncData(boolean force);

To determine when developers need to invoke sync() to trigger MUC synchronisation task, invoke isDataSynced():

/**
* Indicates whether multi user chat room data synchronization task is finished or
not.
*
* @return whether the multi user chat room data synchronization task is finished or
not
*/
boolean isDataSynced();

To check if the MUC synchronization task is running, invoke isDataSyncing():

/**
* Indicates whether multi user chat room data synchronization task is running or not.
*
* @return whether multi user chat room data synchronization task is running or not.
*/
boolean isDataSyncing();

If you want to trigger MUC synchronization task for specific MUC, invoke syncData():

/**
* Request to start single MUC synchronization task.
*
* @param roomId
multi chat room ID
* @param callback an asynchronous callback of MUC synchronization result, {@link
SyncMultiUserChatRoomCallback#complete(String)} method will be called if the request
is success, otherwise {@link SyncMultiUserChatRoomCallback#error(String,
M800ChatRoomError, String)} method will be called.
*/
void syncData(String roomId, SyncMultiUserChatRoomCallback callback);

/**
* Callback for use with {@link IM800MultiUserChatRoomManager#syncData(String,
SyncMultiUserChatRoomCallback)} to get the request result.
*/
interface SyncMultiUserChatRoomCallback {
/**
* Called when MUC synchronization is finished without error.
*
* <p>This callback is called on application's main thread.</p>
*
* @param roomId multi chat room ID
*/
void complete(String roomId);

/**
* Called when MUC synchronization is finished with error.
*
* <p>This callback is called on application's main thread.</p>
*
* @param roomId multi chat room ID
* @param error simplified error result
* @param message detail error result
*/
void error(String roomId, M800ChatRoomError error, String message);
}

Multi User Chat Room(MUC) Participants Management


As an administrator, you can invite more users to the chat room by calling inviteMembers():

/**
* Invite members to join a specific chat
room.
*
* @param roomId
multi chat room ID
* @param jids
JID the unique identifier of an M800 user, the members will be
invite.
* @param callback an asynchronous callback of invite member result, {@link
InviteMembersCallback#complete(String, String[])} method will be called if
the request is success, otherwise {@link InviteMembersCallback#error(String,
String[], M800ChatRoomError, String)} method will be called.
*/
void inviteMembers(String roomId, String[] jids,
InviteMembersCallback callback);

/**
* Callback for use with {@link IM800MultiUserChatRoomManager#inviteMembers(String,
String[], InviteMembersCallback)} to get the request result.
*/
interface InviteMembersCallback {
/**
* Called when invite member is finished without error.
*
* <p>This callback is called on application's main thread.</p>
*
* @param roomId multi chat room ID
* @param jids JID the unique identifier of an M800 user
*/
void complete(String roomId, String[] jids);

/**
* Called when invite member is finished with error.
*
* <p>This callback is called on application's main thread.</p>
*
* @param roomId multi chat room ID
* @param jids JID the unique identifier of an M800 user
* @param error simplified error result
* @param message detail error result
*/
void error(String roomId, String[] jids, M800ChatRoomError error, String message);
}

As an administrator, you can force specific user to leave the chat room by invoking kickMember():

/**
* Force members leave the specific chat room.
*
* @param roomId
multi chat room ID
* @param jid
JID the unique identifier of an M800 user, the member will be kick.
* @param callback an asynchronous callback of leave member result, {@link
KickMemberCallback#complete(String, String)} method will be called if the request is
success, otherwise {@link KickMemberCallback#error(String, String, M800ChatRoomError,
String)} method will be called.
*/
void kickMember(String roomId, String jid, KickMemberCallback callback);

Upon successful request, kicked users will no longer be able to chat in the room. However, they are still able to read old messages stored in the
chat room.

/**
* Callback for use with {@link IM800MultiUserChatRoomManager#kickMember(String,
String, KickMemberCallback)} to get the request result.
*/
interface KickMemberCallback {
/**
* Called when kick member is finished without error.
*
* <p>This callback is called on application's main thread.</p>
*
* @param roomId multi chat room ID
* @param jid JID the unique identifier of an M800 user
*/
void complete(String roomId, String jid);
/**
* Called when kick member is finished with error.
*
* <p>This callback is called on application's main thread.</p>
*
* @param roomId multi chat room ID
* @param jid JID the unique identifier of an M800 user
* @param error simplified error result
* @param message detail error result
*/
void error(String roomId, String jid, M800ChatRoomError error, String message);
}

As an administrator of a chatroom, you can promote or demote other users by calling the API below.

To promote a user in a room to administrator level, invoke promoteMember():

/**
* Promote member to become administrator.
*
* @param roomId
multi chat room ID
* @param jid
JID the unique identifier of an M800 user, the member will be
promote become admin.
* @param callback an asynchronous callback of promote member result, {@link
PromoteMemberCallback#complete(String, String)} method will be called if the request
is success, otherwise {@link PromoteMemberCallback#error(String, String,
M800ChatRoomError, String)} method will be called.
*/
void promoteMember(String roomId, String jid, PromoteMemberCallback callback);

/**
* Callback for use with {@link IM800MultiUserChatRoomManager#promoteMember(String,
String, PromoteMemberCallback)} to get the request result.
*/
interface PromoteMemberCallback {
/**
* Called when promote member is finished without error.
*
* <p>This callback is called on application's main thread.</p>
*
* @param roomId multi chat room ID
* @param jid JID the unique identifier of an M800 user
*/
void complete(String roomId, String jid);

/**
* Called when promote member is finished with error.
*
* <p>This callback is called on application's main thread.</p>
*
* @param roomId multi chat room ID
* @param jid JID the unique identifier of an M800 user
* @param error simplified error result
* @param message detail error result
*/
void error(String roomId, String jid, M800ChatRoomError error, String message);
}

To demote an administrator to a member level, invoke demoteAdministrator():

/**
* Demote administrator to become member.
*
* @param roomId
multi chat room ID
* @param jid
The jid of administrator, the administrator will be demote become
member.
* @param callback an asynchronous callback of demote member result, {@link
DemoteAdministratorCallback#complete(String, String)} method will be called if the
request is success, otherwise {@link DemoteAdministratorCallback#error(String, String,
M800ChatRoomError, String)} method will be called.
*/
void demoteAdministrator(String roomId, String jid, DemoteAdministratorCallback
callback);

/**
* Callback for use with {@link
IM800MultiUserChatRoomManager#demoteAdministrator(String, String,
DemoteAdministratorCallback)} to get the request result.
*/
interface DemoteAdministratorCallback {
/**
* Called when demote administrator without error.
*
* <p>This callback is called on application's main thread.</p>
*
* @param roomId multi chat room ID
* @param jid JID the unique identifier of an M800 user
*/
void complete(String roomId, String jid);
/**
* Called when demote administrator with error.
*
* <p>This callback is called on application's main thread.</p>
*
* @param roomId multi chat room ID
* @param jid JID the unique identifier of an M800 user
* @param error simplified error result
* @param message detail error result
*/
void error(String roomId, String jid, M800ChatRoomError error, String message);
}

Leave Multi User Chat Room(MUC)


If a user wants to leave a specific chat room, invoke leaveRoom():

/**
* Allow current user leave specific chat room.
*
* @param roomId
multi chat room ID
* @param callback an asynchronous callback of leave chat room result, {@link
LeaveRoomCallback#complete(String)} method will be called if the request is success,
otherwise {@link LeaveRoomCallback#error(String, M800ChatRoomError, String)} method
will be called.
*/
void leaveRoom(String roomId, LeaveRoomCallback callback);

Upon successful request, the user will no longer be able to chat in the room. However, they are still able to read old messages stored in the chat
room.

/**
* Callback for use with {@link IM800MultiUserChatRoomManager#leaveRoom(String,
LeaveRoomCallback)} to get the request result.
*/
interface LeaveRoomCallback {
/**
* Called when leave room is finished without error.
*
* <p>This callback is called on application's main thread.</p>
*
* @param roomId multi chat room ID
*/
void complete(String roomId);
/**
* Called when leave room is finished with error.
*
* <p>This callback is called on application's main thread.</p>
*
* @param roomId multi chat room ID
* @param error simplified error result
* @param message detail error result
*/
void error(String roomId, M800ChatRoomError error, String message)
}

Even if you leave the room, you still can retrieve this room from the local database.

To remove the chat room in local database, please invoke deleteChatRoom():

/**
* Delete the chat room and all related data in local database.
*
* @param roomId multi chat room ID
* @return true if this chat room was deleted, false otherwise.
*/
boolean deleteChatRoom(String roomId);

Multi User Chat Room(MUC) Property Management


All participant can enable/disabled mute mode and smart notification. This just a boolean to let client side setup corresponding notification for chat
room.
To enable/disable mute mode, invoke setMuteModeEnabled():

/**
* Enable the mute mode of the chat room.
* This just a boolean to let client side setup corresponding notification for chat
room.
*
* @param roomId multi chat room ID
* @param isMute True if want to enable mute mode, false otherwise
* @param callback an asynchronous callback of enable mute mode result, {@link
SetMuteModeCallback#complete(String, boolean)} method will be called if the request is
success, otherwise {@link SetMuteModeCallback#error(String, M800ChatRoomError,
String)} method will be called.
*/
void setMuteModeEnabled(String roomId, boolean isMute, SetMuteModeCallback callback);

/**
* Callback for use with {@link
IM800MultiUserChatRoomManager#setMuteModeEnabled(String, boolean,
SetMuteModeCallback)} to get the request result.
*/
interface SetMuteModeCallback {
/**
* Called when enable/disable mute mode without error.
*
* <p>This callback is called on application's main thread.</p>
*
* @param roomId multi chat room ID
* @param isMuted True if mute mode is enabled, false otherwise
*/
void complete(String roomId, boolean isMuted);
/**
* Called when enable/disable mute mode with error.
*
* <p>This callback is called on application's main thread.</p>
*
* @param roomId multi chat room ID
* @param error simplified error result
* @param message detail error result
*/
void error(String roomId, M800ChatRoomError error, String message);
}

To enable/disable smart notification mode, please invoke setSmartNotificationEnabled().

/**
* Enable the smart notification of the chat room.
* This just a boolean to let client side setup corresponding notification for chat
room.
*
* @param roomId multi chat room ID
* @param enable True if smart notification is enabled, false otherwise
* @param callback an asynchronous callback of enable smart notification result,
{@link SetSmartNotificationCallback#complete(String, boolean)} method will be called
if the request is success, otherwise {@link SetSmartNotificationCallback#error(String,
M800ChatRoomError, String)} method will be called.
*/
void setSmartNotificationEnabled(String roomId, boolean enable,
SetSmartNotificationCallback callback);

/**
* Callback for use with {@link
IM800MultiUserChatRoomManager#setSmartNotificationEnabled(String, boolean,
SetSmartNotificationCallback)} to get the request result.
*/
interface SetSmartNotificationCallback {
/**
* Called when enable/disable smart notification without error.
*
* <p>This callback is called on application's main thread.</p>
*
* @param roomId multi chat room ID
* @param isEnabled True if smart notification is enabled, false otherwise
*/
void complete(String roomId, boolean isEnabled);
/**
* Called when enable/disable smart notification with error.
*
* <p>This callback is called on application's main thread.</p>
*
* @param roomId multi chat room ID
* @param error simplified error result
* @param message detail error result
*/
void error(String roomId, M800ChatRoomError error, String message);
}

As an administrator, you can manage the chat room properties by using the API below.
To change the name of chat room, invoke changeChatRoomName():

/**
* Send a message to server, request update the name of multi chat room.
*
* @param roomId
multi chat room ID
* @param title
The title of chat room
* @param callback an asynchronous callback of update chat room name result, {@link
ChangeChatRoomNameCallback#complete(String, String)} method will be called if the
request is sent, otherwise {@link ChangeChatRoomNameCallback#error(String, String,
M800ChatRoomError, String)} method will be called.
*/
void changeChatRoomName(String roomId, String title, ChangeChatRoomNameCallback
callback);
/**
* Callback for use with {@link
IM800MultiUserChatRoomManager#changeChatRoomName(String, String,
ChangeChatRoomNameCallback)} to get the request result.
*/
interface ChangeChatRoomNameCallback {
/**
* Called when update chat room name request is sent without error.
*
* <p>This callback is called on application's main thread.</p>
*
* @param roomId multi chat room ID
* @param title The title of chat room
*/
void complete(String roomId, String title);
/**
* Called when update chat room name request is sent with error.
*
* <p>This callback is called on application's main thread.</p>
*
* @param roomId multi chat room ID
* @param title The title of chat room
* @param error simplified error result
* @param message detail error result
*/
void error(String roomId, String title, M800ChatRoomError error, String message);
}

To change the icon of chat room, invoke changeChatRoomIcon():

/**
* Send a message to server, request update the icon of multi chat room.
*
* @param roomId
multi chat room ID
* @param iconBitmap
Image bitmap, size should be smaller than 50KB, will be
recycled after process completed, either success or failure
* @param callback
an asynchronous callback of update chat room icon result,
{@link ChangeChatRoomIconCallback#complete(String)} method will be called if the
request is sent, otherwise {@link ChangeChatRoomIconCallback#error(String,
M800ChatRoomError, String)} method will be called.
*/
void changeChatRoomIcon(String roomId, Bitmap iconBitmap, ChangeChatRoomIconCallback
callback);

/**
* Callback for use with {@link
IM800MultiUserChatRoomManager#changeChatRoomIcon(String, Bitmap,
ChangeChatRoomIconCallback)} to get the request result.
*/
interface ChangeChatRoomIconCallback {
/**
* Called when update chat room icon request is sent without error.
*
* <p>This callback is called on application's main thread.</p>
*
* @param roomId multi chat room ID
*/
void complete(String roomId);
/**
* Called when update chat room icon request is sent with error.
*
* <p>This callback is called on application's main thread.</p>
*
* @param roomId multi chat room ID
* @param error simplified error result
* @param message detail error result
*/
void error(String roomId, M800ChatRoomError error, String message);
}

To change the theme id of chat room, invoke changeChatRoomThemeId():

/**
* Send a message to server, request update the theme id of multi chat room.
*
* @param roomId
multi chat room ID
* @param themeId
The theme Id of chat room, which is defined by client side. Just a
string value to let client side setup corresponding theme for chat room.
* @param callback an asynchronous callback of update chat room theme id result,
{@link ChangeChatRoomThemeIdCallback#complete(String, String)} method will be called
if the request is sent, otherwise {@link ChangeChatRoomThemeIdCallback#error(String,
String, M800ChatRoomError, String)} method will be called.
*/
void changeChatRoomThemeId(String roomId, String themeId,
ChangeChatRoomThemeIdCallback callback);

/**
* Callback for use with {@link
IM800MultiUserChatRoomManager#changeChatRoomThemeId(String,
String, ChangeChatRoomThemeIdCallback)} to get the request result.
*/
interface ChangeChatRoomThemeIdCallback {
/**
* Called when update the theme id
request is sent without error.
*
* <p>This
callback is called on application's main thread.</p>
*
* @param roomId multi chat room ID
* @param themeId
The theme Id of chat room, which is defined by client side.
Just a
string value to let client side setup corresponding theme for chat room.
*/
void complete(String roomId, String themeId);
/**
* Called when update the theme id request
is sent with error.
*
* <p>This
callback is called on application's main thread.</p>
*
* @param roomId multi chat room ID
* @param themeId
The theme Id of chat room, which is defined by client side.
Just a
string value to let client side setup corresponding theme for chat room.
* @param error simplified error result
* @param message detail error result
*/
void error(String roomId, String themeId, M800ChatRoomError error, String
message);

When SDK received server message about MUC icon changed, SDK will build cache for this icon. But, if user clear the app cache, this cache may
also lost. To recover the cache, please invoke buildChatRoomIconCacheFile().

/**
* Trigger a process to rebuild the cache file.
*
* @param roomIds list of multi user chat room ID
* @param callback callback an asynchronous callback of rebuild the cache file result,
{@link BuildChatRoomIconCacheFileCallback#onResult(String[], String[])} method will be
called if the build cache process is finished.
*/
void buildChatRoomIconCacheFile(String[] roomIds, BuildChatRoomIconCacheFileCallback
callback);

/**
* Callback for use with {@link
IM800MultiUserChatRoomManager#buildChatRoomIconCacheFile(String[],
BuildChatRoomIconCacheFileCallback)} to get the process result.
*/
interface BuildChatRoomIconCacheFileCallback {
/**
* Called when build cache process is
finished.
*
* <p>This
callback is called on application's main thread.</p>
*
* @param success list of multi user chat room ID, which is rebuild icon
cache file successfully
* @param failure list of multi user chat room ID, which is rebuild icon
cache file failure, that should be decode image data failure.
*/
void onResult(String[] success, String[] failure)
}

To distinguish if the chat room is missing icon cache or icon not defined, please consider the following code:

List<IM800MultiUserChatRoom> mucItems =
M800SDK.getInstance().getMultiUserChatRoomManager().getChatRooms();
for (IM800MultiUserChatRoom chatRoom : mucItems) {
if (chatRoom.hasRoomIcon() && chatRoom.getRoomIconThumbnail() == null) {
//icon cache is lost, please rebuild.
}
}

System Chat Room


As a starting point...

Please get an instance of IM800SystemChatRoomManager from M800SDK:

IM800SystemChatRoomManager mSystemChatManager =
M800SDK.getInstance().getSystemChatRoomManager();

Monitor System Chat Room Activity


Please invoke addChatRoomListener() to start monitor System Chat Room activity.

/**
* Register a listener that listeners events of system chat room.
*
* @param listener a listener implements {@link IM800SystemChatRoomListener}
* @throws NullPointerException if listener is null
*/
void addChatRoomListener(IM800SystemChatRoomListener listener);

And use the following listener.

/**
* Callback for use with {@link
IM800SystemChatRoomManager#addChatRoomListener(IM800SystemChatRoomListener)} to
monitor the activity of system chat room.
*/
public interface IM800SystemChatRoomListener {
/**
* Called on the main thread of the process to report that system chat room has
been created.
*
* @param roomId single user chat room ID
*/
void onChatRoomCreated(String roomId);
/**
* Called on the main thread of the process to report that chat activity occurs.
*
* @param roomId system chat room ID
* @param lastUpdateTime last chat time
*/
void onLastUpdateTimeChanged(String roomId, Date lastUpdateTime);
}

We recommend that you keep the reference object of the listener, since developer needs it to stop related monitoring.
To stop monitoring System Chat Room Activity, please invoke removeChatRoomListener() to stop monitor System Chat Room activity.

/**
* Unregister a system chat room listener.
*
* @param listener a listener previously registered
* @throws NullPointerException if listener is null
*/
void removeChatRoomListener(IM800SystemChatRoomListener listener);

To stop all System Chat Room Activity monitoring, please invoke clearChatRoomListeners() to stop monitor all System Chat Room activity.

/**
* Unregister all system chat room listeners.
*/
void clearChatRoomListeners();

Retrieve System Chat Room


To retrieve System Chat Room, please invoke getSystemChatRoom().

/**
* Retrieve system chat room object.
*
* @return system chat room object
*/
IM800ChatRoom getSystemChatRoom();

SMS Chat Room


To start with SMS chat room APIs, you need to get IM800SMSChatRoomManager first:

M800SDK.getInstance().getSMSChatRoomManager();

Create SMS Chat Room


To create an SMS chat room, you need to provide a valid phone number with country code, for example, +85255558888.
If the provided phone number isnt start with +, current users country code will be added during chat room creation. For example, if you provide
55558888, and current users phone number is +852xxxxxxxx, +852 will be added, so the phone number used to create SMS chat room
would be +85255558888.

M800SDK.getInstance().getSMSChatRoomManager().createChatRoom("phoneNumber",
new IM800SMSChatRoomManager.CreateSMSChatRoomCallback() {
@Override
public void complete(String roomId, String phoneNumber) {
// Chat room created
}
@Override
public void error(String phoneNumber, M800ChatRoomError error, String
message) {
// Chat room creation failed
}
});

Monitor SMS Chat Room Activity


To monitor activities of SMS chat rooms, implement the following interface:

public interface IM800SMSChatRoomListener {


/**
* Called on the main thread of the process to report that a new SMS chat room has been
created.
*
* @param roomId single user chat room ID
*/
void onChatRoomCreated(String roomId);
/**
* Called on the main thread of the process to report that an existing SMS chat room
* has been removed from local database.
*
* @param roomId single user chat room ID
*/
void onChatRoomRemoved(String roomId);
/**
* Called on the main thread of the process to report that chat activity occurs.
*
* @param roomId SMS user chat room ID
* @param lastUpdateTime last chat time
*/
void onLastUpdateTimeChanged(String roomId, Date lastUpdateTime);
}

You can register the chat room events listener to a one SMS chat room or all:

// Listen to SMS chat room events of a specific room


M800SDK.getInstance().getSMSChatRoomManager().addChatRoomListener("RoomID",
chatRoomListener);
// Listen to all SMS chat rooms' events
M800SDK.getInstance().getSMSChatRoomManager().addChatRoomListener(chatRoomListener);

Retrieve SMS Chat Room


To get all SMS chat rooms:

mSMSChatRoomManager.getChatRooms();

To find a SMS chat room by room ID:

mSMSChatRoomManager.getChatRoomById(roomID);

Delete SMS Chat Room


To delete an SMS chat room and all its messages:

mSMSManager.deleteChatRoom(roomID);

Retrieve Chat Participants in SMS Chat Room


To get chat participants in an SMS chat room:

String currentUserPhoneNumber = M800SDK.getInstance().getUsername();


List<IM800SMSChatRoomParticipant> participants =
mSMSChatRoomManager.getParticipants("chatRoomID");
for (IM800SMSChatRoomParticipant participant : participants) {
if (TextUtils.equals(currentUserPhoneNumber, participant.getPhoneNumber())) {
// Current user as chat participant
} else {
// The other party as chat participant
}
}

Messaging
Introduction
User can send and receive various types of M800 chat messages in chat rooms.
M800 chat message contains the following key attributes:
Message ID: A unique identifier of a M800 chat message
Room ID: An M800 chat rooms ID where the chat message belongs to.
Direction: Either incoming or outgoing.
Status: For incoming messages, the status could be read or unread. For outgoing messages, the status could be processing, delivering,
delivered, delivery failed, server received, client received.
Content Type: Can be text, audio, image, ephemeral image, video or system notifications like member join, member promote, etc.
Location: User can choose to share his/her location in a message by simply providing latitude and longitude.

To start messaging, get the IM800ChatMessageManager first:

M800SDK.getInstance().getChatMessageManager();

Send text message


The following code demos how to send a text message in a chat room with location. Please make sure the chat room ID is valid and the text is not
null or empty.
Note: Location is optional for all kinds of messages, so it is allowed to pass a null location. It means sending message without location.

//Do this in a background thread


String roomID = "<Your room ID>";
String text = "<Message Text, cannot be empty>";
M800MessageLocation location = new M800MessageLocation(latitude, longitude);
M800ChatRoomError result =
M800SDK.getInstance().getChatMessageManager().sendTextMessage(roomID, text, location);
if (result == M800ChatRoomError.NO_ERROR) {
// Successfully sent
} else {
// Failed
}

Send SMS message


You can use the same API in Send text message section to send SMS messages in an SMS chat room.
If you are sending text via SMS and your input text is very long. You messages will be separated into several SMS messages to send. By default,
the maximum length of a single ASCII char SMS message is 130. The maximum length of a single UNICODE chat SMS message is 65.
If your text is separated into several SMS messages, by default, the maximum length of every ASCII char SMS message is 122. The maximum
length of every UNICODE char SMS message is 61.
M800 server may change the limitation.

Send audio message


The following code demos how to send an audio message in a chat room with location. Please make sure the chat room ID and the audio file are
valid. The audio files duration should be limited to 1 second to 3 minutes. To be compatible with iOS platform, the audio file should be in M4A
format.

//Do this in a background thread


String roomID = "<You chat room ID>";
File audioFile = <Your audio file>;
float audioDuration = <You audio duration>;
M800MessageLocation location = new M800MessageLocation(latitude, longitude);
M800ChatRoomError result =
M800SDK.getInstance().getChatMessageManager().sendAudio(roomID, audioFile,
audioDuration, location,
new IM800FileTransferListener() {
@Override
public void transferStarted(String filePath, long fileSize) {
// Starts to transfer audio file to M800 server
}
@Override
public void transferred(long transferredBytes, long fileSize) {
// Progress update
}
@Override
public void transferFinished(int code, String url, String localPath) {
// Audio file transfer finished
}
@Override
public void transferFailed(int code, String localPath) {
// Audio file transfer failed
}
});
if (result == M800ChatRoomError.NO_ERROR) {
// All the parameters are valid and message will be sent
} else {
// Has invalid parameter
}

IM800FileTransferListener.transferFailed could be invoded with the following error code:


Error Code

Description

-1

Media transfer finished, but failed to send message due to exception.

7001

The same file is uploading.

7002

HTTP exception.

7003

Upload file request failed.

7401

Host not found.

7900

Upload file request has been rejected. (One possible reason is


current user is the only member left in a group chat room)

7901

Feature not supported.

others

HTTP erros, please refer to java.net.HttpURLConnection.

Send image message


The following code demos how to send an image message in a chat room with location. Please make sure the chat room ID and the image file are
valid. The image thumbnail is an optional item. If its provided, the thumbnail will be sent along with message and the recipient can get a preview
of the image.
Note that M800SDK will save the thumbnail in local cache folder once the message is received. You can get its path via IM800MediaChatMessag
e.getThumbnailPath() method. It is possible that user or other APPs will delete the cached thumbnails later. If this happens, you can generate a
new thumbnail yourself via the original file you get from IM800MediaChatMessage.getMediaFileURL().

// Do this in a background thread


String roomID = "<You chat room ID>";
File imageFile = <Your image file>;
Bitmap imageThumbnail = <You image thumbnail>;
M800MessageLocation location = new M800MessageLocation(latitude, longitude);
M800ChatRoomError result =
M800SDK.getInstance().getChatMessageManager().sendImage(roomID, imageFile,
imageThumbnail, location,
new IM800FileTransferListener() {
@Override
public void transferStarted(String filePath, long fileSize) {
// Starts to transfer image file to M800 server
}
@Override
public void transferred(long transferredBytes, long fileSize) {
// Progress update
}
@Override
public void transferFinished(int code, String url, String localPath) {
// Image file transfer finished
}
@Override
public void transferFailed(int code, String localPath) {
// Image file transfer failed
}
});
if (result == M800ChatRoomError.NO_ERROR) {
// All the parameters are valid and message will be sent
} else {
// Has invalid parameter
}

Send video message


The following code demos how to send a video message in a chat room with location. Please make sure the chat room ID and the video file are
valid. The video file size should be smaller than 200MB and it should be in MP4 format. The video thumbnail is an optional item. If its provided,
the thumbnail will be sent along with message and the recipient can get a preview of the video.

//Do this in a background thread


String roomID = "<You chat room ID>";
File videoFile = <Your video file>;
float videoDuration = <Your video duration>;
Bitmap videoThumbnail = <You video thumbnail>;
M800MessageLocation location = new M800MessageLocation(latitude, longitude);
M800ChatRoomError result =
M800SDK.getInstance().getChatMessageManager().sendVideo(roomID, videoFile,
videoDuration, videoThumbnail, location,
new IM800FileTransferListener() {
@Override
public void transferStarted(String filePath, long fileSize) {
// Starts to transfer video file to M800 server
}
@Override
public void transferred(long transferredBytes, long fileSize) {
// Progress update
}
@Override
public void transferFinished(int code, String url, String localPath) {
// Video file transfer finished
}
@Override
public void transferFailed(int code, String localPath) {
// Video file transfer failed
}
});
if (result == M800ChatRoomError.NO_ERROR) {
// All the parameters are valid and message will be sent
} else {
// Has invalid parameter
}

Send ephemeral message


The following code demos how to send an ephemeral message in a chat room with location.
Because M800 server will not store an ephemeral messages data, you must provide a bitmap instead of file and an integer value indicates the
live time of this ephemeral message in seconds.

//Do this in a background thread


String roomID = "<You chat room ID>";
Bitmap ephemeralImage = <You ephemeral image>;
int ttl = <ephemeral TTL in seconds>;
M800MessageLocation location = new M800MessageLocation(latitude, longitude);
M800ChatRoomError result =
M800SDK.getInstance().getChatMessageManager().sendEphemeral(roomID, ephemeralImage,
ttl, location);
if (result == M800ChatRoomError.NO_ERROR) {
// Successfully sent
} else {
// Failed
}

Register message listener


You need to register a message listener to listener to events including
New outgoing chat message received
New incoming chat message created
Data update of an existing chat message

The following code demos an implementation of chat message listener:

private class ChatMessageListener implements IM800ChatMessageManager.Listener {


@Override
public void onNewIncomingChatMessage(IM800ChatMessage chatMessage) {
// Update UI
}
@Override
public void onNewOutgoingChatMessage(IM800ChatMessage chatMessage) {
// Update UI
}
@Override
public void onChatMessageDataChanged(String messageID, Bundle changedValues) {
// Update message data if needed
}
}

The following code demos how to add and remove a chat message listener:

M800SDK.getInstance().getChatMessageManager().addChatMessageListener(mRoomId,
mMessageListener);
M800SDK.getInstance().getChatMessageManager().removeChatMessageListener(mMessageListen
er);

If onChatMessageDataChanged(messageID, bundle) callback is called, that means an existing M800 messages data has been updated. If you
have an instance of IM800ChatMessage that has the same messageID which you get from onNewIncomingChatMessage(message) or onNewOu

tgoingChatMessage(chatMessage)or M800SDK.getInstance().getChatMessageManager().getChatMessage(messageID), you can apply the


bundle to the IM800ChatMessage instance and update its data.

IM800ChatMessage chatMessage = <You chat message>;


chatMessage.updateData(changedValues);

Set media file upload progress listener


Media type chat message includes audio, video and image chat messages. You can set media file upload progress listener to a media chat
message anytime. Only one listener can be set at one time. You can set null to clear previously registered listener.

M800SDK.getInstance().getChatMessageManager().setMediaFileTransferListener("messageID"
, <Implementation of IM800FileTransferListener>);

Get historical chat messages and statistics


There are multiple APIs in IM800ChatMessageManager to get older chat messages, you may choose to use one of the following codes base on
your needs.

/**
* Get chat message with ID.
*
* @param messageID chat message ID
* @return chat message, null if not found
* @throws IllegalArgumentException
*/
IM800ChatMessage getChatMessage(String messageID);

/**
* Get last chat messages in a chat room.
*
* @param roomID chat room ID
* @return last chat message, if no room is found with the roomID, null will be
returned
* @throws IllegalArgumentException
*/
IM800ChatMessage getLastChatMessage(String roomID);

/**
* Get chat messages in a chat room.
*
* @param roomID chat room ID
* @param limit maximum count of chat messages that will return
* @param dateOrderDesc if set to true, chat messages will be ordered by date DESC,
otherwise date ASC
* @return list of chat messages
* @throws IllegalArgumentException
*/
List<IM800ChatMessage> getChatMessages(String roomID, int limit, boolean
dateOrderDesc);

/**
* Get chat messages in a chat room.
*
* @param roomID chat room ID
* @param limit maximum count of chat messages that will return
* @param fromDate if dateOrderDesc is set to true, will only return chat messages
earlier(include) than this date;
*
if dateOrderDesc is set to false, will only return chat messages
later(include) than this date
* @param dateOrderDesc if set to true, chat messages will be ordered by date DESC,
otherwise date ASC
* @return list of chat messages
* @throws IllegalArgumentException
*/
List<IM800ChatMessage>
getChatMessages(String roomID, int limit, Date fromDate, boolean dateOrderDesc);

/**
* Get chat messages in a chat room.
*
* @param roomID chat room ID
* @param limit maximum count of chat messages that will return
* @param messageID if dateOrderDesc is set to true, will only return chat messages
earlier than this message;
*
if dateOrderDesc is set to false, will only return chat messages
later than this message
* @param dateOrderDesc if set to true, chat messages will be ordered by date DESC,
otherwise date ASC
* @return list of chat messages
* @throws IllegalArgumentException
*/
List<IM800ChatMessage> getChatMessages(String roomID, int limit, String messageID,
boolean dateOrderDesc);

There are APIs in IM800ChatMessageManager that are able to get the number of chat messages in a chat room and unread chat rooms count.

/**
* Get chat messages count in a chat room.
*
* @param roomID chat room ID
* @return chat messages count, if no room is found with the roomID, 0 will be
returned
* @throws IllegalArgumentException
*/
int getChatMessagesCount(String roomID);
/**
* Get unread chat messages count in a chat room.
*
* @param roomID chat room ID
* @return unread chat messages count, if no room is found with the roomID, 0 will be
returned
* @throws IllegalArgumentException
*/
int getUnreadChatMessagesCount(String roomID);
/**
* Get unread chat messages count of all chat rooms.
*
* @return unread chat messages count of all chat rooms
*/
int getUnreadChatMessagesCount();
/**
* Get number of chat rooms that has unread messages.
*
* @return number of chat rooms that has unread messages
*/
int getUnreadChatRoomsCount();

Retrieve message data


After retrieve chat messages from message listeners or chat message manager in section 7 and 8, and get the common data of all types of chat
message through the getters of IM800ChatMessage interface, you probably need to retrieve the data of a specific content type. To do so, cast the
message to sub interfaces of IM800ChatMessage.

IM800ChatMessage chatMessage = <You chat message>;


if (chatMessage instanceof IM800TextChatMessage) {
// Text message, do this on any thread
IM800TextChatMessage textChatMessage = (IM800TextChatMessage) chatMessage;
String text = textChatMessage.getText();
// TODO Deal with the text, do this on any thread
} else if (chatMessage instanceof IM800MediaChatMessage) {
// Audio, image, video message, do this on any thread
IM800MediaChatMessage mediaChatMessage = (IM800MediaChatMessage) chatMessage;
String mediaURL = mediaChatMessage.getMediaFileURL();
// TODO Deal with the URL
} else if (chatMessage instanceof IM800EphemeralChatMessage) {
// Ephemeral message, do this on background thread
IM800EphemeralChatMessage ephemeralChatMessage = (IM800EphemeralChatMessage)
chatMessage;
long TTL = ephemeralChatMessage.getTTL();
byte[] imageByteArray =
M800SDK.getInstance().getChatMessageManager().getEphemeralImageBitmapArray(chatMessage
.getMessageID());
// TODO Deal with image byte array, convert it to bitmap if needed
} else if (chatMessage instanceof IM800SMSChatMessage) {
// SMS message, do this on any thread
IM800SMSChatMessage smsChatMessage = (IM800SMSChatMessage) chatMessage;
String recipientPhoneNumber = smsChatMessage.getRecipientPhoneNumber();
// Cost of this SMS message
double cost = smsChatMessage.getCost();
// SMS count in this message
int totalMessageCount = smsChatMessage.getMessageCount();
// Sent SMS count, should be less than or equal to <totalMessageCount>
int successfullySentCount = smsChatMessage.getSentCount();
// Error occurred during SMS sending,
// check this if <successfullySentCount> is less than <totalMessageCount>
IM800SMSChatMessage.SMSError error = smsChatMessage.getError();
} else {
// System notification message, do this on any thread
IM800ChatMessage.ContentType contentType = chatMessage.getContentType();
// TODO Deal with the content type
}

In multi-user chat room, except from normal messages like text or media messages, user will also receive some system notification messages.
The following code demonstrate how to read a system notification message:

IM800ChatMessage chatMessage = <A chat message>;


switch (chatMessage.getContentType()) {
case GroupChatJoined:
// A new member has joined
String newMemberJID = chatMessage.getSenderJID();
break;
case GroupChatLeft:
// A member/admin has left
String leftJID = chatMessage.getSenderJID();
break;
case GroupChatRoleAdmin:
// A member has been promoted to admin
String promotedJID = chatMessage.getSenderJID();
break;
case GroupChatRoleMember:
// An admin has been demoted to member
String demotedJID = chatMessage.getSenderJID();
break;
case GroupChatTheme:
case GroupChatImage:
case GroupChatSubject:
// Chat room's attribute has changed
String whoChanged = chatMessage.getSenderJID();
break;
}

Manage ephemeral message


To get ephemeral messages image byte array data, user the following API in IM800ChatMessageManager. You can use the byte array to
generate a bitmap and show to user.

/**
* Get image bitmap array in an ephemeral chat message.
*
* @param messageID ephemeral chat message ID
* @return ephemeral message's image in byte array,
* null if the message is not found, or not ephemeral message, or ephemeral image is
already timeout
* @throws IllegalArgumentException if messageID is null or empty
*/
byte[] getEphemeralImageBitmapArray(String messageID);

After showing an ephemeral messages image to user, you should start a timer to count the display time. If the messages time to live (TTL) valu
e is reached, you should clear ephemeral messages data and set its time to live value to zero so that the user cannot see this message anymore.
To do so, call the following APIs in IM800ChatMessageManager.

/**
* Set an ephemeral chat message's time to live value.
*
* <p>When an ephemeral message's TTL is set to 0,
* you should also call {@link #removeEphemeralMessageImage(String)} to clear its
image data.</p>
*
* @param messageID ephemeral chat message ID
* @param TTL time to live, should be greater than or equal to 0
* @return true if set TTL successfully, otherwise false
* @throws IllegalArgumentException if messageID is null or empty
*/
boolean setEphemeralMessageTTL(String messageID, @Nonnegative int TTL);

/**
* Remove image data stored in an ephemeral chat message.
*
* <p>Next time when {@link #getEphemeralImageBitmapArray(String)} is called, it will
return null.</p>
*
* @param messageID ephemeral chat message ID
* @return true if remove ephemeral image successfully, otherwise false
* @throws IllegalArgumentException if messageID is null or empty
*/
boolean removeEphemeralMessageImage(String messageID);

Remove chat messages


The following code demos how to remove a chat message knowing its message ID.

private
class RemoveMessageTask extends AsyncTask<String, Void, Boolean> {
@Override
protected Boolean doInBackground(String... params) {
String messageID = params[0];
return M800SDK.getInstance().getChatMessageManager().removeMessage(messageID)
> 0;
}
@Override
protected void onPostExecute(Boolean isSuccess) {
if (isSuccess) {
// Update UI
}
}
}

The following code demos how to remove all (non-system) chat messages in a chat room.

private
class RemoveMessageTask extends AsyncTask<String, Void, Void> {
@Override
protected Void doInBackground(String... params) {
String roomID = params[0];
M800SDK.getInstance().getChatMessageManager().removeAllMessagesInRoom(roomID);
// OR
M800SDK.getInstance().getChatMessageManager().removeAllNonSystemChatMessages(roomID);
return null;
}
}

Forward chat message


User can forward a text, SMS, location, image, audio or video chat message into a single user chat room or multi-user chat room.
User can forward a text or SMS chat message into an SMS chat room.
If the forwarded message is an outgoing message, its status cannot be OutgoingProcessing, OutgoingDelivering nor OutgoingDeliveryFailed
.

M800ChatRoomError forwardChatMessage(String messageID, String chatRoomID);

Read chat message


If an incoming chat message is read by the user, M800SDK provides APIs for you send display receipts to the sender so that the sender knows
his/her message is read.
To implement this feature in your app, after user enters a chat room and reads the incoming chat messages inside, you need to mark the
messages as read so that displayed receipt can be sent correctly.

private
class MarkChatMessageAsReadTask extends AsyncTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... params) {
// Mark chat messages as read
M800SDK.getInstance().getChatMessageManager().markAllChatMessagesAsRead(mRoomId);
// Then can send displayed receipt so others
// know user have read the messages
M800SDK.getInstance().getChatMessageManager().sendDisplayedReceipt(mRoomId);
return null;
}
}

If user doesnt connect to M800 server when he reads the chat messages, you should still mark the messages as read and call the following API
in IM800ChatMessageManager to resend all display receipts when connected.

/**
* Resend all displayed receipts that failed to send before.
*
* <p>If chat messages are marked as read correctly
* and {@link #sendDisplayedReceipt(String)} is never been called,
* will send displayed receipts for all chat rooms if needed.</p>
*/
void resendDisplayedReceipts();

Send chat state


If the current user's the typing state of in a chat room should be notified to other participants, you may send the IM800ChatMessageManager.Cha
tState to the corresponding chat room.

/**
* Send chat state in a chat room.
*
* <p>Chat state message tells other chat participants whether user is typing or not.
* Don't send {@link ChatState#Composing} state too frequently if user keeps typing,
* recommended interval is 2 seconds.</p>
*
* @param roomID chat room ID, if no room is found with this ID, nothing will be sent
* @param state the {@link ChatState} chat state
* @return error with code {@link M800ChatRoomError#NO_ERROR} if message is sent,
* otherwise see {@link M800ChatRoomError}
* @throws IllegalArgumentException
*/
M800ChatRoomError sendChatState(String roomID, ChatState state);

Monitor chat state changes


You can apply add the listener IM800ChatMessageManager.ChatStateListener to the IM800ChatMessageManager instance if you want to know
the other participants in the chat room are typing.
You should firstly implement your M800ChatMessageManager.ChatStateListener object. See,

/**
* Implement this listener to listen all {@link ChatState} events in a chat room.
*/
interface ChatStateListener {
/**
* The event will be triggered when the chat state of a chat room changed
*
* @param roomId the roomId of the chat room.
* @param jid
the JID of chat participant who triggers the event.
* @param state the state of the chat participant.
*/
void onChatStateChanged(String roomId, String jid, ChatState state);
}

And then, add the listener to the IM800ChatMessageManager instance by invoking the below method.

/**
* Add a chat state listener that listens to chat state event of the chat room with
provided roomID.
*
* @param roomID chat room id
* @param listener chat state listener
* @throws IllegalArgumentException if roomID or listener is null
*/
void addChatStateListener(String roomID, ChatStateListener listener);

Credit Module
Introduction to Credit Module
The credit module provides simple APIs to get the credit information of the current user. The application may also listen for the instant credit
update events through the credit module.

Pre-requisites
User must have signed up on the application before getting the credit information. User credit information can be provided only if the project
provision supports user wallet feature. Please confirm this with M800 project managers.

How to Implement
In this section, we introduce the details on how to implement and use the credit module.
Get the IM800CreditManager instance. You may invoke M800SDK.getInstance().getCreditManager().

IM800CreditManager creditInfo = M800SDK.getInstance().getCreditManager();

The information IM800CreditManager provides are listed below:


The current balance
The currency of balance
The balance expiration timestamp
The current credit status
The current user account status
IM800CreditManager provides APIs to get the above information. For example, to get the current balance, invoke IM800CreditManager.get
Balance().

//To get the IM800CreditManager instance.


IM800CreditManager creditManager = M800SDK.getInstance().getCreditManager();
//To get the current balance.
double balance = creditManager.getBalance();

The class MainActivity.java of demo app demonstrates the usage of the APIs. You may also see the Java Documentation of IM800CreditM
anager for full description.
Note. IM800CreditManager provides the credit information only when user has signed up to the M800 server.

To listen for the credit update events from IM800CreditManager, please implement IM800CreditListener. Pass the implemented IM800Cr
editListener object to IM800CreditManager by invoking IM800CreditManager.addCreditListener(listener).
ApplicationClass.java of the demo app demonstrates how to add the IM800CreditListener listener:

public class ApplicationClass extends MultiDexApplication implements


IM800CreditManager.IM800CreditListener{
@Override
public void onCreate() {
super.onCreate();
//Add IM00CreditListener.
M800SDK.getInstance().getCreditManager().addCreditListener(this);
}
@Override
public void onCreditUpdated(IM800CreditManager creditInfo) {
//Implementation of your own logic.
}
}

To remove the IM800CreditListener listener from IM800CreditManager, please invoke IM800CreditManager.removeCreditListener(listene


r).

Contact Management
Introduction
After user finds some M800 users by phone number, location or recommendation, he/she can add them as his/her M800 contact. Later if the user
swaps device or reinstalls the app, he/she can retrieve M800 contacts added this way automatically after contact sync.

How to implement
Add Contact
User can add an M800 user into his/her contact list providing the JID.
You should check validity of the JID before calling this API (See Find User section).

M800SDK.getInstance().getContactManager().addM800Contact(JID, addOrRemoveCallback);

Remove contact
User can remove contacts added, only by using the API above. The M800 contacts found in users native address book cannot be removed using
this API because they are linked to native contacts.
However, user can go to native address book app and remove the native contact there. After contact sync in M800SDK, the associated M800
contact will be removed automatically.

M800SDK.getInstance().getContactManager().removeM800Contact(JID, addOrRemoveCallback);

Add or Remove Contact Callback


If an implementation of AddOrRemoveContactCallback is provided in the above API calls, it will be triggered when the contact adding or removal
finished.
onComplete will be called if the request is executed successfully. If contact roster is started, and a listener is registered to M800ContactM
anager, onContactChanged will be called.
onError will be called if the request failed and detail error information will be provided.

interface AddOrRemoveContactCallback {
void onComplete(String JID);
void onError(String JID, M800Error error);
}

Rate Table Module


Introduction
The rate table module provides an API to get a list of call and sms rates for different call destinations.

Pre-requisites
The user has signed in.

How to implement
To retrieve an instance of the RateManager:
Retrieve an instance of the IM800RateManager, like so:

IM800RateManager mM800RateManager = M800SDK.getInstance().getRateManager();

To listen for change event in the Rate Table:


Create a listener by extending IM800RateManager.IM800RateTableListener:

private IM800RateManager.IM800RateTableListener m800RateTableListener = new


IM800RateManager.IM800RateTableListener() {
@Override
public void onRateTableUpdated(IM800RateManager rateManager) {
//Your implementation
}
};

Then, add the listener to the Rate Manager:

mM800RateManager.addRateTableListener(m800RateTableListener);

To update the RateManagers data from server:


Request an update on the rate table, as follows:

mM800RateManager.update(context);

Note:
1. The updated result notifies the application ONLY if you have listen for the rate table event by IM800RateTableListener.
2. No operation would be started if there is no update in the RateManager.

To check if the RateManagers data is up-to-date:


Invoke the below method to check if update is required.

Boolean needUpdate = mM800RateManager.needUpdate();

To retrieves rates:
Call getRateInfoItems on the RateManager and specify the type.
For SMS, pass in IM800RateManager.ChargingRateType.SMS as parameter:

String language = "<App language>"; //en, zh_cn, zh


List<IM800CountryRateInfo> smsList =
mM800RateManager.getRateInfoItems(IM800RateManager.ChargingRateType.SMS, language);

For Offnet Call, pass in IM800RateManager.ChargingRateType.OFFNET_CALL as parameter:

String language = "<App language>"; //en, zh_cn, zh


List<IM800CountryRateInfo> offnetList =
mM800RateManager.getRateInfoItems(IM800RateManager.ChargingRateType.OFFNET_CALL,
language);

To retrieve the rates with keyword filter. (Search by country name or country code)

String language = "<App language>"; //en, zh_cn, zh


String keyword = "<keyword>";
IM800RateManager.ChargingRateType type = <IM800RateManager.ChargingRateType>;
List<IM800CountryRateInfo> offnetList = mM800RateManager.getRateInfoItems(keyword
,IM800RateManager.ChargingRateType.OFFNET_CALL, language);

Note: You should never invoke the above API on the UI thread. This method requires database reading which may block the UI thread tasks. The
class RateInfoListFragment.java of demo app demonstrates how to get rate list.

Find User Module


Introduction
The Find User module in the m800SDK provides functionality to query other m800 users profile.

How to Implement
As a starting point, from M800SDK, get an instance of IM800FindUserManager.

private IM800FindUserManager mFindUserManager =


M800SDK.getInstance().getFindUserManager();

If the method above returns null, user hasnt signed up. Sign up is necessary before using M800SDK.

Find user by phone number/JID


To query user by phone number from server, please invoke findM800UserByPhoneNumberFromServer ().

/**
* Callback for use with {@link
IM800FindUserManager#findM800UserByPhoneNumberFromServer(String,
FindM800UserByPhoneNumberCallback)} to get the request result.
*/
interface FindM800UserByPhoneNumberCallback {
/**
* Called when M800 user search is finished without error.
*
* <p>This callback is called on application's main thread.</p>
*
* @param phoneNumber phoneNumber the phone number used during search
* @param userProfile the search result, if result not found, that should be null
* @param isContact indicates whether the related user is friend or not
*/
void complete(String phoneNumber, IM800UserProfile userProfile, boolean
isContact);
/**
* Called when M800 user search is finished with error.
*
* <p>This callback is called on application's main thread.</p>
*
* @param phoneNumber the phone number used during search
* @param error simplified error result
* @param message detail error result
*/
void error(String phoneNumber, M800PacketError error, String message);
}

Take the demo project as an example. Please refer to the class ContactApiDemoFindUserByNumFromServerActivity.java.

mFindUserManager.findM800UserByPhoneNumberFromServer(phoneNumber, new
IM800FindUserManager.FindM800UserByPhoneNumberCallback() {
@Override
public void complete(String phoneNumber, IM800UserProfile userProfile, boolean
isContact) {
//Invoked when M800 user search is finished without error.
//if userProfile is null, that mean user not found.
}
@Override
public void error(String phoneNumber, M800PacketError error, String message) {
//Invoked when M800 user search is finished with error.
}
});

1. Please note that, even if complete () invoked, please don't forget check the userProfile. If userProfile is null, that mean user not found
in server.
2. To query user by JID from server, please invoke findM800UserByJIDFromServer ().

/**
* Query an M800 user's profile by JID
from M800 server asynchronously.
*
* @param JID the unique identifier of an M800 user
* @param callback an asynchronous callback of find user result, {@link
FindM800UserByJIDCallback#complete(String, IM800UserProfile, boolean)}
*
method will be called if the request is success, otherwise {@link
FindM800UserByJIDCallback#error(String, M800PacketError, String)}
*
method will be called.
*/
void findM800UserByJIDFromServer(String JID, FindM800UserByJIDCallback callback);

/**
* Callback for use with {@link
IM800FindUserManager#findM800UserByJIDFromServer(String, FindM800UserByJIDCallback)}
to get the
request result.
*/
interface FindM800UserByJIDCallback {
/**
* Called when M800 user search is finished without error.
*
* <p>This callback is called on application's main thread.</p>
*
* @param JID the unique identifier of an M800 user
* @param userProfile the search result, if result not found, this should be null
* @param isContact indicates whether the related user is friend or not
*/
void complete(String JID, IM800UserProfile userProfile, boolean isContact);
/**
* Called when M800 user search is finished with error.
*
* <p>This callback is called on application's main thread.</p>
*
* @param JID the unique identifier of an M800 user
* @param error simplified error result
* @param message detail error result
*/
void error(String JID, M800PacketError error, String message);
}

Please refer to the class ContactApiDemoFindUserByJIDFromServerActivity.java.

findUserManager.findM800UserByJIDFromServer(jid, new
IM800FindUserManager.FindM800UserByJIDCallback() {
@Override
public void complete(String JID, IM800UserProfile userProfile, boolean
isContact) {
//Invoked when M800 user search is finished without error.
//if userProfile is null, that mean user not found.
}
@Override
public void error(String JID, M800PacketError error, String message) {
//Invoked when M800 user search is finished with error.
}
});

Please note that, even if complete () invoked, please don't forget check the userProfile. If userProfile is null, that mean user not found
in server.
M800SDK will cache M800 user's profile locally, it provided a fast way to query the user profile, but the data will not auto update unless
the M800 user is current user's M800 contact and M800 roster is started, so the user profile you get from this method is not guaranteed to
contain the latest data.

To query user by JID from local, please invoke findM800UserByJIDFromLocal ().

/**
* Query an M800 user's profile by JID in local M800SDK database synchronously.
*
* <p>Note: M800SDK will cache M800 user's profile locally,
* but it will not update the profile data unless the M800 user is current user's
M800 contact and M800 roster is started
* (M800 roster will push contacts' change to user), so the user profile you get
from this method is not guaranteed to contain the latest data.
* This means, the user name, email...etc may not be the most updated.</p>
* <p>If you want to get the most updated user profile, please use {@link
#findM800UserByJIDFromServer(String, FindM800UserByJIDCallback)}</p>
*
* @param JID the unique identifier of an M800 user
*/
IM800UserProfile findM800UserByJIDFromLocal(String JID);

Please refer to the class ContactApiDemoFindUserByJIDFromLocalActivity.java.

IM800UserProfile userProfile = findUserManager.findM800UserByJIDFromLocal(mJid);

If you want to get the most updated user profile, we recommend that please see findM800UserByJIDFromServer ().
Since the above query methods are related to database query action, we recommend that, developer should invoke this method on a
background thread, thus avoid blocking the main thread process.

Find User by PIN


Every M800 user has a unique PIN assigned by M800 Server after signup. The PIN is a string value contains only letter and numbers. Unlike JID,
PIN doesnt contain sensitive information like user phone number or APP carrier. Thats why it can be shared with others and let them find the
M800 user.
To get current users PIN:

AsyncTask<Void, Void, String> mGetMyPinTask = new AsyncTask<Void, Void, String>() {


@Override
protected String doInBackground(Void... params) {
IM800AccountManager accountManager = M800SDK.getInstance().getAccountManager();
return accountManager.getPin();
}
@Override protected void onPostExecute(String s) {
mPinTextView.setText(s);
}
};

To find other M800 user by PIN:

mFindUserManager.findM800UserByPin(pin, new
IM800FindUserManager.FindM800UserByPinCallback() {
@Override
public void complete(String pin, IM800UserProfile userProfile, boolean isContact) {
if (userProfile != null) {
// Found the user
} else {
// User not found
}
}
@Override
public void error(String pin, M800PacketError error, String message) {
// Error
}
});

Find User by Recommendation


M800 server can provide a list of recommended users based current users contacts. You can choose to get the list from server or get local
cached list.
To get the recommendation list from server:

mFindUserManager.findM800UsersByRecommendation(new
IM800FindUserManager.FindM800UsersCallback() {
@Override
public void complete(List<IM800UserProfile> userProfiles) {
}
@Override
public void error(M800PacketError error, String message) {
}
}, true);

You can remove a user from the recommended user list use the following API:

/**
* Remove an M800 user from the recommended user list.
*
* <p>Next time when {@link
IM800FindUserManager#findM800UsersByRecommendation(FindM800UsersCallback, boolean)}
* is called, this user will not appear in the list.</p>
*
* @param JID the unique identifier of an M800 user
* @param callback an asynchronous callback of remove user from recommendation list
result, {@link RemoveRecommendationCallback#success(String)}
*
method will be called if the request is success, otherwise {@link
RemoveRecommendationCallback#error(String, M800PacketError, String)}
*
method will be called.
*/
void removeM800UserFromRecommendation(String JID, RemoveRecommendationCallback
callback);

Find User by Location


To find nearby users, simply provide current users location.

mFindUserManager.findM800UsersByLocation(latitude, longitude, new


IM800FindUserManager.FindM800UsersCallback() {
@Override
public void complete(List<IM800UserProfile> userProfiles) {
}
@Override
public void error(M800PacketError error, String message) {
}
});

Report and Block User


You can report an M800 user by providing his/her JID:

M800SDK.getInstance().getFindUserManager().reportM800User("JID", new
IM800FindUserManager.ReportM800UserCallback() {
@Override
public void success(String JID) {
}
@Override
public void error(String JID, M800PacketError error, String message) {
}
});

You can block or unblock an M800 user. Current user will not receive any IM or call from the blocked user.

M800SDK.getInstance().getFindUserManager().blockM800User("JID", new
IM800FindUserManager.BlockM800UserCallback() {
@Override
public void success(String JID, boolean isBlocked) {
}
@Override
public void error(String JID, M800PacketError error, String message) {
}
});

To check whether an M800 user is block or not:

// Check the user's profile to see if it is blocked


IM800UserProfile profile = M800SDK.getInstance().getFindUserManager().findM800User...
boolean isBlocked = profile.isBlocked();
// Check whether a user is blocked providing its JID
boolean isBlocked =
M800SDK.getInstance().getFindUserManager().isM800UserBlocked("JID");

User Profile Module


Introduction
The User Profile module in the m800SDK provides functionality to retrieve/update current users profile.

How to Implement
As a start point...
Please get an instance of IM800AccountManager from M800SDK.

IM800AccountManager accountManager = M800SDK.getInstance().getAccountManager();

Retrieve current user profile


Retrieve Name
To retrieve the name, please invoke following method.

/**
* Get name of current user.
*
* @return name of current user
*/
String getName();

Retrieve Status
To retrieve the status, please invoke following method.

/**
* Get status of current user.
*
* @return status of current user
*/
String getStatus();

Retrieve Gender
To retrieve the gender, please invoke following method.

/**
* Get gender of current user.
*
* @return gender of current user
*/
IM800UserProfile.Gender getGender();

Retrieve Birthday
To retrieve the birthday, please invoke following method.

/**
* Get birthday of current user.
*
* @return time(UTC) of birthday, return -1 if not defined
*/
long getBirthday();

Retrieve Email Address


To retrieve the email address, please invoke following method.

/**
* Get email address of current user.
*
* @return email address of current user
*/
String getEmailAddress();

Retrieve Profile Image


To retrieve the profile image url, please invoke following method.

/**
* Get profile image url of current user.
*
* @return url of media, return null if not found.
*/
String getProfileImageUrl();

To retrieve the profile image thumbnail url, please invoke following method.

/**
* Get profile thumbnail url of current user.
*
* @return url of media, return null if not found.
*/
String getProfileImageThumbnailUrl();

Retrieve Cover Image


To retrieve the cover image url, please invoke following method.

/**
* Get cover image url of current user.
*
* @return url of media, return null if not found.
*/
String getCoverImageUrl();

Retrieve Caller Video


To retrieve the caller video url, please invoke following method.

/**
* Get caller video url of current user.
*
* @return url of media, return null if not found.
*/
String getCallerVideoUrl();

To retrieve the caller video thumbnail url, please invoke following method.

/**
* Get caller video thumbnail url of current user.
*
* @return url of media, return null if not found.
*/
String getCallerVideoThumbnailUrl();

Update current user profile


Update Name
To update the name, please invoke following method.

/**
* Set name of current user.
*
* @param value name of current user
* @param callback an asynchronous callback of set profile data, {@link
UpdateUserProfileCallback#complete()} method will be called if the request is success,
otherwise {@link UpdateUserProfileCallback#error(M800PacketError, String)} method will
be called.
*/
void setName(String value, UpdateUserProfileCallback callback);

The following code show how to update the name.

IM800AccountManager accountManager = M800SDK.getInstance().getAccountManager();


String name = "<Name>";
accountManager.setName(name, new IM800AccountManager.UpdateUserProfileCallback() {
@Override
public void complete() {
//update success
}
@Override
public void error(M800PacketError error, String message) {
//update failure
}
});

Update Status
Unlike other user profile values, user status will be cleared every time user sign-in. It is recommended that you set a default status for
user after he/she sign-up successfully.
To update the status, please invoke following method.

/**
* Set status of current user.
*
* @param value status of current user
* @param callback an asynchronous callback of set profile data, {@link
UpdateUserProfileCallback#complete()} method will be called if the request is success,
otherwise {@link UpdateUserProfileCallback#error(M800PacketError, String)} method will
be called.
*/
void setStatus(String value, UpdateUserProfileCallback callback);

The following code show how to update the status.

IM800AccountManager accountManager = M800SDK.getInstance().getAccountManager();


String status= "<Status>";
accountManager.setStatus(status, new IM800AccountManager.UpdateUserProfileCallback() {
@Override
public void complete() {
//update success
}
@Override
public void error(M800PacketError error, String message) {
//update failure
}
});

Update Gender
To update the gender, please invoke following method.

/**
* Set gender of current user.
*
* @param gender status of current user
* @param callback an asynchronous callback of set profile data, {@link
UpdateUserProfileCallback#complete()} method will be called if the request is success,
otherwise {@link UpdateUserProfileCallback#error(M800PacketError, String)} method will
be called.
*/
void setGender(IM800UserProfile.Gender gender, UpdateUserProfileCallback callback);

The following code show how to update the gender.

IM800AccountManager accountManager = M800SDK.getInstance().getAccountManager();


IM800UserProfile.Gender gender = <IM800UserProfile.Gender>;
accountManager.setGender(gender, new IM800AccountManager.UpdateUserProfileCallback() {
@Override
public void complete() {
//update success
}
@Override
public void error(M800PacketError error, String message) {
//update failure
}
});

Update Birthday
To update the birthday and the date is selected from DatePickerDialog, please invoke following method.

/**
* Set birthday of current user.
*
* @param year year of birthday
* @param monthOfYear month of birthday
* @param dayOfMonth day of birthday
* @param callback an asynchronous callback of set profile data, {@link
UpdateUserProfileCallback#complete()} method will be called if the request is success,
otherwise {@link UpdateUserProfileCallback#error(M800PacketError, String)} method will
be called.
*/
void setBirthday(int year, int monthOfYear, int dayOfMonth, UpdateUserProfileCallback
callback);

The following code show how to update the birthday. where the date is selected from DatePickerDialog.

IM800AccountManager accountManager = M800SDK.getInstance().getAccountManager();


int year= <year>; //Calendar.YEAR
int monthOfYear= <monthOfYear>; //Calendar.MONTH
int dayOfMonth= <dayOfMonth>; //Calendar.DAY_OF_MONTH
accountManager.setBirthday(year, monthOfYear, dayOfMonth, new
IM800AccountManager.UpdateUserProfileCallback() {
@Override
public void complete() {
//update success
}
@Override
public void error(M800PacketError error, String message) {
//update failure
}
});

Update Email Address


To update the email address, the given email address must be valid, please invoke following method.

/**
* Set email address of current user.
*
* @param value email of current user
* @param callback an asynchronous callback of set profile data, {@link
UpdateUserProfileCallback#complete()} method will be called if the request is success,
otherwise {@link UpdateUserProfileCallback#error(M800PacketError, String)} method will
be called.
*/
void setEmailAddress(String value, UpdateUserProfileCallback callback);

The following code show how to update the email address.

IM800AccountManager accountManager = M800SDK.getInstance().getAccountManager();


String email = "<valid email address>";
accountManager.setEmailAddress(email, new
IM800AccountManager.UpdateUserProfileCallback() {
@Override
public void complete() {
//update success
}
@Override
public void error(M800PacketError error, String message) {
//update failure
}
});

Update Profile Image


To update the profile image, please invoke following method.

/**
* Set profile image of current user.
*
* @param source
media source
* @param callback file upload progress listener
*/
void setProfileImage(File source, UpdateUserProfileMediaSourceCallback callback);

The following code show how to update the profile image.

IM800AccountManager accountManager = M800SDK.getInstance().getAccountManager();


File imageFile = <Your Profile Image>;
accountManager.setProfileImage(imageFile, new
IM800AccountManager.UpdateUserProfileMediaSourceCallback() {
@Override
public void complete(int code, String url, String localPath) {
//update success
}
@Override
public void error(M800PacketError error, String message, int code, String
localPath) {
//update failure
}
@Override
public void transferStarted(String filePath, long fileSize) {
//on upload begin
}
@Override
public void transferred(long transferredBytes) {
//update progress
}
@Override
public void transferFinished(int code, String url, String localPath) {
//on upload success
}
@Override
public void transferFailed(int code, String localPath) {
//on upload failure
}
});

Update Cover Image


To update the cover image, please invoke following method.

/**
* Set cover image of current user.
*
* @param source
media source
* @param callback file upload progress listener
*/
void setCoverImage(File source, UpdateUserProfileMediaSourceCallback callback);

The following code show how to update the cover image.

IM800AccountManager accountManager = M800SDK.getInstance().getAccountManager();


File imageFile = <Your Cover Image>;
accountManager.setCoverImage(imageFile, new
IM800AccountManager.UpdateUserProfileMediaSourceCallback() {
@Override
public void complete(int code, String url, String localPath) {
//update success
}
@Override
public void error(M800PacketError error, String message, int code, String
localPath) {
//update failure
}
@Override
public void transferStarted(String filePath, long fileSize) {
//on upload begin
}
@Override
public void transferred(long transferredBytes) {
//update progress
}
@Override
public void transferFinished(int code, String url, String localPath) {
//on upload success
}
@Override
public void transferFailed(int code, String localPath) {
//on upload failure
}
});

Update Caller Video


To update the caller video, the Mime Type of file must be video/mp4 and the file size must be less than 700 KB ,please invoke following
method.

/**
* Set caller video of current user.
*
* @param source
media source
* @param callback file upload progress listener
*/
void setCallerVideo(File source, UpdateUserProfileMediaSourceCallback callback);

The following code show how to update the caller video.

IM800AccountManager accountManager = M800SDK.getInstance().getAccountManager();


File videoFile = <Your Video File>;
accountManager.setCallerVideo(mSelectedMediaFile, new
IM800AccountManager.UpdateUserProfileMediaSourceCallback() {
@Override
public void complete(int code, String url, String localPath) {
//update success
}
@Override
public void error(M800PacketError error, String message, int code, String
localPath) {
//update failure
}
@Override
public void transferStarted(String filePath, long fileSize) {
//on upload begin
}
@Override
public void transferred(long transferredBytes) {
//update progress
}
@Override
public void transferFinished(int code, String url, String localPath) {
//on upload success
}
@Override
public void transferFailed(int code, String localPath) {
//on upload failure
}
});

Delete Profile Image


To delete the profile image, please invoke following method.

/**
* Remove profile image of current user.
*
* @param callback remove file progress listener
*/
void deleteProfileImage(DeleteUserProfileMediaSourceCallback callback);

The following code show how to delete the profile image.

IM800AccountManager accountManager = M800SDK.getInstance().getAccountManager();


accountManager.deleteProfileImage(new
IM800AccountManager.DeleteUserProfileMediaSourceCallback() {
@Override
public void complete() {
//delete success
}
@Override
public void error(M800PacketError error, String message) {
//delete failure
}
});

Delete Cover Image


To delete the cover image, please invoke following method.

/**
* Remove cover image of current user.
*
* @param callback remove file progress listener
*/
void deleteCoverImage(DeleteUserProfileMediaSourceCallback callback);

The following code show how to delete the cover image.

IM800AccountManager accountManager = M800SDK.getInstance().getAccountManager();


accountManager.deleteCoverImage(new
IM800AccountManager.DeleteUserProfileMediaSourceCallback() {
@Override
public void complete() {
//delete success
}
@Override
public void error(M800PacketError error, String message) {
//delete failure
}
});

Delete Caller Video


To delete the caller video, please invoke following method.

/**
* Remove caller video of current user.
*
* @param callback remove file progress listener
*/
void deleteCallerVideo(DeleteUserProfileMediaSourceCallback callback);

The following code show how to delete the caller video.

IM800AccountManager accountManager = M800SDK.getInstance().getAccountManager();


accountManager.deleteCallerVideo(new
IM800AccountManager.DeleteUserProfileMediaSourceCallback() {
@Override
public void complete() {
//delete success
}
@Override
public void error(M800PacketError error, String message) {
//delete failure
}
});

User Preference
Introduction
The User Preference module in the m800SDK provides functionality to modify the user preference, and sync the related data to server.

How to Implement
As a start point...
Please get an instance of IM800UserPreference from M800SDK.

IM800UserPreference userPreference = M800SDK.getInstance().getUserPreference();

Retrieve / Modify User Preference


Language
To retrieve the selected language in user preference, please invoke following method.

/**
* Return a user preference - language
*
* @param defaultValue it default value will return if a null value is associated with
this field.
* @return the value associated with this field, or defaultValue if no valid value is
currently mapped to this field.
*/
IM800Management.M800Language getLanguage(IM800Management.M800Language defaultValue);

To modify the language in user preference, please invoke following method.

/**
* Store a user preference - language
*
* <p>After update, it will update the related user preference to server
automatically. Client side also can use this value to setup corresponding UI.</p>
*
* @param language which is supported by M800 SDK
*/
void setLanguage(IM800Management.M800Language language);

Recommendation
The recommendation preference is referring to the feature of finding M800 recommended users in Find User Module,
To retrieve the current setting, please invoke the following method:

/**
* Get the current preference setting of recommendation of users.
* @return {@code true} if this preference enabled.
*/
boolean isRecommendationEnabled();

To modify the setting, please invoke the following method:

/**
* Enable finding M800 recommendated users
* @param enable {@code true} the set this preference enabled.
*/
void enableRecommendation(boolean enable);

Find users by Pin/Phone


The find users by Pin/Phone preference is referring to the feature of finding M800 users by pin and phone numbers in Find User Module,
To retrieve the current setting, please invoke the following method:

/**
* Get the current preference setting of enable finding users by Pin/Phone.
* @return {@code true} if this preference enabled. Default value, true.
*/
boolean isFindUsersByPinPhoneEnabled();

To modify the setting, please invoke the following method:

/**
* Enable finding users by Pin/Phone
* @param enable {@code true} the set this preference enabled.
*/
void enableFindUsersByPinPhone(boolean enable);

Find users by location


The find users by location preference is referring to the feature of finding M800 users by location in Find User Module,
To retrieve the current setting, please invoke the following method:

/**
* Get the current preference setting of enable finding users by location.
* @return {@code true} if this preference enabled. Default value, true.
*/
boolean isFindUsersByLocationEnabled();

To modify the setting, please invoke the following method:

/**
* Enable finding users by location
* @param enable {@code true} the set this preference enabled.
*/
void enableFindUsersByLocation(boolean enable);

My video caller ID visibility


The my video caller ID visibility preference is referring to the visibility of the current user's video call ID to other users,
To retrieve the current setting, please invoke the following method:

/**
* Get the current preference setting of showing the user's video callerId to others.
* @return {@code true} if this preference enabled. Default value, true.
*/
boolean isShowingMyCallerId();

To modify the setting, please invoke the following method:

/**
* Enable showing the user's video callerId to others
* @param show {@code true} the set this preference enabled.
*/
void showMyCallerId(boolean show);

Other's video caller ID visibility


The other's video caller ID visibility preference is referring to the visibility of the other user's video call ID to the current user,
Please note that this setting is a local setting only. It is not synchronized with M800 server.
To retrieve the current setting, please invoke the following method:

/**
* Get the current preference setting of showing the other's video callerId to the
user.
* @return {@code true} if this preference enabled. Default value, true.
*/
boolean isShowingOthersCallerId();

To modify the setting, please invoke the following method:

/**
* Enable showing other's video callerId to the user.
* @param show {@code true} the set this preference enabled.
*/
void showOthersCallerId(boolean show);

Presence
The presence preference is referring to the feature of sending online/offline state in Connect Module,
After enabling this preference, other users will see your last online time.
To retrieve the current setting, please invoke the following method:

/**
* Get the current preference setting of sharing the user's presence to others.
* @return {@code true} if this preference enabled. Default value, true.
*/
boolean isSharingMyPresence();

To modify the setting, please invoke the following method:

/**
* Enable sharing the user's presence to others.
* @param share {@code true} the set this preference enabled.
*/
void shareMyPresence(boolean share);

Displayed Receipt
The displayed receipt preference is referring to the feature of sending displayed receipt of an incoming message in Message Module,
After enabling this preference, you will be able to send the displayed receipt per incoming message.
To retrieve the current setting, please invoke the following method:

/**
* Get the current preference setting of sending displayed receipt of incoming
messages.
* @return {@code true} if this preference enabled. Default value, true.
*/
boolean isDisplayedReceiptEnabled();

To modify the setting, please invoke the following method:

/**
* Enable sending displayed receipt of incoming messages.
* <p/>
* Please note that developers have to handle the related business logic by
themselves.<br/>
* For example, check {@link #isDisplayedReceiptEnabled()} before sending the
displayed receipt of an incoming message.
* @param enable {@code true} means a displayed receipt should be sent for every
message which has been displayed to the user.
*/
void enableDisplayedReceipt(boolean enable);

Message notifications
The message notifications preference is referring to the feature of receiving incoming message notifications from GCM/ JPush/ M800Server,
After enabling this preference, you will receive notifications of incoming messages.
To retrieve the current setting, please invoke the following method:

/**
* Get the current preference setting of receiving incoming message notifications.
* @return {@code true} if this preference enabled. Default value, true.
*/
boolean isMessageNotificationEnabled();

To modify the setting, please invoke the following method:

/**
* Enable receiving incoming message notifications.
* @param enable {@code true} the set this preference enabled.
*/
void enableMessageNotification(boolean enable);

Monitor User Preference Update Activity


Please invoke addListener() to start monitor User Preference update activity.

/**
* Register a listener that listeners events of all user preference update.
*
* @param listener a listener implements {@link IM800UserPreferenceListener}
* @throws NullPointerException if listener is null
*/
void addListener(IM800UserPreferenceListener listener);

And use the following listener.

/**
* Callback to monitor the update event of user preference.
*/
interface IM800UserPreferenceListener {
/**
* This method is invoked when user preference[language] is updated.
* <p>
* This callback is invoked on {@link android.app.Application}'s main thread.
*
* @param language The updated language.
*/
void onLanguageUpdated(IM800Management.M800Language language);

/**
* This method is invoked when user preference[Recommendation] is updated.
* <p>
* This callback is invoked on {@link android.app.Application}'s main thread.
*
* @param enabled provides the latest preference setting.
*/
void onRecommendationEnabled(boolean enabled);
/**
* This method is invoked when user preference[FindUsersByPinPhone] is updated.
* <p>
* This callback is invoked on {@link android.app.Application}'s main thread.
*
* @param enabled provides the latest preference setting.
*/
void onFindUsersByPinPhoneEnabled(boolean enabled);
/**
* This method is invoked when user preference[FindUsersByLocation] is updated.
* <p>
* This callback is invoked on {@link android.app.Application}'s main thread.
*
* @param enabled provides the latest preference setting.
*/
void onFindUsersByLocationEnabled(boolean enabled);
/**
* This method is invoked when user preference[ShowMyCallerId] is updated.
* <p>
* This callback is invoked on {@link android.app.Application}'s main thread.
*
* @param isShowing provides the latest preference setting.
*/
void onShowingMyCallerId(boolean isShowing);
/**
* This method is invoked when user preference[ShowOthersCallerId] is updated.
* <p>
* This callback is invoked on {@link android.app.Application}'s main thread.
*
* @param isShowing provides the latest preference setting.
*/
void onShowingOthersCallerId(boolean isShowing);

/**
* This method is invoked when user preference[ShareMyPresence] is updated.
* <p>
* This callback is invoked on {@link android.app.Application}'s main thread.
*
* @param isSharing provides the latest preference setting.
*/
void onSharingMyPresence(boolean isSharing);
/**
* This method is invoked when user preference[SendDisplayedReceipt] is updated.
* <p>
* This callback is invoked on {@link android.app.Application}'s main thread.
*
* @param enabled provides the latest preference setting.
*/
void onDisplayedReceiptEnabled(boolean enabled);
/**
* This method is invoked when user preference[ReceiveMessageNotification] is updated.
* <p>
* This callback is invoked on {@link android.app.Application}'s main thread.
*
* @param enabled provides the latest preference setting.
*/
void onMessageNotificationEnabled(boolean enabled);
/**
* Called when sync status changed.
*
* <p>This callback is called on application's main thread.</p>
*
* @param isSyncing Indicates whether user preference is synced with server.
*/

void onSyncStatusChanged(boolean isSyncing);


}

We recommend that you keep the reference object of the listener, since developer needs it to stop related monitoring.
To stop monitoring User Preference Update Activity, please invoke removeListener() to stop monitor User Preference update activity.

/**
* Unregister a listener.
*
* @param listener an user preference listener previously registered
* @throws NullPointerException if listener is null
*/
void removeListener(IM800UserPreferenceListener listener);

To stop all User Preference Update Activity monitoring, please invoke clearListeners() to stop monitor User Preference update activity.

/**
* Unregister all user preference listeners.
*/
void clearListeners();

User Preference Synchronization


To check whether user preference is synced with server. please invoke following method.

/**
* Indicates whether user preference is synced with server.
*
* @return whether user preference is synced with server
*/
boolean isDataSynced();

To check whether the user preference synchronization is in progress. please invoke following method.

/**
* Indicates whether user preference synchronization task is running or not.
*
* @return whether user preference synchronization task is running or not.
*/
boolean isDataSyncing();

To check last time of user preference synchronization. please invoke following method.

/**
* Retrieve the last success sync time.
*
* @return last success sync time, return -1 if never synced yet.
*/
long getLastSyncTime();

To trigger user preference synchronization manually. please invoke following method.

/**
* Request to start user preference synchronization task.
* <p>
*
If synchronization task is executed once, and force is not set to true, no
synchronization task will be executed.
*
Only one synchronization task will be executed at one time, no duplicate
request allowed.
* </p>
*
* @param force force update
*/
void syncData(boolean force);

Anda mungkin juga menyukai