Secure Messaging SDK for Android

Add secure messaging into any app

The IDENTOS Secure Messaging SDK provides you a full featured messaging app, in which all data transmitted is encrypted by default. Users can send and receive text messages, images, and documents, as well as view, and organized their contacts. This is a simple way to integrate secure messaging into your existing solution.

Main functions of the SDK:

Authenticate & Authorize
IDENTOS provides the ability to enforce a PIN entry upon application launch to ensure the user is authenticated. This PIN helps to secure the user's private key which is used to protect data and digitally sign requests for keys. The PIN can be set to 0 to disable PIN Required as a feature, however this is not recommended.

Control access to data
Encrypt and decrypt any given piece of data, grant users access to the encryption keys, and maintain compliance by logging every request for data and keys.

Enable users to communicate securely
With all messages automatically encrypted and stored securely, users can communicate worry free, even in sensitive industries like healthcare, finance, and government.

Getting Started

Download the SDK

Contact us to request the SDK

Install (Android Studio)

Add the .aar archive file for securemessagingsdk to your project. To do this in Android Studio:

1. Click File > New > New Module
2. Click Import .JAR/.AAR Package then click Next
3. Enter the location of the securemessagingsdk.aar file then click Finish.

To add as a dependency to any of your modules:

1. Right click on your module and select 'Open Module Settings'
2. Navigate to the dependencies tab and click on the '+' button, select module dependency
3. Select the securemessaging module in the 'Choose Module' window

Initialize the SDK

You can find your appId and clientKey on your app’s admin page.

/**
* This method initializes the SecureMessaging for this android application instance, it does
* this with the application context and the secure messaging configuration. This is where sqlite
* database for the app and Identos security functionality is initialized for the app.
* This method should always be called first before any other Secure Messaging method to avoid
* invalid state errors. Note that this method works aynchronously.
* @param context application context for current app instance, cannot be null.
* @param config securemessaging config contains app credentials, cannot be null.
*/
public void initialize(Context context, SecureMessagingConfig config)

Example

SecureMessagingConfig config = new SecureMessagingConfig();
config.setAppId(APP_ID);
config.setClientKey(CLIENT_KEY);
config.setAppVersion(APP_VERSION);

SecureMessaging.getInstance().initialize(getApplicationContext(), Utils.getMessagingConfig());

For cases where the results of the initialization call are needed:

1. The calling class must implement the InitializaCallback interface and provide an implementation for the onInitializeTaskComplete method
2. Call the initialize method with the calling class as an argument. The initialize operation is carried out asynchronously on a separate thread and on completion the onInitializeTaskComplete method of the calling class is invoked with the results of the initialization as arguments

Example

public class MessageActivity implements InitializeCallback{

protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

SecureMessaging.getInstance().initialize(getApplicationContext(), Utils.getMessagingConfig(), this);

}

/**
* @param status enum, representing the status of the Secure messaging sdk instance, not null.
* @param error if sqlite database or identos initialization fails.
*/
@Override
public void onInitializeTaskComplete(Status status, SMError error){

switch (status){

case: SecureMessaging.Status.FAILED
//initialization call failed
break;
case: SecureMessaging.Status.SUCCESS
//Initialization call completed successfully.
break;
case: SecureMessaging.Status.DEVICEUNREGISTERED
//Initialization failed, identos keys for user has been disabled.
break;
case: SecureMessaging.Status.DEVICEWIPED
break;

}

}

}

Authenticating the User

Logging In

/**
* Log-in user with email or username and password after which pin for the user is set. The user
* pin set as this point will be used for future authentication operations. Note that this method
* works asynchronously and will call the onLoginTaskComplete} method of the supplied callback
* with the result of the login operation when it is done.
* @param email user email or username, cannot be null.
* @param password user password, cannot be null.
* @param pin user pin, value supplied here will be used for authentication, cannot be null.
* @param loginCallBack callback for returning the results of the login call.
*/
public void loginUserWithEmail(final String email, final String password, final String pin, final LoginCallBack loginCallBack)

Authentication

/**
* Authenticates user by comparing entered pin with already set pin.
* @param pin user pin, cannot be null.
* @param authCallBack callback for returning results of the authentication operation.
*/
public void authenticate(final String pin, final AuthCallBack authCallBack)

Channels

Private Channels

/**
* Creates a chat(channel). This method works synchronously.
* @param channelName name of channel, cannot be null.
* @param uniqueId unique id for channel, cannot be null.
* @param contacts list of contacts to be added to this channel, cannot be null.
*/
public Channel createPrivateChannel(String channelName, String uniqueId, List<Contact> contacts) throws SMException

Sending & Receiving Messages

Sending to a Channel

 /**
* Post message into this channel. This method is synchronous and should not be called on the
* UI thread as it makes a network call.
* @param message text to be posted into channel, not null.
* @return Message object representing message that was posted into channel, null if post call fails.
* @throws SMException in the case of network error or database error.
*/
public Message postMessage(String message) throws SMException

Example

