This document provides a functional description for Kandy Android SDK.
The code samples in this document include parsed code in a developer-friendly window. The window allows developers to copy the code into their development environments.

A sample screenshot of such window is presented below.

Sample Code

Quick Start with Kandy Android SDK

This guide covers what you need to go through in order to be able to start using Kandy SDK for Android

  1. Download and Install Kandy SDK for Android
  2. API Keys and Secret
  3. Configure Android Project
  4. Run sample app

Step 1 - Download and Install Kandy SDK for Android

The Kandy Android SDK is made for Android 4.0 and above.

Download and unzip the SDK

Download SDK

The zip contains:

  • kandy-x.x.xxx-sdk.zip:
    • libs/armeabi - .so (or any other armeabi-* folders. (like: armeabi-v7a))
    • libs/arm64-v8a - .so
    • libs/x86 - .so
    • kandy-x.x.xxx.jar - Kandy SDK library
    • kandy-x.x.xxx-javadoc - Documentation
  • kandy-x.x.xxx-sample.zip - sources for sample application

Adding the SDK to your environment:

Import the “kandy-1.6.254-sdk.zip” file’s contents into your existing Android project by extracting it into your “libs” folder. If your project does not already have a “libs” folder, create one at the root of the project.

Note: For Android Studio the libs integration shall be performed as follows

  • For .jar KandySDK library integration:
    • Copy .jar file of KandySDK into folder libs (MyProject->app->libs)
    • Right click on added .jar file and click on “Add as library”
  • For .so library integration:
    • Create folder jniLibs under the following path MyProject->app->src->main->jniLibs->armeabi-v7a
    • Copy libjingle_peerconnection_so.so into armeabi-v7a

Step 2 - API Keys and Secret

One thing to notice when viewing your developer dashboard is that you have multiple API keys. It’s important to know which one to use. You have a public and secret API key for your account which you can use for administrative actions like creating new domains. You also have public and secret API keys for each of your domains which you use for most of Kandy’s features. The only API key you will need to use for the Javascript SDK is your domain’s public API key. Here’s where you can find it:

Dashboard Example

Step 3 - Configure your Android project

Import

Add Permissions

  • Your app must request permissions to use Kandy. If it is not already doing so, add these lines before the <application> tag in your AndroidManifest.xml:
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
  • Add reference to MyApp(name of the class which extends the Application class) in the Manifest under the <application> tag
	android:name=".MyApp"
  • Add the following import statement to your MyApp class(class which extends Application class)
	import com.genband.kandy.api.Kandy;

Initialize

Note: If you already have a class that extends from android.app.Application, skip this step:

	public class MyApp extends Application {
	@Override
	public void onCreate() {
	  super.onCreate();
	}
	}
  • Call Kandy.initialize from the onCreate method of your Application class to set your API KEY and API SECRET:
	public class MyApp extends Application {
	@Override
	public void onCreate() {
	  super.onCreate();

	  // Init Kandy SDK , note that "API KEY/SECRET" can be null 
	  Kandy.initialize(getApplicationContext(), "API KEY", "API SECRET");
	}
	}

Note: API Key and API Secret both are optional they could be empty strings

Logging

By default Kandy prints logs to Andorid logcat. To use custom output do the following:

To use custom output do the following:

* Implement IKandyLogger interface:
		public class KandyLogger implements IKandyLogger {

		@Override
		public void log(int level, String tag, String message) {
			// print logs to Android logcat
			switch (level)
			{
			case Level.ERROR:
				android.util.Log.e(tag, message);
				break;
			case Level.INFO:
				android.util.Log.i(tag, message);
				break;
			case Level.VERBOSE:
				android.util.Log.v(tag, message);
				break;
			case Level.WARN:
				android.util.Log.w(tag, message);
				break;
			default:
				android.util.Log.d(tag, message);
				break;
			}
		}

		@Override
		public void log(int level, String tag, String message, Throwable throwable) {
	// print logs to Android logcat
			switch (level)
			{
			case Level.ERROR:
				android.util.Log.e(tag, message, throwable);
				break;
			case Level.INFO:
				android.util.Log.i(tag, message, throwable);
				break;
			case Level.VERBOSE:
				android.util.Log.v(tag, message, throwable);
				break;
			case Level.WARN:
				android.util.Log.w(tag, message, throwable);
				break;
			default:
				android.util.Log.d(tag, message, throwable);
				break;
			}
		}

	}
* Set up your logger:

java // set custom logger instead of using default one Kandy.getKandyLog().setLogger(new KandyLogger());

* Define the lowest logs level to be printed:

java // set log level Kandy.getKandyLog().setLogLevel(Level.VERBOSE);

Provisioning of Application users

User provisioning is required to add/remove users of your project to/from Kandy system. It can be done in two ways:

  • From developers.kandy.io account.
    • Your Kandy domain administrators can create/delete users for the specific project manually. Such users shall register to the application by their username/password defined by the admin.
  • From the application (as detailed below)
    • Each user is able to register/unregister to Kandy from the application over the specific device. Currently, the SDK supports adding users by their phone number only.

Subscription flow from the application using phone number:

  • User enters his phone number from GUI
  • The application sends user phone number to Kandy - see Request Activation Code
  • Kandy sends validation code by SMS to the user’s phone number
  • The user copies the validation code manually from the SMS (or automatically captured by the application)
  • The application sends the validation code with the related phone number via the SDK to Kandy - see Activation Code
  • Get response with the KandyUser that contains the relevant data for connecting the user application to Kandy - see Activation Code

Request Activation Code

This call will send a registration request to the server. As a result, Kandy will send a validation code to the user.

