Rich Content

If a Message Part contains a large amount of content (> 2KB), it will be sent as rich content instead. This has no effect on how you send a Message.

Sending Rich Content

Sending large messages works the same way as standard messages:

// Creates a message part with an image and sends it to the specified conversation
public void sendImage(Bitmap imageBitmap, Conversation conversation, LayerClient layerClient) {

    // Extract the byte data
    ByteArrayOutputStream stream = new ByteArrayOutputStream();
    imageBitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
    byte[] imageData = stream.toByteArray();

    // Add the message part to a message and send it with a ProgressListener
    MessagePart messagePart = layerClient.newMessagePart("image/jpeg", imageData);
    Message message = layerClient.newMessage(Arrays.asList(messagePart));
    conversation.send(message, new MyProgressListener());

Receiving Rich Content

There are some differences in how such a Message would be received:

Once the rich content has been downloaded, it can be filtered by its MIME type and handled appropriately.

public void displayImage(Message message, ImageView imageView) {
	// Look for a message part with an image MIME type
	for (MessagePart part : message.getMessageParts()) {
            switch (part.getMimeType()) {
                case "image/jpeg":
                	MessagePart.TransferStatus status = part.getTransferStatus();

                	// If it's ready, render the image from the message part
                	if(!((status == MessagePart.TransferStatus.READY_FOR_DOWNLOAD) || (status == MessagePart.TransferStatus.DOWNLOADING))) {
                        // NOTE: getData() should be called off the UI thread
                        Bitmap imageMsg = BitmapFactory.decodeByteArray(part.getData(), 0, part.getData().length);

Monitoring transfer progress

As Rich Content may involve upload of large files, being able to monitor the progress of sending these Messages can be significant. You can access the progress of any message part upload (while sending) or download (while receiving) via its progress.

There are two ways to get progress. You could either either include a LayerProgressListener when you send the message (see code above), or register a progress listener class:

public class MyProgressListener implements LayerProgressListener {

    public void onProgressStart(MessagePart part, Operation operation) {
        System.out.println("Message part started " + operation.toString());

    public void onProgressUpdate(MessagePart part, Operation operation, long bytes) {
        // You can calculate the percentage complete based on the size of the Message Part
        float pctComplete = bytes / part.getSize();

        // Use this to update any GUI elements associated with this Message Part
        System.out.println(operation.toString() + " Percent Complete: " + pctComplete);

    public void onProgressComplete(MessagePart part, Operation operation) {
        System.out.println("Message part finished " + operation.toString());

    public void onProgressError(MessagePart part, Operation operation, Throwable e) {
        System.out.println("Message part error " + operation.toString());

onProgressUpdate is called with a long argument representing the transfer progress, ranging from 0.0 to 1.0.

Transfer status

MessagePart objects provide a TransferStatus property, which can be one of five values:

  • AWAITING_UPLOAD: The content has been saved in the local queue but hasn’t had a chance to start uploading yet
  • UPLOADING: Content is currently uploading
  • READY_FOR_DOWNLOAD: Content is fully uploaded and ready on Layer servers but hasn’t had a chance to start downloading to the device yet
  • DOWNLOADING: Content is currently downloading
  • COMPLETE: Content has finished uploading or downloading

The TransferStatus value is useful for certain use cases, such as only showing fully-downloaded messages. It is queryable.

Announcements Querying