M800SDK User Manual For Android [PDF]

  • 0 0 0
  • Gefällt Ihnen dieses papier und der download? Sie können Ihre eigene PDF-Datei in wenigen Minuten kostenlos online veröffentlichen! Anmelden
Datei wird geladen, bitte warten...
Zitiervorschau

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 user’s 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 RateManager’s data from server: To check if the RateManager’s 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: [email protected].

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 project’s 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 project’s 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 project’s gradle file: Add following dependencies for M800SDK in your project’s 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 project’s AndroidManifest.xml file: Production environment:



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:







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:

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 SDK’s 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 hasn’t 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



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 user’s phone number by the following API:

M800SDK.getInstance().getUsername();

After a successful sign up, You can get current user’s 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 device’s 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 SDK’s 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 { @Override protected List doInBackground(Void... params) { return M800SDK.getInstance().getContactManager().getM800Contacts(); } @Override protected void onPostExecute(List contacts) { // Update UI } }

Get M800 native contact list

class GetContactsTask extends AsyncTask { @Override protected List doInBackground(Void... params) { return M800SDK.getInstance().getContactManager().getM800NativeContacts(); } @Override protected void onPostExecute(List 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. Don’t 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 = ; // 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(); // Get one request M800SDK.getInstance().getContactManager().getAddContactRequest(, ); // Get requests count M800SDK.getInstance().getContactManager().getAddContactRequestsCount();

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();

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 user’s 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 contact’s 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 user’s 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 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 callee’s 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 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 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 callee’s 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 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 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 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. *

* 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. *

* 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 user’s face is close to the screen. It is a common behavior of the mobile devices that the screen dims when user’s 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, " Restoring screen brightness"); } else { Log.d(DEBUG_TAG, " 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.

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 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.

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 don’t 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(“”); 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 doesn’t 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 getChatRooms();

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

List 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 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. * *

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)}.

*

This callback is called on application's main thread.

* * @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. * *

This callback is called on application's main thread.

* * @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 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 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 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. *

* 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. *

* * @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. * *

This callback is called on application's main thread.

* * @param roomId multi chat room ID */ void complete(String roomId);

/** * Called when MUC synchronization is finished with error. * *

This callback is called on application's main thread.

* * @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. * *

This callback is called on application's main thread.

* * @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. * *

This callback is called on application's main thread.

* * @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. * *

This callback is called on application's main thread.

* * @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. * *

This callback is called on application's main thread.

* * @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. * *

This callback is called on application's main thread.

* * @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. * *

This callback is called on application's main thread.

* * @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. * *

This callback is called on application's main thread.

* * @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. * *

This callback is called on application's main thread.

* * @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. * *

This callback is called on application's main thread.

* * @param roomId multi chat room ID */ void complete(String roomId); /** * Called when leave room is finished with error. * *

This callback is called on application's main thread.

* * @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. * *

This callback is called on application's main thread.

* * @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. * *

This callback is called on application's main thread.

* * @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. * *

This callback is called on application's main thread.

* * @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. * *

This callback is called on application's main thread.

* * @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. * *

This callback is called on application's main thread.

* * @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. * *

This callback is called on application's main thread.

* * @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. * *

This callback is called on application's main thread.

* * @param roomId multi chat room ID */ void complete(String roomId); /** * Called when update chat room icon request is sent with error. * *

This callback is called on application's main thread.

* * @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. * *

This callback is called on application's main thread.

* * @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. * *

This callback is called on application's main thread.

* * @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. * *

This callback is called on application's main thread.

* * @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 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 isn’t start with “+”, current user’s country code will be added during chat room creation. For example, if you provide “55558888”, and current user’s 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 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 room’s 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 = ""; String text = ""; 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 file’s 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 = ""; File audioFile = ; float audioDuration = ; 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 it’s 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 = ""; File imageFile = ; Bitmap imageThumbnail = ; 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 it’s 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 = ""; File videoFile = ; float videoDuration = ; Bitmap videoThumbnail = ; 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 message’s 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 = ""; Bitmap ephemeralImage = ; int ttl = ; 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 message’s 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 = ; 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" , );

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 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 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 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 = ; 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 int successfullySentCount = smsChatMessage.getSentCount(); // Error occurred during SMS sending, // check this if is less than 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 = ; 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 message’s 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 message’s image to user, you should start a timer to count the display time. If the message’s time to live (TTL) valu e is reached, you should clear ephemeral message’s 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. * *

When an ephemeral message's TTL is set to 0, * you should also call {@link #removeEphemeralMessageImage(String)} to clear its image data.

* * @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. * *

Next time when {@link #getEphemeralImageBitmapArray(String)} is called, it will return null.

* * @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 { @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 { @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 { @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 doesn’t 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. * *

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.

*/ 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. * *

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.

* * @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 user’s 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 RateManager’s 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 RateManager’s 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 = ""; //en, zh_cn, zh List smsList = mM800RateManager.getRateInfoItems(IM800RateManager.ChargingRateType.SMS, language);

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

String language = ""; //en, zh_cn, zh List offnetList = mM800RateManager.getRateInfoItems(IM800RateManager.ChargingRateType.OFFNET_CALL, language);

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

String language = ""; //en, zh_cn, zh String keyword = ""; IM800RateManager.ChargingRateType type = ; List 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 user’s 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 hasn’t 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. * *

This callback is called on application's main thread.

* * @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. * *

This callback is called on application's main thread.

* * @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. * *

This callback is called on application's main thread.

* * @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. * *

This callback is called on application's main thread.

* * @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. * *

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.

*

If you want to get the most updated user profile, please use {@link #findM800UserByJIDFromServer(String, FindM800UserByJIDCallback)}

* * @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 doesn’t contain sensitive information like user phone number or APP carrier. That’s why it can be shared with others and let them find the M800 user. To get current user’s PIN:

AsyncTask mGetMyPinTask = new AsyncTask() { @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 user’s 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 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. * *

Next time when {@link IM800FindUserManager#findM800UsersByRecommendation(FindM800UsersCallback, boolean)} * is called, this user will not appear in the list.

* * @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 user’s location.

mFindUserManager.findM800UsersByLocation(latitude, longitude, new IM800FindUserManager.FindM800UsersCallback() { @Override public void complete(List 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 user’s 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 = ""; 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= ""; 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 = ; 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= ; //Calendar.YEAR int monthOfYear= ; //Calendar.MONTH int 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 = ""; 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 = ; 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 = ; 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 = ; 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 * *

After update, it will update the related user preference to server automatically. Client side also can use this value to setup corresponding UI.

* * @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. *

* Please note that developers have to handle the related business logic by themselves.
* 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. *

* 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. *

* 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. *

* 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. *

* 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. *

* 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. *

* 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. *

* 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. *

* 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. *

* 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. * *

This callback is called on application's main thread.

* * @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. *

* 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. *

* * @param force force update */ void syncData(boolean force);