Request Activation Code by SMS

	String phoneNumber = "442012345678"; // your international number with the country code prefix
	String twoLetterISOCountryCode = "IL";
	/*
	 * Defining from which prefix will start the incoming phone number
	 * prefix could contain only digits and must be not longer than 6 digits,
	 * in case of the prefix length less than 6 digits will be auto-completed with zeros
	 * If won't be defined would be used default Kandy's incoming phone number
	 */
	String callerPhonePrefix = null;

	Kandy.getProvisioning().requestCode(KandyValidationMethoud.SMS, phoneNumber, twoLetterISOCountryCode, callerPhonePrefix, new KandyResponseListener()
	{
	@Override
	public void onRequestFailed(int responseCode, String err) {
		//TODO insert your code here
	}

	@Override
	public void onRequestSucceded() {
		//TODO insert your code here
	}

Request Activation Code by IVR

	String phoneNumber = "442012345678"; // your international number with the country code prefix
	String twoLetterISOCountryCode = "IL";
	/*
	 * Defining from which prefix will start the incoming phone number
	 * prefix could contain only digits and must be not longer than 6 digits,
	 * in case of the prefix length less than 6 digits will be auto-completed with zeros
	 * If won't be defined would be used default Kandy's incoming phone number
	 */
	String callerPhonePrefix = "123456";

	Kandy.getProvisioning().requestCode(KandyValidationMethoud.CALL, phoneNumber, twoLetterISOCountryCode, callerPhonePrefix, new KandyResponseListener()
	{
		@Override
		public void onRequestFailed(int responseCode, String err) {
			//TODO insert your code here
		}

		@Override
		public void onRequestSucceded() {
			//TODO insert your code here
		}
	});

Note: It’s possible to get current user location country for twoLetterISOCountryCode parameter by using Location service via getCountryInfo API call.

Validation

The code, entered manually by the user, is used for the validation API call below. This call sends the received code to the server for validation. On success, the system adds the user as a provisioned subscriber.

	String phoneNumber = "442012345678"; // your international number with the country code prefix
	String validationCode = "code";
	String twoLetterISOCountryCode = "IL";

	Kandy.getProvisioning().validateAndProvision(phoneNumber, validationCode, twoLetterISOCountryCode, new KandyValidationResponseListener() {

		@Override
		public void onRequestFailed(int responseCode, String err) {
			//TODO insert your code here
		}

		@Override
		public void onRequestSuccess(IKandyValidationResponse response) {
			//TODO insert your code here
		} 
	});

Provisioning Deactivation

To deactivate a provisioned subscriber device use the following:

	Kandy.getProvisioning().deactivate(new KandyResponseListener() {

		@Override
		public void onRequestFailed(int responseCode, String err) {
			//TODO insert your code here
		}

		@Override
		public void onRequestSucceded() {
			//TODO insert your code here
		}
	});

Access

After you have provisioned user, you should log the user into the system. The login is required for access the SDK capabilities e.g. Calls, Chats, Presence, etc.

Notifications

You can be notified when the user’s connection to the system is changed. First implement KandyConnectServiceNotificationListener in the suitable class.

Then use the following code:

	Kandy.getAccess().registerNotificationListener(new KandyConnectServiceNotificationListener() {

		@Override
		public void onRegistrationStateChanged(KandyRegistrationState state){
			//TODO insert your code here
		}

		@Override
		public void onConnectionStateChanged(KandyConnectionState state) {
			//TODO insert your code here
		}
		
		@Override
		public void onInvalidUser(String error) {
			//TODO insert your code here
		}

		@Override
		public void onSessionExpired(String error) {
			//TODO insert your code here
		}

		@Override
		public void onSDKNotSupported(String error) {
			//TODO insert your code here		
		}
		
		@Override
		public void onCertificateError(String error) {
			//TODO insert your code here		
		}		
						
		@Override
		public void onServerConfigurationReceived(JSONObject serverConfiguration) {
			//TODO insert your code here		
		}		
		
	}); 

Log In

To log user into Kandy system using his user name and password use the following:

	KandyRecord kandyRecord = null;
	try {
		kandyRecord = new KandyRecord("username@domain");
	} catch (KandyIllegalArgumentException e) {
		//TODO insert your code here
		return;
	}
	String password = "password";

	Kandy.getAccess().login(kandyRecord, password, new KandyLoginResponseListener() {

		@Override
		public void onRequestFailed(int responseCode, String err) {
			//TODO insert your code here
		}

		@Override
		public void onLoginSucceeded() {
			//TODO insert your code here
		}
	});

Log Out

To log the user out of the Kandy server use the following:

	Kandy.getAccess().logout(new KandyLogoutResponseListener() {

		@Override
		public void onRequestFailed(int responseCode, String err) {
			//TODO insert your code here
		}

		@Override
		public void onLogoutSucceeded() {
			//TODO insert your code here
		}
	});

Connection State

To receive the current connection state to the server, use the following code:

	Kandy.getAccess().getConnectionState();

Calls

Call services of Kandy’s SDK is about starting / receiving a call and handing that call in general. To make calls with Kandy, you must be logged in.

Make a Voice or Video Call

The following method initiates a call, where:

  • Caller: origin of the call, if null the caller is current user.
  • Callee: the call destination
  • KandyOutgingVoipCallOptions : call options (START_CALL_WITHOUT_VIDEO, START_CALL_WITH_VIDEO, AUDIO_ONLY_CALL)
  • localVideoView - the view that will present the self video
  • remoteVideoView - the view that will present the other side video
	KandyRecord caller = null;
	KandyRecord callee = null;
	try {
		callee = new KandyRecord("username@domain");
	} catch (KandyIllegalArgumentException e) {
		//TODO insert your code here
		return;
	}
	KandyView localVideoView = (KandyView)findViewById (R.id.kandy_local_video_view);
	KandyView remoteVideoView = (KandyView)findViewById (R.id.kandy_remote_video_view);
	IKandyOutgoingCall currentCall = Kandy.getServices().getCallService().createVoipCall(caller, callee, KandyOutgingVoipCallOptions.START_CALL_WITHOUT_VIDEO);

	//YOU MUST TO PASS THE NON NULL VALUE OF LOCAL VIEW TO THE KandyOutgoingCall or/and KandyIncomingCall
	currentCall.setLocalVideoView(localVideoView);
	//YOU MUST TO PASS THE NON NULL VALUE OF REMOTE VIEW TO THE KandyOutgoingCall or/and KandyIncomingCall
	currentCall.setRemoteVideoView(remoteVideoView);
	currentCall.establish(new KandyCallResponseListener() {

		@Override
		public void onRequestSucceeded(IKandyCall call) {
			//TODO insert your code here
		}

		@Override
		public void onRequestFailed(IKandyCall call, int arg1, String arg2) {
			//TODO insert your code here
		}
	});

Note: Calls should be made from UI thread or HandlerThread

Make a VoIP to PSTN call

The following method initiates a VoIP to PSTN call, while the destination must be an International phone number in E164 format with country code but without the ���+��� prefix. e.g. for US number (213) 456-7890 use 12134567890.

	KandyView localVideoView = (KandyView)findViewById(R.id.kandy_local_video_view);
	KandyView remoteVideoView = (KandyView)findViewById(R.id.kandy_remote_video_view);
	//Here possible to define the user- caller whose number/name will see the callee side
	//in Case and will be null the calle will see number/username with which caller registered
	KandyRecord caller = null;
	try {
		caller = new KandyRecord("custom_name@domain");
	} catch (KandyIllegalArgumentException e) {
		//TODO insert your code here
		return;
	}IKandyOutgoingCall currentCall = Kandy.getServices().getCallService().createPSTNCall(caller, ���12134567890���, KandyOutgoingPSTNCallOptions.NONE);
	//YOU MUST TO PASS THE NON NULL VALUE OF LOCAL VIEW TO THE KandyOutgoingCall or/and KandyIncomingCall
	currentCall.setLocalVideoView(localVideoView);
	//YOU MUST TO PASS THE NON NULL VALUE OF REMOTE VIEW TO THE KandyOutgoingCall or/and KandyIncomingCall
	currentCall.setRemoteVideoView(remoteVideoView);

	currentCall.establish(new KandyCallResponseListener() {

		@Override
		public void onRequestSucceeded(IKandyCall call) {
			//TODO insert your code here
		}

		@Override
		public void onRequestFailed(IKandyCall call, int code, String error) {
			//TODO insert your code here
		}
	});

The XML Layout Definition of the KandyView

	<com.genband.kandy.api.services.calls.KandyView
		android:id="@+id/kandy_local_video_view"
		android:layout_width="100dp"
		android:layout_height="100dp" />
	
	 <com.genband.kandy.api.services.calls.KandyView
		android:id="@+id/kandy_remote_video_view"
		android:layout_width="100dp"
		android:layout_height="100dp" />

Notifications

To be notified regarding the call events: gotIncomingCall, callStateChanged, gotMissedCall etc, you shall implement KandyCallServiceNotificationListener

	Kandy.getServices().getCallService().registerNotificationListener(new KandyCallServiceNotificationListener() {
		
		@Override
		public void onVideoStateChanged(IKandyCall call, boolean isReceivingVideo, boolean isSendingVideo)
		{
			//TODO insert your code here
		}
		@Override
		public void onIncomingCall(IKandyIncomingCall call)
		{
			//TODO insert your code here
		}
		@Override
		public void onGSMCallIncoming(IKandyCall call, String incomingNumber)
		{
			//TODO insert your code here
		}
		@Override
		public void onGSMCallDisconnected(IKandyCall call, String incomingNumber)
		{
			//TODO insert your code here
		}
		@Override
		public void onGSMCallConnected(IKandyCall call, String incomingNumber)
		{
			//TODO insert your code here
		}
		@Override
		public void onCallStateChanged(KandyCallState state, IKandyCall call)
		{
			//TODO insert your code here	
		}
		@Override
		public void onMissedCall(KandyMissedCallMessage missedCallMessage) {
			//TODO insert your code here
		}
		
		@Override
		public void onWaitingVoiceMailCall(KandyWaitingVoiceMailMessage event)
		{
			//TODO insert your code here			
		}
	});

In-Call Operations

To perform operations during an active call e.g. mute, switch camera, hold, etc. use the relevant call object methods as follows:

	/**
	 * Hold current active call
	 */
	private void doHold(IKandyCall pCall) {
	
		pCall.hold(new KandyCallResponseListener() {

			@Override
			public void onRequestSucceeded(IKandyCall call) {
				//TODO insert your code here
			}

			@Override
			public void onRequestFailed(IKandyCall call, int responseCode, String err) {
				//TODO insert your code here
			}
		});
	}

Screen rotation

On screen rotation your UI can be recreated. In such case your video views will disappear. You need to use setLocalVideoView and setRemoteVideoView as you use them during make a VoIP call.

Multi Party Conference (MPV)

Multi Party Conference Service allows you to create an audio/video conference room, and invite others to join your conference.

Create Room and Invite

Before you can start a multi party conference you need to create a room, once you have the room credentials you can invite others to join the conference room.

There are three ways to invite users:

  • By email - user will receive the email with the invitation
  • By chat (only for users who already registered in your app) - user must be registered to your application and will get chat with invitation.
  • By SMS - user will receive the invitation by SMS

Note: if user not registered in your app and still able to get the invite and participate in the conference but without video and it will be regular GSM call, for conference with video the invited user must be registered in your app. It’s possible to invite by single method or by some or even all methods together.

The create room and invite users requests can be called separately or in a single request as shown in the following example:

	ArrayList<String> inviteByMail = new ArrayList<String>();
	ArrayList<String> inviteBySMS = new ArrayList<String>();
	ArrayList<KandyRecord> inviteByChat = new ArrayList<KandyRecord>();

	try {
		KandyRecord invitee = new KandyRecord("username@domain");
		inviteByChat.add(invitee);
	} catch (KandyIllegalArgumentException e) {
		e.printStackTrace();
	}

	inviteByMail.add("some@email.com");
	inviteBySMS.add("usepPhoneNumber"); //must by in international format but without '+' in the beginning

	KandyMultiPartyConferenceInvitees kandyMultiPartyConferenceInvitees = new KandyMultiPartyConferenceInvitees();
	kandyMultiPartyConferenceInvitees.setInviteByMail(inviteByMail);
	kandyMultiPartyConferenceInvitees.setInviteByChat(inviteByChat);
	kandyMultiPartyConferenceInvitees.setInviteBySMS(inviteBySMS);

	Kandy.getServices().getMultiPartyConferenceService().createRoomAndInvite(KandyMultiPartyConferenceAnnotation.NICKNAME, kandyMultiPartyConferenceInvitees ,  new KandyMultiPartyConferenceCreateAndInviteListener() {

		@Override
		public void onRequestFailed(int responseCode, String err) {
			//TODO insert your code here
		}		

		@Override
		public void onRequestSuceeded(KandyMultiPartyConferenceRoom createdRoom, KandyMultiPartyConferenceSuccessfullInvitees inviteesSeccess, 
					KandyMultiPartyConferenceFailedInvitees failedInvite) {
		   //TODO insert your code here								
		}
	});

Create Room

To create room separately use the following:

	Kandy.getServices().getMultiPartyConferenceService().createRoom (new KandyMultiPartyConferenceCreateListener()
	{
					
	@Override
	public void onRequestFailed(int responseCode, String err)
		{
			//TODO insert your code here
		}
					
					

		@Override
		public void onRequestSuceeded(KandyMultiPartyConferenceRoom createdRoom)
		{
				//TODO insert your code here							
		}
	});

Invite

To invite into separately created room use the following:

	ArrayList<String> inviteByMail = new ArrayList<String>();
	inviteByMail.add("some@email.com");
	KandyMultiPartyConferenceInvitees invitees= new KandyMultiPartyConferenceInvitees();
	invitees.setInviteByMail(inviteByMail);
	String conferenceId = "conference_id"; //must be extracted from KandyMultiPartyConferenceRoom with getConferenceId() method after room created

	Kandy.getServices().getMultiPartyConferenceService().invite(conferenceId, invitees , new KandyMultiPartyConferenceInviteListener()
	{
					
	@Override
	public void onRequestFailed(int responseCode, String err)
		{
			//TODO insert your code here
		}
									
		@Override
		public void onRequestSuceeded(	KandyMultiPartyConferenceSuccessfullInvitees inviteesSeccess,
									KandyMultiPartyConferenceFailedInvitees failedInvite )
		{
				//TODO insert your code here							
		}
	});

Make a call to created room

It is possible to make a call to the created room by 2 ways: VOIP and PSTN, which one to choose is depending on a developer’s choice.

To make a call to the created room, it is necessary to take a room’s number and create a call.

	// get Room from createRoom or createRoomAndInvite onRequestSuceeded callback
	String roomNumber;

	//FOR VOIP CALL
	roomNumber = createdRoom.getRoomNumber();

	//FOR PSTN CALL
	roomNumber = createdRoom.getRoomPSTNNumber();

	KandyRecord record = new KandyRecord(roomNumber);
	IKandyDomain kandyDomain = Kandy.getSession().getKandyDomain();
	if(kandyDomain != null)
	{
		KandyRecord recordWithDomain = new KandyRecord(record.getUserName(), kandyDomain.getName());
		// use recordWithDomain to call
	}

How to make a calls, please see 8.1 for VOIP calls (including video calls) and 8.2 for PSTN calls. Calls should be made from UI thread or HandlerThread.

Join

After steps above were finished and you have called the room you should notify server about joining to the conference.

To join the conference you should use the following:

	String conferenceId = "conference_id"; //must be extracted from KandyMultiPartyConferenceRoom with getConferenceId() method after room created
	String nickname = "Nickname";
	Kandy.getServices().getMultiPartyConferenceService().join(conferenceId, nickname, new KandyResponseListener()
	{
					
	@Override
	public void onRequestFailed(int responseCode, String err)
		{
			//TODO insert your code here
		}						

		@Override
		public void onRequestSucceded()
		{
				//TODO insert your code here							
		}
	});

Room can be extracted from chat invite message:

	KandyMultiPartyConferenceRoom room = new KandyMultiPartyConferenceRoom();
	try
	{
		JSONObject jsonObject = new JSONObject(content);
		room.initFromJson(jsonObject);
	}
	catch (JSONException e)
	{

	}

Leave

When you wish to disconnect from conference you should notify the server about leaving it. To leave the conference you should do the following:

	String conferenceId = "conference_id"; //must be extracted from KandyMultiPartyConferenceRoom with getConferenceId() method after room created

	Kandy.getServices().getMultiPartyConferenceService().leave(conferenceId, new KandyResponseListener()
	{
					
	@Override
	public void onRequestFailed(int responseCode, String err)
		{
			//TODO insert your code here
		}
					
		@Override
		public void onRequestSucceded()
		{
				//TODO insert your code here							
		}
	});

Destroy Room

When you wish to finish the conversation and disconnect the participants you should call destroy room. To destroy room you should do following:

	String conferenceId = "conference_id"; //must be extracted from KandyMultiPartyConferenceRoom with getConferenceId() method after room created

	Kandy.getServices().getMultiPartyConferenceService().destroyRoom (conferenceId, new KandyResponseListener()
	{
					
	@Override
	public void onRequestFailed(int responseCode, String err)
		{
			//TODO insert your code here
		}

		@Override
		public void onRequestSucceded(	)
		{
				//TODO insert your code here							
		}
	});

Get Room Details

Use this API to get the room details:

  • getConferenceRoom include: getConferenceId(), getRoomNumber(), getRoomPinCode(), getRoomPSTNNumber()
  • getCallDuration()
  • getParticipants() includes: getParticipantId(), getCallDuration(), getNickName(), getAudioState(), getVideoState()
  • getAdministrators()
	String conferenceId = "conference_id"; //must be extracted from KandyMultiPartyConferenceRoom with getConferenceId() method after room created

	Kandy.getServices().getMultiPartyConferenceService().getRoomDetails(conferenceId, new KandyMultiPartyConferenceRoomDetailsListener()
	{
		@Override
		public void onRequestFailed(int responseCode, String err)
		{
			//TODO insert your code here
		}

		@Override
		public void onRequestSuceeded(IKandyMultiPartyConferenceRoomDetails roomDetails)
		{
			//TODO insert your code here
		}
	});

Update Participant Actions

Use this API to to control on participants, only the Admin can control on participants. Control types: MUTE, UNMUTE, ENABLE_VIDEO, DISABLE_VIDEO, HOLD, UNHOLD, REMOVE

	String conferenceId = "conference_id"; //must be extracted from KandyMultiPartyConferenceRoom with getConferenceId() method after room created
	String participantId = "participantId"; //must be extracted from KandyMultiPartyConferenceRoom with getParticipants().get(?).getParticipantId() method after room created
	KandyMultiPartyConferenceActionType actionType = KandyMultiPartyConferenceActionType.MUTE; //Action can be MUTE, UNMUTE, ENABLE_VIDEO, DISABLE_VIDEO, HOLD, UNHOLD, REMOVE
			
	//In this API you can update participant actions for multiply participants and multiply actions 
	KandyMultiPartyConferenceParticipantActionParmas participantActionParams = new KandyMultiPartyConferenceParticipantActionParmas(participantId, actionType);
	List<KandyMultiPartyConferenceParticipantActionParmas> participantActionList = new ArrayList<KandyMultiPartyConferenceParticipantActionParmas>();
	participantActionList.add(participantActionParams);
	Kandy.getServices().getMultiPartyConferenceService().updateParticipantActions(conferenceId, participantActionList, new KandyMultiPartyConferenceUpdateParticipantActionsListener() {

		@Override
		public void onRequestFailed(int responseCode, String err) {
			// TODO Auto-generated method stub
	
		}

		@Override
		public void onRequestSuceeded(
				List<KandyMultiPartyConferenceParticipantActionParmas> suceededActionParams,
				List<KandyMultiPartyConferenceParticipantFailedActionParmas> failedActionParams) {
			// TODO Auto-generated method stub
	
		}
	});

Update Participant Name

Use this API to change participant name:

	String conferenceId = "conference_id"; //must be extracted from KandyMultiPartyConferenceRoom with getConferenceId() method after room created
	String participantId = "participantId"; //must be extracted from KandyMultiPartyConferenceRoom with getParticipants().get(?).getParticipantId() method after room created
	String nickname = "new nick name";
	Kandy.getServices().getMultiPartyConferenceService().updateParticipantName(conferenceId, participantId, nickname, new KandyResponseListener() {
		
		@Override
		public void onRequestFailed(int responseCode, String err) {
			// TODO Auto-generated method stub
	
		}

		@Override
		public void onRequestSucceded() {
			// TODO Auto-generated method stub
	
		}
	});

Events

Multi Party Conference Service fires event

Events type:

CONFERENCE_INVITE, CONFERENCE_PARTICIPANT_MUTE,
CONFERENCE_PARTICIPANT_UNMUTE,
CONFERENCE_PARTICIPANT_JOINED_ROOM,
CONFERENCE_PARTICIPANT_LEFT_ROOM,
CONFERENCE_PARTICIPANT_NAME_CHANGE,
CONFERENCE_PARTICIPANT_VIDEO_ENABLE,
CONFERENCE_PARTICIPANT_VIDEO_DISABLED,
CONFERENCE_PARTICIPANT_HOLD,
CONFERENCE_PARTICIPANT_UNHOLD,
CONFERENCE_PARTICIPANT_REMOVED,
CONFERENCE_ROOM_REMOVED

For example:
* KandyEventsType. CONFERENCE_INVITE received by the side that was invited to the conference and contains information about it such as:
* Kandy Record - Initiator
* KandyMultiPartyConferenceRoom - information about room its Id, VoiP number, PSTN number and pin code

In order to receive this event you should implement IKandyMultiPartyConferenceNotificationListener interface and register the listener

	import com.genband.kandy.api.services.mpv.IKandyMultiPartyConferenceNotificationListener;
	import com.genband.kandy.api.services.mpv.KandyMultiPartyConferenceInvite;

	public class MultiPartyConferenceNotificationListener implements IKandyMultiPartyConferenceNotificationListener
	{

		@Override
		public void onInviteRecieved(KandyMultiPartyConferenceInvite arg0)
		{
			// TODO Auto-generated method stub
		}
	}
	MultiPartyConferenceNotificationListener mMultiPartyConferenceNotificationListener = new MultiPartyConferenceNotificationListener();

	}

Register

	Kandy.getServices().getMultiPartyConferenceService().registerNotificationListener(mMultiPartyConferenceNotificationListener);

Unregister

	Kandy.getServices().getMultiPartyConferenceService().unregisterNotificationListener(mMultiPartyConferenceNotificationListener);

Messaging

Messaging services enables you to send/receive text and rich media to/from a single user or a group of recipients.

Make sure to enable Push Notifications to be notified regarding new messages or events when the application isn’t in an active state.

Notifications

In order to receive messaging events e.g. incoming message, etc. make sure to register a listener to receive events.

To register a listener to receive events use the following:

	Kandy.getServices().getChatService().registerNotificationListener(new KandyChatServiceNotificationListener() 
	{
		@Override
		public void onChatReceived(IKandyMessage message, KandyRecordType recordType) 
		{	
			KandyMessageMediaItemType mediaType = message.getMediaItem().getMediaItemType();
			switch (mediaType) {

			case AUDIO:
					//TODO insert your code here
				break;

			case LOCATION:
					//TODO insert your code here
				break;

			case TEXT:
					//TODO insert your code here
				break;

			case IMAGE:
					//TODO insert your code here
				break;

			case CONTACT:
					//TODO insert your code here
				break;

			case VIDEO:
					//TODO insert your code here
				break;
	
			case FILE:
					//TODO insert your code here
				break;
			}
		}   
		@Override
		public void onChatDelivered(List<KandyDeliveryAck> ackEvents)
		{
			// TODO insert your code here	
		}
		
		@Override
		public void onChatRead(List<KandyReadMessage> readEvents);
		{
			// TODO insert your code here	
		}			
		
		@Override
		public void onChatMediaAutoDownloadFailed(IKandyMessage message, int errorCode, String error)
		{
			// TODO insert your code here	
		}
		@Override
		public void onChatMediaAutoDownloadProgress(IKandyMessage message, IKandyTransferProgress progress)
		{
			// TODO insert your code here	
		}
		@Override
		public void onChatMediaAutoDownloadSucceded(IKandyMessage message, Uri path)
		{
			// TODO insert your code here
		}
	});

Send Text Message

To send a text message to a single recipient use the following:

	KandyRecord recipient = null;

	try {
		recipient = new KandyRecord("recipient@domain");
	} catch (KandyIllegalArgumentException ex) {
		//TODO insert your code here
	}

	final KandyChatMessage message = new KandyChatMessage(recipient, "message body");
	Kandy.getServices().getChatService().sendChat(message, new KandyResponseListener() {

		@Override
		public void onRequestFailed(int responseCode, String err) {
			//TODO insert your code here
		}

		@Override
		public void onRequestSucceded() {
			//TODO insert your code here
		}
	});

Send Group Message

To send a message to a group use the following:

	KandyRecord recipient = null;

	try {
		recipient = new KandyRecord("groupID@domain",KandyRecordType.GROUP);
	} catch (KandyIllegalArgumentException ex) {
		//TODO insert your code here
	}

	final KandyChatMessage message = new KandyChatMessage(recipient, "message body");
	Kandy.getServices().getChatService().sendChat(message, new KandyResponseListener() {

		@Override
		public void onRequestFailed(int responseCode, String err) {
			//TODO insert your code here
		}

		@Override
		public void onRequestSucceded() {
			//TODO insert your code here
		}
	});

Send Rich Media Message

In this section, we will cover sending and receiving image, video, audio, files..etc using Kandy. At the end of each sub-section, we will have sample code that shows off this feature.

To send an image (video/audio) message:

As a first step don’t forget to add permission to manifest:

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

Example coe for image sending:

	public static final int IMAGE_PICKER_RESULT = 100000;
	/**
	* Pick image by android default gallery picker
	*/
	private void pickImage() 
	{
		Intent intent = new Intent(Intent.ACTION_PICK);
		intent.setType("image/*");
		startActivityForResult(intent, IMAGE_PICKER_RESULT);
	}
	//Handle the picked image data
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		if (resultCode == RESULT_OK) {
			switch (requestCode) {
			case IMAGE_PICKER_RESULT:
				sendImageMessage(data.getData());
				break;
			}
		}
	}
	/**
	* Send image
	* @param imgUri uri with "content://" scheme also coud be passed uri of the file
	*/
	private void sendImageMessage(Uri uri) 
	{
		KandyRecord recipient = null;
		try {	
			recipient = new KandyRecord("user@domain.com");
		} catch (KandyIllegalArgumentException e) {
			//TODO insert your code here
		}
		IKandyImageItem kandyImage = null;
		try
		{
			kandyImage = KandyMessageBuilder.createImage("put your caption text here", uri);
		}
		catch (KandyIllegalArgumentException e)
		{
			//TODO insert your code here
		}
		final KandyChatMessage message = new KandyChatMessage(recipient, kandyImage);
		Kandy.getServices().getChatService().sendChat(message, new KandyUploadProgressListener() {
			@Override
			public void onRequestFailed(int responseCode, String err) 
			{
				//TODO insert your code here
			}       
			@Override
			public void onRequestSucceded() 
			{
				//TODO insert your code here				
			}
			@Override
			public void onProgressUpdate(IKandyTransferProgress transferProgress)
			{
				// TODO Auto-generated method stub	
			}
		});
	}

