In this article, we will learn to send long SMS using the cloudhopper SubmitSm. In this article, we use Charset GSM (7bit), which means we will split the message if the length of the message is greater than 160 characters.
GSM-7 is a character encoding standard that packs the most commonly used letters and symbols in many languages into 7 bits each for usage on GSM networks.
private String sendTextMessage(SmppSession session, String sourceAddr, String message
, String toMobile) throws IllegalStateException {
String messageId = "";
if (session.isBound()) {
try {
byte[] textBytes = CharsetUtil.encode(message, CharsetUtil.CHARSET_GSM);
if (textBytes != null && textBytes.length > 160) {
int maximumMultipartMessageSegmentSize = 152;
byte[] byteSingleMessage = textBytes;
byte[][] byteMessagesArray = splitUnicodeMessage(byteSingleMessage, maximumMultipartMessageSegmentSize);
// submit all messages
for (int i = 0; i < byteMessagesArray.length; i++) {
SubmitSm submit = new SubmitSm();
submit.setEsmClass(SmppConstants.ESM_CLASS_UDHI_MASK);
submit0.setRegisteredDelivery(SmppConstants.REGISTERED_DELIVERY_SMSC_RECEIPT_REQUESTED);
submit.setSourceAddress(new Address((byte) 0x05, (byte) 0x01, sourceAddr));
submit.setDestAddress(new Address((byte) 0x01, (byte) 0x01, toMobile));
submit.setShortMessage(byteMessagesArray[i]);
SubmitSmResp submitResponse = session.submit(submit, 10000);
if (submitResponse.getCommandStatus() == SmppConstants.STATUS_OK) {
messageId += " "+submitResponse.getMessageId();
LOGGER.info("Long SMS submitted, response is {}, response message id {}", submitResponse.getResultMessage()
, submitResponse.getMessageId());
} else {
throw new IllegalStateException(submitResponse.getResultMessage());
}
}
}
} catch (RecoverablePduException e) {
throw new IllegalStateException(e);
} catch (UnrecoverablePduException e) {
throw new IllegalStateException(e);
} catch (SmppTimeoutException e) {
throw new IllegalStateException(e);
} catch (SmppChannelException e) {
throw new IllegalStateException(e);
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
return messageId;
}
throw new IllegalStateException("SMPP session is not connected");
}
public static byte[][] splitUnicodeMessage(byte[] aMessage, Integer maximumMultipartMessageSegmentSize) {
final byte UDHIE_HEADER_LENGTH = 0x06;
final byte UDHIE_IDENTIFIER_SAR = 0x08;
final byte UDHIE_SAR_LENGTH = 0x04;
// determine how many messages have to be sent
int numberOfSegments = aMessage.length / maximumMultipartMessageSegmentSize;
int messageLength = aMessage.length;
if (numberOfSegments > 255) {
numberOfSegments = 255;
messageLength = numberOfSegments * maximumMultipartMessageSegmentSize;
}
if ((messageLength % maximumMultipartMessageSegmentSize) > 0) {
numberOfSegments++;
}
// prepare array for all of the msg segments
byte[][] segments = new byte[numberOfSegments][];
int lengthOfData;
// generate new reference number
byte[] referenceNumber = new byte[2];
new Random().nextBytes(referenceNumber);
// split the message adding required headers
for (int i = 0; i < numberOfSegments; i++) {
if (numberOfSegments - i == 1) {
lengthOfData = messageLength - i * maximumMultipartMessageSegmentSize;
} else {
lengthOfData = maximumMultipartMessageSegmentSize;
}
// new array to store the header
segments[i] = new byte[7 + lengthOfData];
// UDH header
// doesn't include itself, its header length
segments[i][0] = UDHIE_HEADER_LENGTH;
// SAR identifier
segments[i][1] = UDHIE_IDENTIFIER_SAR;
// SAR length
segments[i][2] = UDHIE_SAR_LENGTH;
// reference number (same for all messages)
segments[i][3] = referenceNumber[0];
segments[i][4] = referenceNumber[1];
// total number of segments
segments[i][5] = (byte) numberOfSegments;
// segment number
segments[i][6] = (byte) (i + 1);
// copy the data into the array
System.arraycopy(aMessage, (i * maximumMultipartMessageSegmentSize), segments[i], 7, lengthOfData);
}
return segments;
}
Here we have encoded the message using the Charset GSM7 and checked if the length of the byte array is > 160, if yes then we will send the message as a long SMS by splitting the message into chunks and adding headers (UDH) before every message. If the length is not > 160, we will continue sending it as normal SMS.
Let’s discuss the UDH headers which are going to be added before every chunk of the long message.
The first part of the UDH header we have added is – UDHIE_HEADER_LENGTH, which tells that the next length of bytes will be read as the UDH header. So in our case, the value Is 0x06, which tells that the next 6 bytes are reserved for the UDH header.
In the 2nd part, UDHIE_IDENTIFIER_SAR, the value in the 2nd byte tells that the Ref Number is 1 byte or 2 bytes. Here 0x00 value must be used if the length of the reference number is 1 byte and the 0x08 value must be used if the length of the reference number is 2 bytes.
Now the 3rd part, UDHIE_SAR_LENGTH, the value in the 3rd byte can be 0x03 or 0x04. 0x03 value must be used if the length of the reference number is 1 byte and the 0x04 value must be used if the length of the reference number is 2 bytes.
Now if we have chosen to go with 1-byte reference number then the next byte value in the UDH header is the reference numberand if we have chosen to go with 2-byte Ref number then the next 2 bytes is the value of the reference number. The reference number is auto-generated random number bytes, which is used to uniquely identify the group of split messages in the case of long messages.
Now the next byte of the UDH will tell the total number of segments in which the message is split.
Now the last byte of the UDH header will tell the segment number of the split messages.