/**
* Post the message in a background thread, then update the UI with the message
*/
class PostMessageAsyncTask extends AsyncTask<String, Void, Message>{

....

public PostMessageAsyncTask(String message) {
messageTxt = message;
}

@Override
protected Message doInBackground(String... params) {

Message message = null;

try {
message = channel.postMessage(messageTxt);
}catch (SMException e){
Log.e(TAG, "Unable to post message", e);

}

return message;
}

@Override
protected void onPostExecute(Message message){

//update UI
}
}

Receiving from a Channel

/**
* Fetch, from server, the new messages for this channel since the last time messages for this channel
* were fetched. This method is synchronous and should not be called on the
* UI thread as it makes a network call.
* @return Messages arraylist, empty if there are no new mmessages, null if call fails.
* @throws SMException in the case of network or database error.
*/
public List<Message> fetchMessages() throws SMException

Example

/**
* fetch messages from the server.
* When finished update the UI.
*/
class MessageFetchAsyncTask extends AsyncTask<Void, Void, List<Message>>{

private Channel channel;
MessageFetchAsyncTask(Channel channel){
this.channel = channel;
}

@Override
protected List<Message> doInBackground(Void... params) {

try {
return channel.fetchMessages();
}catch (SMException e){
Log.e(TAG, "Unable to fetch messages", e);
//TODO Error alog
}
return new ArrayList<Message>();
}

@Override
protected void onPostExecute(List<Message> messages){

//update UI
}
}

Sending & Receiving Files

Sending to a Channel

/**
* Post file into this channel. This method is synchronous and should not be called on the
* UI thread as it makes a network call.
* @param data content of the file in bytes.
* @param fileName name of the file to be posted
* @param mimeType A MIME type for the file.
* @return File object representing the file posted into the channel
* @throws SMException in the event of network error or database error.
*/
public File postFile(byte[] data, String fileName, String mimeType) throws SMException

Example

try {
File file = channel.postFile(decryptedData, fileName, mimeType);
} catch(SMException e) {
e.printStackTrace();
}

Receiving from a Channel

//**
* Fetch, from server, the files for this channel since the last time files for this
* channel were fetched.This method is synchronous and should not be called on the UI thread
* as it makes a network call.
* @return Files arraylist, empty if there are no new mmessages, null if call fails.
* @throws SMException in the event of a network or database error
*/

public List<File> fetchFiles() throws SMException

Example

try {
List<File> files = channel.fetchFiles();
} catch(SMException e) {
e.printStackTrace();
}

Contacts

Update Contacts from API

Update the list of contacts for the user from the API

 /**
* Fetch the current user's contacts from the server. This method is a synchronous method that
* makes a network call and as such should not be called on the UI thread.
* @return Contact arraylist, not null.
* @throws SMException in the case of network error or database error.
*/
public List<Contact> refreshContacts()throws SMException

Example

try {
List<Contact> contacts = user.refreshContacts();
} catch(SMException e) {
e.printStackTrace();
}

Update the list of contacts online status

/**
* Fetches the statuses for every contact for this user and updates the contact status. To get the
* status for a particular contact, getOnlineStatus method must be called for that contact.
* This method should not be called on the main thread as it makes a network call.
* @returns void
* @throws SMException in the event of a network error or database error
*/
public void getContactsOnlineStatus() throws SMException

Example

try {
user.getContactsOnlineStatus();
OnlineStatus status = contact.getOnlineStatus();
} catch(SMException e) {
e.printStackTrace();
}

Get All (Non-System) Contacts

Get a list of all users contacts from the user object

/**
* gets this user's contacts from the database and removes the user's personal contact and system
* contact from the list. No network calls made here, method can be called on UI thread.
* @return Contact arraylist, not null.
* @throws SMException in the case of database error.
*/
public List<Contact> getContactsNoSystem() throws SMException

Status

Update the user's online status

/**
* Update user online status on server
* @param status new online status for the current user
* @throws SMException in the case of a network error
*/
public void changeUserStatus(OnlineStatus status) throws SMException

Example

try {               
currentUser.changeUserStatus(OnlineStatus.ONLINE);
}catch (SMException e) {
Log.e(TAG, "Unable to change user status", e);
}

Receiving Through Sockets

Setting up an SMAPIListener

Your class must implement the SMAPIListener interface and override the handleSMAPIEvent method.

Example

public class MessageActivity implements SMAPIListener{

....

/**
* Invoked when a secure messaging event occurs.
* @param event object representing the event that occurred.
*/
@Override
public void handleSMAPIEvent(final SMAPIEvent event) {

switch (event.eventType){
case NEWMESSAGE:
//new message event
break;
case CHANNELUPDATED:
//a chanel has been updated
break;
case PROFILEUPDATED:
//contact profile changed
break;
case STATUSUPDATED:
//online status changed
break;
case CONNECTERROR:
//socket connection has an error
break;
}
}
}

Register the class as a listener with the SDK using the SecureMessaging addListener method

**
* register a secure messaging event listener for events.
* @param listener any class that implements the {@link SMAPIListener} interface
*/
public void addListener(SMAPIListener listener)

To unsubscribe a class from receiving SMAPIEvent from the SDK the SecureMessaging removeListener method should be called.

/**
* unregister a secure messaging event listener.
* @param listener any class that implements the {@link SMAPIListener} interface
*/
public void removeListener(SMAPIListener listener)