Send Data SMS to Subscriber
This part of the SMS API enables a third party to send data (binary) SMSes to a subscriber. Data messages are used to let applications talk to each other without requiring data network access, or where the data network is unreliable.
The same type of SMS messages are also used for a number of other network specific and SIM related management, and this both have more options than sending text messages, and more restrictions.
To see what can be set as the sender address consult the API for Sending text SMS to subscriber.
Note that some device receiver applications have stricter requirements on
the message than common text SMS apps. E.g. many APN
config update apps
have stricter limits to the length and formatting of the sender address, e.g
allows max 22 chars.
Fragmentation And Udh
We do not allow callers to the API to freely set the UDH (User Data Header) themselves. If the content
data is longer
than 140
bytes (or 133
bytes if application port it set), we will fragment the message the same way as with
other messages to subscriber, and application port is set from
the request if provided.
Prerequisites
Required Scope
sms.data:send_to_subscriber
is required to use the API function.
Code Dependencies
<dependency>
<groupId>com.wgtwo.api.v1.grpc</groupId>
<artifactId>sms</artifactId>
<version>1.10.1</version>
</dependency>
Code
If targeting production, you would need to add authentication to the sample code.
#!/usr/bin/env bash
grpcurl \
-d @ \
sandbox.api.shamrock.wgtwo.com:443 \
wgtwo.sms.v1.SmsService/SendDataToSubscriber <<EOM
{
"content": "U2FtcGxlIENvbnRlbnQ=",
"toSubscriber": "+4799990000",
"fromAddress": "MyProduct",
"messageClass": "MESSAGE_CLASS_ME_SPECIFIC",
"applicationPort": {
"originatorPort": 1349,
"destinationPort": 1349
}
}
EOM
package com.example.sms
import com.google.protobuf.ByteString
import com.wgtwo.api.v1.sms.SmsProto.MessageClass
import com.wgtwo.api.v1.sms.SmsProto.SendDataToSubscriberRequest
import com.wgtwo.api.v1.sms.SmsServiceGrpc
import io.grpc.ManagedChannelBuilder
fun main(vararg args: String) {
val channel = ManagedChannelBuilder.forAddress("sandbox.api.shamrock.wgtwo.com", 443).build()
val stub = SmsServiceGrpc.newBlockingStub(channel)
val content: ByteString = ByteString.copyFrom("Hello, World!".toByteArray())
val request = SendDataToSubscriberRequest.newBuilder().apply {
this.fromAddress = "MyProduct"
this.toSubscriber = "+4799999999"
this.content = content
// The parts below depends on your application needs.
messageClass = MessageClass.MESSAGE_CLASS_ME_SPECIFIC
applicationPortBuilder.apply {
originatorPort = 1349
destinationPort = 1349
}
}.build()
println("Request:
$request")
val response = stub.sendDataToSubscriber(request)
println("Response:
$response")
}
Example Results
{
"messageId": "6a75356e-6191-11ec-b47d-7382e9b102b6",
"status": "SEND_STATUS_OK",
"numFragments": 1
}
message_id: "6a75356e-6191-11ec-b47d-7382e9b102b6"
status: SEND_STATUS_OK
num_fragments: 1
Handling The Binary Sms
The binary SMS also needs to be handled on the receiving device, which will need
some application on the device to know what to do with the message. Most third party
developers will not have access to create messages that can harm the handset directly,
see using the messageClass
and applicationPort
below.
Setting The Message Class
The binary SMS also needs to be handled on the receiving device. And in case of
UNSPECIFIED
, FLASH_MESSAGE
and ME_SPECIFIC
messages, they need to be handled
by an application on the device.
Note that SIM_SPECIFIC
and TE_SPECIFC
are handled by the SIM card itself or
the hardware (non-programmable part) of the handset itself respectively, and have
more restricted access than the FLASH_MESSAGE
and ME_SPECIFIC
classes. If not
set the message will not have a message class specified (aka UNSPECIFIED
).
Setting The Destination Port Number
Binary SMS messages also usually needs a port number to route it to a specific
application. It is important that the destinationPort
in the API request and
the android:port
configuration (or equivalent for iOS) matches. This way your
data messages will be sent to your application.
Example Receiver Application
Android devices can install apps that listen to SMS messages, including data messages. See google developer training for more detailed howto, and android for details on the SMS itself.
package com.example;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.SmsMessage;
import android.util.Log;
import java.nio.charset.StandardCharsets;
public class DataSmsReceiver extends BroadcastReceiver {
private static final String TAG = DataSmsReceiver.class.getName();
@TargetApi(Build.VERSION_CODES.M)
@Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
if (bundle != null) {
String format = bundle.getString("format");
Object[] incomingPDUs = (Object[]) bundle.get("pdus");
byte[][] dataParts = new byte[incomingPDUs.length];
int totalLength = 0;
for (int i = 0; i < msgs.length; i++) {
SmsMessage msg = SmsMessage.createFromPdu((byte[]) incomingPDUs[i], format);
dataParts[i] = msg.getUserData();
totalLength += dataParts[i].length;
}
byte[] content = new byte[totalLength];
int pos = 0;
for (byte[] part : dataParts) {
System.arraycopy(part, 0, content, pos, part.length);
pos += part.length;
}
Log.d(TAG, "Received raw data: " + new String(content, StandardCharsets.UTF_8));
}
}
}
The receiver also needs to be connected to the data SMS.
<receiver android:name="com.example.DataSmsReceiver"
android:enabled="true"
android:exported="true">
<intent-filter android:priority="10">
<action android:name="android.intent.action.DATA_SMS_RECEIVED"/>
<data android:scheme="sms"
android:host="*"
android:port="1349"/>
</intent-filter>
</receiver>
NOTE: There are strict limitations preventing applications from listening to SMS messages, including data messages on iOS devices.