To send Video, use:

	IKandyVideoItem kandyVideo = KandyMessageBuilder.createVideo("put your caption text here", uri);

To send Audio, use:

	IKandyAudioItem kandyAudio = KandyMessageBuilder.createAudio("put your caption text here", uri);

To send File, use:

	IKandyFileItem kandyFile = KandyMessageBuilder.createFile("put your caption text here", uri);

To send a Contact (vCard):

Add permission to manifest:

	<user-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
	<user-permission android:name="android.permission.READ_CONTACTS" />

Example code for contact sending:

	public static final int CONTACT_PICKER_RESULT = 100001;
	/**
	* Pick contact by android default contact picker
	*/
	public void pickContact() 
	{
		Intent contactPickerIntent = new Intent(Intent.ACTION_PICK, Contacts.CONTENT_URI);
		startActivityForResult(contactPickerIntent, CONTACT_PICKER_RESULT);
	}
	//Handle the picked image data
	protected void onActivityResult(int requestCode, int resultCode, Intent data) 
	{
		if (resultCode == RESULT_OK) 
		{
			switch (requestCode) {
			case CONTACT_PICKER_RESULT:
				sendContact(data.getData());
				break;
			}
		}
	}
	/**
	* Send the contact - vcard file
	* @param contactUri
	*/
	private void sendContact(Uri contactUri) 
	{
		IKandyContactItem kandyContact = null;
		try
		{
				kandyContact = KandyMessageBuilder.createContact("put your caption text here", contactUri);
		} 
		catch (KandyIllegalArgumentException e)
		{
				//TODO insert your code here 
		}
		KandyRecord recipient = null;
		try { 
			recipient = new KandyRecord("user@domain.com");
		} catch (KandyIllegalArgumentException e) {
			//TODO insert your code here
		}
		final KandyChatMessage message = new KandyChatMessage(recipient, kandyContact);
		Kandy.getServices().getChatService().sendChat(message, new KandyUploadProgressListener() {
			@Override
				public void onRequestFailed(int responseCode, String err) 
			{
					//TODO insert your code here
				}

			@Override
				public void onProgressUpdate(IKandyTransferProgress transferProgress) 
				{
					//TODO insert your code here
				}
				@Override
				public void onRequestSucceded() 
				{
					//TODO insert your code here	
				}
		});
	}

Send Location:

Add permission to manifest:

	<user-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
	<user-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

Example code for location sending:

	/**
	* Retrieves and send current device location via KandySDK
	*/
	private void sendCurrentLocation() throws KandyIllegalArgumentException {
		Kandy.getServices().getLocationService().getCurrentLocation(new KandyCurrentLocationListener() {
			@Override
			public void onCurrentLocationReceived(Location location) {
				sendLocation(location);
			}
			@Override
			public void onCurrentLocationFailed(int errorCode, String error) {
				//TODO insert your code here
			}
		});
	}
	/**
	* Send location
	* @param location location to be sent
	*/
	private void sendLocation(Location location) {
		IKandyLocationItem kandyLocation = KandyMessageBuilder.createLocation("put your caption text here", location);
		KandyRecord recipient =null;
		try {
			recipient = new KandyRecord("user@domain.com");
		} catch (KandyIllegalArgumentException e) {
			//TODO insert your code here
		}

		if(recipient == null)
			return;

		final KandyChatMessage message = new KandyChatMessage(recipient, kandyLocation);
		Kandy.getServices().getChatService().sendChat(message, new KandyUploadProgressListener() {

			@Override
			public void onRequestFailed(int responseCode, String err) {
				//TODO insert your code here		
			}

			@Override
			public void onProgressUpdate(IKandyTransferProgress progress) {
				//TODO insert your code here		
			}

			@Override
			public void onRequestSucceded() {
				//TODO insert your code here
			}
		});
	} 

Send Additional Content:

To send additional data to be sent with the message, use the following:

  • Sender
	JSONObject additionalData = createJSONStub();

	// Set the recipient
	KandyRecord recipient = getRecipient(destination);

	// creating message to be sent
	KandyChatMessage message = new KandyChatMessage(recipient, text);

	// set custom additional data to be sent with the message
	message.getMediaItem().setAdditionalData(additionalData);

	// sending message
	Kandy.getServices().getChatService().sendChat(message, new KandyResponseListener() { }
  • Receiver
  @Override
	public void onChatReceived(IKandyMessage message, KandyRecordType type) {
		JSONObject additionalData  = message.getMediaItem().getAdditionalData();
		Log.d(TAG, "onChatReceived: " + " additionalData: " + additionalData);
	} 

Sending SMS

To send SMS to a regular cellular phone via Kandy SMS out service use the following:

	private void sendSMS() {
		String destination = "972591234567";
		String text = "Hello Worold";

		KandySMSMessage message = null;
		try 
		{
			message = new KandySMSMessage(destination, "Kandy SMS", text);
		} 
		catch (KandyIllegalArgumentException e) 
		{	
			//TODO insert your code here		
		}

		// Sending message
		Kandy.getServices().getChatService().sendSMS(message, new KandyResponseListener() 
		{
			@Override
			public void onRequestFailed(int responseCode, String err) 
			{
				//TODO insert your code here
			}

			@Override
			public void onRequestSucceded() 
			{
				//TODO insert your code here			
			}
		});
	}

Pull Events

To pull pending Chat events from the server, use the following code:

	Kandy.getServices().getChatService().pullEvents(new KandyResponseListener() {

		@Override
		public void onRequestFailed(int responseCode, String err) 
		{
			//TODO insert your code here	
		}

		@Override
		public void onRequestSucceded() 
		{
			//TODO insert your code here
		}
	});

Acknowledging Events

You should respond to KandyChatServiceNotificationListener Chat notifications by acknowledging them; otherwise, you will receive them again as pending events.

For Chat received event acknowledgement use the following:

	private void ack(IKandyMessage message) {
		message.markAsReceived(new KandyResponseListener() {

			@Override
			public void onRequestFailed(int responseCode, String err) {
				//TODO insert your code here
			}

			@Override
			public void onRequestSucceded() {
				//TODO insert your code here
			}
		});
	}

In case, you don���t want to send message acknowledgement manually each time you can configure SDK to do this automatically

	private void enableAutomaticEventsAcknowledgment(boolean enableAutomaticEventsAcknowledgment){
	
		Kandy.getGlobalSettings().setEnableEventsAutomaticAck(enableAutomaticEventsAcknowledgment);
		
	}

Note: By default this feature is enabled.

Download Media

To download media, use the following:

	private void downloadMedia(IKandyMessage message) {
		Kandy.getServices().getChatService().downloadMedia(message, new KandyResponseProgressListener() {

				@Override
				public void onRequestFailed(int responseCode, String err) 
				{
					//TODO insert your code here
				}

			@Override
				public void onRequestSucceded(Uri fileUri) 
				{
					//TODO insert your code here
				}

				@Override
			public void onProgressUpdate(IKandyTransferProgress progress) 
				{
					//TODO insert your code here				
				}
		});
	}

Download Media Thumbnail

To download media thumbnails use the following:

	private void downloadMediaThumbnail(IKandyMessage message, KandyThumbnailSize thumbnailSize) {

		Kandy.getServices().getChatService().downloadMediaThumbnail(message, thumbnailSize, new KandyResponseProgressListener() {

				@Override
				public void onRequestFailed(int responseCode, String err) 
				{
					//TODO insert your code here
				}

				@Override
				public void onRequestSucceded(Uri fileUri) 
				{
					//TODO insert your code here
				}

				@Override
				public void onProgressUpdate(IKandyTransferProgress progress) 
				{
					//TODO insert your code here				
				}
		});
	}

Cancel Operation

To cancel an upload/download operation, associated with a rich message, use the following:

	public void cancelDownloadMessage(IKandyMessage message) {
	
		Kandy.getServices().getChatService().cancelMediaTransfer(message, new KandyResponseCancelListener() {
			@Override
			public void onRequestFailed(int responseCode, String err) {
				//TODO insert your code here
			}
		
			@Override
			public void onCancelSucceded() {
				//TODO insert your code here
			}
		});
	}

Media Settings

  1. Download policy - When to allow the application to download the received media. (3G only, Wi Fi only, Always, Never)
  2. Maximum upload media size - Set the maximum size for uploading media content (in MB)
  3. Auto download thumbnail size - Set the thumbnail size for auto downloaded media (small, medium, large)
  4. Download path for media - Set the location of the downloaded media files
    (NOTE: the default path for downloaded media is /external_storage/Kandy/media/)

To get and set media settings use the following:

	public void setSettings() throws KandyIllegalArgumentException {
		KandyChatSettings settings = Kandy.getServices().getChatService().getSettings();
		settings.setMediaMaxSize(15);
		settings.setAutoDownloadMediaConnectionType(ConnectionType.WIFI);
		settings.setDownloadMediaPath(new File("/path/to/download/directory/"));
		settings.setAutoDownloadThumbnailSize(KandyThumbnailSize.MEDIUM);
	}

Pull history events

To pull all contact history events from last event timestamp use the following:

	/**
	* Get all event history for KandyRecord from last event timeStamp
	* @param destination - the destination KandyRecord contact OR group 
	* @param numberOfEvents - number of messages to return
	* @param timestamp - last event time stamp
	* @param moveBackword -  BACKWORD or FORWARD from time stamp
	* @param listener - notify about operation succeed or failed
	*/

	KandyRecord recipient = new KandyRecord("user destination url");
	int numberOfEventsToPull = 20;
	long timestamp = System.currentTimeMillis();
	boolean movebackword = true;
	Kandy.getServices().getEventsService().pullHistoryEvents(recipient, numberOfEventsToPull, timestamp, moveBackword, new KandyPullHistoryEventsListner() {

	  @override
	  public void onRequestFailed(int arg0, String arg1) {
		//TODO Auto-generated method stub

	  }

	  public void onResponseSucceded(boolean arg0) {
		//TODO Auto-generated method stub

	  }

	}

Get all user conversations

To get all user conversations use the following:


	/**
	 * Get all conversations 
	 * @param listener - notify about operation succeed or failed
	 */

	Kandy.getServices().getEventService().getAllConversations(new KandyAllConversationsListener() {

	  @Override
	  public void onRequestFailed(int arg0, String arg1) {
		//TODO insert your code here
	  }

	  @Override
	  public void onResponseSucceded(IKandySumOfConversation arg0, ArrayList<IKandyConversation> arg1) {
		//TODO insert your code here
	  }
	});

Pull all conversations with messages

To pull all conversations with messages from last event timestamp use the following:

	/**
	* pull all conversations with messages from last event timeStamp
	* @param numberOfEvents - Number of messages to return
	* @param timestamp - last event time stamp
	* @param moveBackword -  BACKWORD or FORWARD from time stamp
	* @param listener - notify about operation succeed or failed 
	*/

	int numberOfEventsToPull = 20;
	long timestamp = System.currentTimeMillis();
	boolean moveBackword = true;

	Kandy.getServices().getEventService().getAllConversationsWithMessages(numberOfEventsToPull, timestamp, moveBackword, new KandyAllConversationWithMessagesListener() {

	@Override
	public void onRequestFailed(int arg0, String arg1) {
	//TODO insert your code here
	}

	@Override
	public void onResponseSucceded(boolean arg0, IKandySumOfConversation arg1, ArrayList<IKandyConversation> arg2) {
	//TODO insert your code here
	}
	});

Delete history events

Use this api to delete message or number of messages that belong to one conversation

	/**
	* Delete history events - delete events in conversation by user or group conversation  
	* @param eventUUIDs - events uuid to delete 
	* @param destination - the user or group that the events is belong to this user or group
	* @param listener
	*/

	ArrayList<String> messages = new ArrayList<String>();
	messages.add("message id");
	KandyRecord destination = new KandyRecord("user uri");
	Kandy.getServices().getEventService().deleteHistoryEvents(messages, destination, new KandyResponseListener() 
	{

	@override
	public void onRequestSucceded() 
	{
	// TODO Auto-generated method stub
	}

	@override
	public void onRequestFailed(int responseCode, String err) 
	{
	// TODO Auto-generated method stub
	}
	});

Delete conversations

Use this api to delete number of conversations

	/**
	* Delete conversations - delete list of conversations 
	* @param destinations - list of users or groups KandyRecored to delete 
	* @param listener
	*/


	ArrayList<KandyRecord> destinations = new ArrayList<KandyRecord>();
	KandyRecord destination = new KandyRecord("user_uri");
	destinations.add(destination);
	Kandy.getServices().getEventService().deleteConversations(destinations, new KandyResponseListener() 
	{

	@override
	public void onRequestSucceded() 
	{
	// TODO Auto-generated method stub
	}

	@override
	public void onRequestFailed(int responseCode, String err) 
	{
	// TODO Auto-generated method stub
	}
	});

Delete all conversations

Use this api to delete all conversations

	/**
		 * Delete all conversations
		 * @param listener
		 */

	Kandy.getServices().getEventService().deleteAllConversations(new KandyResponseListener() 
	{

	@override
	public void onRequestSucceded() 
	{
	// TODO Auto-generated method stub
	}

	@override
	public void onRequestFailed(int responseCode, String err) 
	{
	// TODO Auto-generated method stub
	}
	});

Management of Messaging Groups

Group management service enables to manage your groups and get updates regarding group changes. Make sure to enable Push Notification to be notified regarding new messages or events, when the application isn’t active.

Group Object:

kandyGroup instance of the KandyGroup. This Object contains the group details and members. Its will be return in most group related APIs to ensure you have an update group instance.

Notifications

To be notified regarding chat events e.g. participant joined, left, etc. you need to register a listener to receive events.

	Kandy.getServices().getGroupService().registerNotificationListener(new KandyGroupServiceNotificationListener()
	{
		
		@Override
		public void onParticipantLeft(IKandyGroupParticipantLeft message)
		{
			//TODO insert your code here
			
		}
		
		@Override
		public void onParticipantKicked(IKandyGroupParticipantKicked message)
		{
			//TODO insert your code here
			
		}
		
		@Override
		public void onParticipantJoined(IKandyGroupParticipantJoined message)
		{
			//TODO insert your code here
			
		}
		
		@Override
		public void onGroupUpdated(IKandyGroupUpdated message)
		{
			//TODO insert your code here
			
		}
		
		@Override
		public void onGroupDestroyed(IKandyGroupDestroyed message)
		{
			//TODO insert your code here
			
		}
	});

Create Group

Enables to create a group with name (optional) and image (optional).

The response callback will return the created group object and set you, as the group admin.

Note:some operations may be performed by the group admin only.

	KandyGroupParams params = new KandyGroupParams();
	String name = "My First Group";
	params.setGroupName(name);
	
	Kandy.getServices().getGroupService().createGroup(params, new KandyGroupResponseListener() {

		@Override
		public void onRequestFailed(int responseCode, String error) {
			//TODO insert your code here
		}

		@Override
		public void onRequestSucceded(KandyGroup kandyGroup) {
			//TODO insert your code here			
		}
	});

Add/Remove Group Participants

To add or remove participants from your groups use the following:

	List<KandyRecord> newParticipants = new ArrayList<KandyRecord>();

	try {
		KandyRecord  newParticipant = new KandyRecord("participant@domain");
		newParticipants.add(newParticipant);
	} catch (KandyIllegalArgumentException e) {
		//TODO insert your code here		
	}

	Kandy.getServices().getGroupService().addParticipants(kandyGroup.getGroupId(), newParticipants, new KandyGroupResponseListener() {

		@Override
		public void onRequestFailed(int responseCode, String err) {
			//TODO insert your code here
		}

		@Override
		public void onRequestSucceded(KandyGroup kandyGroup) {
			//TODO insert your code here;
		}
	});

Update Group

To update group name and image by single request use the following:

Note: for separate update each one use: updateGroupName and updateGroupImage APIs

	public static final int IMAGE_PICKER_RESULT = 100002;
	/**
	* Pick image by android default gallery picker
	*/
	private void pickImage() 
	{
		Intent intent = new Intent(Intent.ACTION_PICK);
		intent.setType("image/*");
		startActivityForResult(intent, GROUP_IMAGE_PICKER_RESULT);
	}
	//Handle the picked image data
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {		
		if (resultCode == RESULT_OK) {

			switch (requestCode) {
			case GROUP_IMAGE_PICKER_RESULT:
				updateImage(data.getData());
				break;
			}
		}
	}
	private void updateGroupImage(String groupName, Uri imgUri) {
		KandyGroupParams params = new KandyGroupParams();
		try {
			params.setGroupImageUri(imgUri);
		} catch (KandyIllegalArgumentException e) {
			//TODO insert your code here
		}

		params.setGroupName(groupName);
	
		Kandy.getServices().getGroupService().updateGroup(kandyGroup.getGroupId(), params, 
		new KandyGroupUploadProgressListener() {

			@Override
			public void onRequestFailed(int responseCode, String err) {
				//TODO insert your code here
			}

			@Override
			public void onRequestSucceded(KandyGroup kandyGroup) {
				//TODO insert your code here		
			}

			@Override
			public void onProgressUpdate(IKandyTransferProgress progress) {
				//TODO insert your code here
			}
		}); 
	}

Destroy Group

To destroy a group, use the following:

	Kandy.getServices().getGroupService().destroyGroup(kandyGroup.getGroupId(), new KandyResponseListener() {

		@Override
		public void onRequestFailed(int responseCode, String err) {
			//TODO insert your code here
		}

		@Override
		public void onRequestSucceded() {
			//TODO insert your code here
		}
	});

Get Groups List

To request the list of groups where user admin or/and participant use the following:

	Kandy.getServices().getGroupService().getMyGroups(new KandyGroupsResponseListener() {

		@Override
		public void onRequestFailed(int responseCode, String error) {
			//TODO insert your code here
		}

		@Override
		public void onRequestSucceded(List<KandyGroup> groupList) {
			//TODO insert your code here
		}
	});

Group Details

To get group details by group ID use the following:

	Kandy.getServices().getGroupService().getGroupById(kandyGroup.getGroupId(), new KandyGroupResponseListener() {

		@Override
		public void onRequestFailed(int responseCode, String error) {
			//TODO insert your code here
		}

		@Override
		public void onRequestSucceded(KandyGroup kandyGroup) {
			//TODO insert your code here
		}
	});

Presence

Last Seen

This feature enables to get the last time when the requested user was online.

To get last seen information use the following:

	KandyRecord user = null;
	try {
		user = new KandyRecord("username@domain");
	} catch(KandyIllegalArgumentException e) {
		//TODO insert your code here
	}

	KandyRecord user_1 = null;
	try {
		user_1 = new KandyRecord("username_1@domain");
	} catch(KandyIllegalArgumentException e) {
		//TODO insert your code here
	}

	ArrayList<KandyRecord> list = new ArrayList<KandyRecord>();
	list.add(user);
	list.add(user_1);

	Kandy.getServices().getPresenceService().retrievePresence(list, new KandyPresenceResponseListener() {
	
		@Override
		public void onRequestFailed(int responseCode, String err) {
			//TODO insert your code here
		}
	
		@Override
		public void onRequestSucceed(ArrayList<IKandyPresence> presences, ArrayList<KandyRecord> missingRecords) {
			//TODO insert your code here
		}
	});

Location

Country Info

You can receive country codes based on the device location information (SIM and IP Address).

To get a location-based country code use the following:

	Kandy.getServices().getLocationService().getCountryInfo(new KandyCountryInfoResponseListener() {

		@Override
		public void onRequestFailed(int responseCode, String err) {
			//TODO insert your code here
		}

		@Override
		public void onRequestSuccess(IKandyAreaCode response) {
			//TODO insert your code here
		}
	});

Current Location

You can receive the current device location, based on GPS/Network info.

Add the following permission to the manifest:

	<uses-permission android:name="android.permissions.ACCESS_COARSE_LOCATION" />
	<uses-permission android:name="android.permissions.ACCESS_FINE_LOCATION" />

To get the current location use the following:

	public void getCurrentLocation() throws KandyIllegalArgumentException 
	{
		Kandy.getServices().getLocationService().getCurrentLocation(new KandyCurrentLocationListener() {
		
			@Override
			public void onCurrentLocationReceived(Location location) {
				//TODO insert your code here
			}		
		   
			@Override
			public void onCurrentLocationFailed(int arg0, String arg1) {
				//TODO insert your code here
			}
		});
	}

Push Notifications

Push Notifications services enables to receive and handle notifications.

Preconditions

To enable push service and receive push notifications you must to implement Android’s Push notification mechanism GCM - see link: https://developer.android.com/google/gcm/client.html.

After the Push mechanism implementation was completed, contact Kandy Customer Support in case you would like to use your own credentials.

Enabling Notifications

To enable your device to receive push notifications pass to SDK the registrationID. The registrationID you will get after your app has been registered with your SENDER_ID(PROJECT_ID) with GCM Servers.

To enable Kandy push notifications use the following:

	/**
	 * Sends the registration ID to your server over HTTP, so it can use GCM/HTTP
	 * or CCS to send messages to your app. Not needed for this demo since the
	 * device sends upstream messages to a server that echoes back the message
	 * using the 'from' address in the message.
	 */
	private void sendRegistrationIdToBackend() {
		// Your implementation here.
		Kandy.getServices().getPushService().enablePushNotification("registrationId", new KandyResponseListener() {

				@Override
				public void onRequestFailed(int responseCode, String err) {
					//TODO insert your code here
				}
	
			 @Override
				public void onRequestSucceded() {
					//TODO insert your code here
				}
		});
	}

Handling Notifications

After the users are logged in, they can handle Kandy notifications.

To handle Kandy SDK push notification Override and put into protected void onMessage(Context context, Intent intent) method in class, which extends the GCMBaseIntentService next API call.

	Kandy.getServices().getPushService().handlePushNotification(context, intent, new KandyResponseListener() {
		
		@Override
		public void onRequestFailed(int responseCode, String err) {
			//TODO insert your code here
		}
		
		@Override
		public void onRequestSucceded() {
			//TODO insert your code here
		}
	});

Note: If you’re using FCM use the below API to handle received push

	
	public class FCMService extends FirebaseMessagingService {
		@Override
		public void onMessageReceived(RemoteMessage remoteMessage)
		{
			Map<String, String> notificationData = remoteMessage.getData();
			Kandy.getServices().getPushService().handlePushNotification(context, notificationData, new KandyResponseListener() {	
				@Override
				public void onRequestFailed(int responseCode, String err) {
					//TODO insert your code here
				}		
				@Override
				public void onRequestSucceded() {
					//TODO insert your code here
				} 
			});
		}
	}

	

Disable Notifications

If you are willing to stop receiving push notifications, call the following API:

Kandy.getServices().getPushService().disablePushNotification(new KandyResponseListener() {

  @Override
  public void onRequestFailed(int responseCode, String err) {
    // TODO insert your code here
  }

  @Override
  public void onRequestSucceded() {
    // TODO insert your code here
  }
});

Contacts

The Contacts service enables you to access the device address book and the domain directory, retrieve and filter contacts and get notification on changes to the device address book.

Notifications

In order to receive local address book related events, you need to register a listener to receive such events.

To create a listener object use the following:

	private KandyAddressBookServiceNotificationListener mNotificationListener = new KandyAddressBookServiceNotificationListener()
	{

		@Override
		public void onDeviceAddressBookChanged()
		{
			//TODO insert your code here
		}
	};

To enable address book notifications use the following:

	Kandy.getServices().getAddressBookService().registerNotificationListener(mNotificationListener);

To stop address book notifications use the following:

	Kandy.getServices().getAddressBookService().unregisterNotificationListener(mNotificationListener);

Device AddressBook Contacts

This API requires android.permission.READ_CONTACTS. Add the following lines to your manifest.xml file:

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

To retrieve the local device contacts use the following:

Note: Optionally, you can add a filter (see below) to get contacts according to the contact fields like: email, phone, etc.

	KandyDeviceContactsFilter[] items = new KandyDeviceContactsFilter[] {KandyDeviceContactsFilter.ALL};
	Kandy.getServices().getAddressBookService().getDeviceContacts(items, new KandyDeviceContactsListener()
	{
		@Override
		public void onRequestFailed(int responseCode, String err)
		{
			//TODO insert your code here
		}
		@Override
		public void onRequestSucceded(final List<IKandyContact> contacts)
		{
			//TODO insert your code here
		}
	});

Retrieving Domain Directory Contacts

The following method returns the domain directory contacts as IKandyContact objects. If the operation failed, it returns an error.

	Kandy.getServices().getAddressBookService().getDomainDirectoryContacts(new KandyDeviceContactsListener() {
		
		@Override
		public void onRequestFailed(int responseCode, String err) {
			// TODO insert your code here
		}
		
		@Override
		public void onRequestSucceded(final List<IKandyContact> contacts) {
			// TODO insert your code here
		};
	});

Filtering Domain Directory Contacts

The following method returns the filtered domain directory contacts as IKandyContact objects. If the operation fails, it returns an error.

Filtering is done according to specified text string, a KandyDomainContactFilter enum indicates which fields to filter and the Boolean specifies whether the filtering is case sensitive. Filtering of the fields logic is achieved by using ���contains���.

	Kandy.getServices().getAddressBookService().getFilteredDomainDirectoryContacts(KandyDomainContactFilter.ALL, false, "searchString",
	new KandyDeviceContactsListener() {
		
		@Override
		public void onRequestFailed(int responseCode, String err) {
			// TODO insert your code here
		}

		@Override
		public void onRequestSucceded(final List<IKandyContact> contacts) {
			// TODO insert your code here
		}
	});

Cloud Storage

Cloud storage service allows you to upload/download files to Kandy cloud storage. For supported file formats see android documentation MediaMimeType.

Note:Maximum supported file size is 20Mb.

Upload Media

To upload file to the cloud storage use the following:

	private void uploadFile(final Uri fileToUploadUri)
	{
		IKandyFileItem kandyFileItem = KandyMessageBuilder.createFile("",fileToUploadUri);
		uploadFile(kandyFileItem);
	}
	private void uploadFile(final IKandyFileItem kandyFileItem)
	{
	Kandy.getServices().geCloudStorageService().uploadMedia(kandyFileItem , new KandyUploadProgressListener()
		{	
				@Override
				public void onRequestFailed(int responseCode, String err)
				{
							//TODO insert your code here
				}
		
				@Override
				public void onRequestSucceded()
				{
					//File upload succeeded, extract server uuid to have access to it in the future				
					UUID fileServerUUID = kandyFileItem.getServerUUID();					    
						//TODO insert your code here
				}
		
				@Override
				public void onProgressUpdate(IKandyTransferProgress progress)
				{
			//TODO insert your code here
				}
	});
	}

Download Media

To download file from the cloud storage use the following:

	private void downloadFile (final UUID fileToDownloadUUID, final fileStorageDestinationURI)
	{
		IKandyFileItem kandyFileItem = KandyMessageBuilder.createFile("",fileStorageDestinationURI);
		kandyFileItem.setServerUUID(serverDataUri);
	}
	private void downloadFile(final IKandyFileItem kandyFileItem)
	{
	Kandy.getServices().geCloudStorageService().downloadMedia(kandyFileItem , new KandyUploadProgressListener()
		{	
				@Override
				public void onRequestFailed(int responseCode, String err)
				{
							//TODO insert your code here
				}
	
				@Override
				public void onRequestSucceded()
				{
							//TODO insert your code here
				}
	
				@Override
				public void onProgressUpdate(IKandyTransferProgress progress)
				{
			//TODO insert your code here
				}
	});
	}

Download Media Thumbnail

To download media thumbnail from the cloud storage use the following:

	private void downloadMediaThumbnail(final UUID fileToDownloadUUID, final fileStorageDestinationURI)
	{
		IKandyFileItem kandyFileItem = KandyMessageBuilder.createFile("",fileStorageDestinationURI);
		kandyFileItem.setServerUUID(serverDataUri);
	}

	private void downloadMediaThumbnail(final IKandyFileItem kandyFileItem)
	{
	Kandy.getServices().geCloudStorageService().downloadMediaThumbnail(kandyFileItem , KandyThumbnailSize.SMALL, 
	new KandyUploadProgressListener()
				{
					@Override
					public void onRequestFailed(int responseCode, String err)
					{
							//TODO insert your code here
					}
	
					@Override
					public void onRequestSucceded()
					{
							//TODO insert your code here
					}
	
					@Override
					public void onProgressUpdate(IKandyTransferProgress progress)
					{
					//TODO insert your code here
					}
	});
	}

Cancel Media Tranfer

To cancel media transfer use the following:

	// Use kandyFileItem fom the file ransfer process you willing to cancel
	private void cancelMediaTransfer (final IKandyFileItem kandyFileItem)
	{
	Kandy.getServices().geCloudStorageService().cancelMediaTransfer (kandyFileItem, 
	new KandyResponseCancelListener ()
				{
					@Override
					public void onRequestFailed(int responseCode, String err)
					{
							//TODO insert your code here
					}
	
					@Override
					public void onCancelSucceded ()
					{
							//TODO insert your code here
					}
	});
	}

Profile

The Profile service API can be used to query more information about the user, and personalize the experience further.

Get profile details

Retrive my profile details

	Kandy.getServices().getProfileService().getUserProfile(new KandyUserProfileResposeListener() {

		@Override
		public void onRequestFailed(int responseCode, String err) {
			//The request to get profile is failed
		}

		@Override
		public void onRequestSuccess(KandyUserProfileParams kandyUserProfileParams) {
			//The request to get profile is succeed
			UUID profileImageServerId = kandyUserProfileParams.getProfileImageServerId();
			String profileName = kandyUserProfileParams.getUserProfileName();

			if (!TextUtils.isEmpty(profileName))
			{
				//need to check if the profileName != null
			}

			if(profileImageServerId != null)
			{
				//need to check if the profileImageServerId != null
			}
		}
	});

Get user profile data for other users:


	List<KandyRecord> records = new ArrayList<>();
	try {
		records.add(new KandyRecord("user1@domain"));
		records.add(new KandyRecord("user2@domain"));
	} catch (KandyIllegalArgumentException e) {
		//user id is wrong
		e.printStackTrace();
	}

	Kandy.getServices().getProfileService().getUserProfiles(records, new KandyUsersProfileResposeListener() {

		@Override
		public void onRequestFailed(int responseCode, String err) {
			//the request to get user profiles is failed
		}

		@Override
		public void onRequestSuccess(List<KandyUserProfileParams> UserProfileList) {
			//the request to get user profiles is succeed

			if (UserProfileList != null && !UserProfileList.isEmpty()) {
				for (KandyUserProfileParams param : UserProfileList) {

					UserId userId = UserIdHelper.fromKandyRecord(param.getFullUserID());
					UUID profileImageServerId = param.getProfileImageServerId();
					String profileName = param.getUserProfileName();

				}
			}
		}
	});

Update profile details

Update my profile image and name

	Uri profileImage = Uri.parse("uri profile image");
	String profileName = "profile name";

	KandyUserProfileParams userProfileParams = new KandyUserProfileParams();
	userProfileParams.setUserProfileDisplayName(profileName);
	try {
	   userProfileParams.setProfileImageUri(profileImage);
	} catch (KandyIllegalArgumentException e) {
	   //ERROR: profile image uri is wrong
	}

	Kandy.getServices().getProfileService().updateProfile(userProfileParams, new KandyResponseListener() {
	   @Override
	   public void onRequestFailed(int responseCode, String err) {
		  //update profile is failed
	   }

	   @Override
	   public void onRequestSucceded() {
		  //update profile is succeded
	   }
	});

Reference Application

Kandy Android SDK package includes a sample application and its source code, which implements the basic services and functions outlined above.

You can quickly get started by copying code sections from this application into your own.

You can also use it for sanity testing when your application under development goes wrong or fails to operate as expected.

This application can be found in the Code section, here.