How to make phone calls and send SMS with Java

Java logo and how to make phone calls and text messages with Bandwidth APIs using Java

Bandwidth has a full suite of messaging API and voice API solutions to power your business’ needs.

Whether you want to send messages from toll-free numbers, local numbers, or short codes, Bandwidth’s APIs make it easy to enable in your software or platform, while Bandwidth’s relationships with the carriers give you reliable message delivery and insights. 

Introduction

In this article, you will see a quick overview of what sending your first message and creating your first call looks like when using Bandwidth’s Voice and Messaging APIs along with Bandwidth’s Java SDK. First you will see some code examples and then at the end of this article is an explanation of the variables you would need to insert into the code to make the SDK work with your Bandwidth account.

Additional resources:

Packages and Client Initialization

First you need to add the SDK package and other required dependencies and plugins to your Maven pom.xml (note that the SDK is not currently available as a Gradle package).

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.3.4.RELEASE</version>
	</parent>
	<groupId>com.firstapp</groupId>
	<artifactId>bandwidth</artifactId>
	<version>1.0.0</version>
	<name>bandwidth</name>

	<properties>
		<java.version>11</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>com.bandwidth.sdk</groupId>
			<artifactId>bandwidth-sdk</artifactId>
			<version>3.10.2</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
			     <artifactId>
                        spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

You then need to initialize the configuration for the SDK client.

package com.firstapp.bandwidth

public class ApiControllerInit {
   private final static BandwidthClient client = new BandwidthClient.Builder()
      .messagingBasicAuthCredentials("{username}", "{password}")
      .voiceBasicAuthCredentials("{username}", "{password}")
      .build();

   public final static com.bandwidth.messaging.controllers.APIController MESSAGING_CONTROLLER = CLIENT.getMessagingClient().getAPIController();

    public final static com.bandwidth.voice.controllers.APIController VOICE_CONTROLLER = CLIENT.getVoiceClient().getAPIController();
}

How to send a text message with Java

Sending a SMS Message with Java from a Bandwidth number looks like this.

package com.firstapp.bandwidth

import com.bandwidth.exceptions.ApiException;
import com.bandwidth.messaging.models.MessageRequest;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class Messaging {

   public static void Send() {
      MessageRequest messageRequest = new MessageRequest();

      List<String> toNumbers = new ArrayList<>();

      toNumbers.add("{to}");

      messageRequest.setApplicationId("{app_id}");
      messageRequest.setText("Hello, I am sending a message! How fun!");
      messageRequest.setTo( toNumbers );
      messageRequest.setFrom("{from}");


      try {
         MESSAGING_CONTROLLER.createMessage("{account_id}", messageRequest);
      } catch (ApiException | IOException e) {
         //catch exception
      }
}

You will need to define a Message class in order to parse data from callbacks.

package com.firstapp.bandwidth

import java.time.Instant;
import java.util.List;

public class Message {
    private String id;
    private Instant time;
    private List<String> to;
    private String from;
    private String text;
    private String applicationId;
    private String owner;
    private String direction;
    private Integer segmentCount;

    Message(String id, Instant time, List<String> to, String from, String text, String applicationId, String owner, String direction, Integer segmentCount) {
        this.id = id;
        this.time = time;
        this.to = to;
        this.from = from;
        this.text = text;
        this.applicationId = applicationId;
        this.owner = owner;
        this.direction = direction;
        this.segmentCount = segmentCount;
    }

    public String getId() {
        return this.id;
    }

    public Instant getTime() {
        return this.time;
    }

    public List<String> getTo() {
        return this.to;
    }

    public String getFrom() {
        return this.from;
    }

    public String getText() {
        return this.text;
    }

    public String getApplicationId() {
        return this.applicationId;
    }

    public String getOwner() {
        return this.owner;
    }

    public String getDirection() {
        return this.direction;
    }

    public Integer getSegmentCount() {
        return this.segmentCount;
    }
}

You will also need to define a MessagingCallback.

package com.firstapp.bandwidth

import java.time.Instant;

public class MessagingCallback {
    private String type;
    private Instant time;
    private String description;
    private String to;
    private Message message;

    MessagingCallback(String type, Instant time, String description, String to, Message message) {
        this.type = type;
        this.time = time;
        this.description = description;
        this.to = to;
        this.message = message;
    }

    public String getType() {
        return this.type;
    }

    public Instant getTime() {
        return this.time;
    }

    public String getDescription() {
        return this.description;
    }

    public String getTo() {
        return this.to;
    }

    public Message getMessage() {
        return this.message;
    }
}

You will need to set up a server that can receive a callback/webhooks with a JSON body that will tell you if the message was successfully delivered or not. Some simple Java and Spring server code using sinatra that can process Bandwidth messaging callbacks could look like this.

package com.firstapp.bandwidth

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;

@RestController
public class ReceiveMessagingCallback {
   @PostMapping("/messagingCallback")
   @ResponseStatus(HttpStatus.OK)
   public void messaging(@RequestBody List<MessagingCallback> callback) {
        if (callback.get(0).getType().equals("message-delivered”)) {
           //successful delivery action
        } else if (callback.get(0).getType().equals("message-failed")) {
           String failureReason = callback.get(0).getDescription();
           //failed delivery action
        }
    }
}

How to make a phone call with Java

Making a phone call with Java from a Bandwidth number looks like this. This must be in the same file as your initiated client or the client must be imported here.

package com.firstapp.bandwidth

import com.bandwidth.exceptions.ApiException;
import com.bandwidth.voice.models.ApiCreateCallRequest;

public class Voice {
   public static void Call() {
       ApiCreateCallRequest callRequest = new ApiCreateCallRequest();
       callRequest.setApplicationId("{app_id}");
       callRequest.setTo("{to}");
       callRequest.setAnswerUrl("{url}");
       callRequest.setFrom("{from}");

       try {
          voiceController.createCall("{account_id}", callRequest);
       } catch (ApiException | IOException e) {
          //catch exception
       }
   }
}

You will need to define a VoiceCallback class in order to parse data from callbacks. Keep in mind that this class would need more fields in order to accommodate additional data points present in other types of callback besides the Answer callback.

package com.firstapp.bandwidth

import java.time.Instant;
import java.util.List;

public class VoiceCallback {
    private String eventType;
    private String accountId;
    private String applicationId;
    private String from;
    private String to;
    private String direction;
    private String callId;
    private String callUrl;
    private Instant startTime;

    VoiceCallback() {}

    VoiceCallback(String eventType, String accountId, String applicationId, String from, String to, String direction, String callId, String callUrl, Instant startTime) {
        this.eventType = eventType;
        this.accountId = accountId;
        this.applicationId = applicationId;
        this.from = from;
        this.to = to;
        this.direction = direction;
        this.callId = callId;
        this.callUrl = callUrl;
        this.startTime = startTime;
    }

    public String getEventType() {
        return this.eventType;
    }

    public String getAccountId() {
        return this.accountId;
    }

    public String getApplicationId() {
        return this.applicationId;
    }

    public String getFrom() {
        return this.from;
    }

    public String getTo() {
        return this.to;
    }

    public String getDirection() {
        return this.direction;
    }

    public String getCallId() {
        return this.callId;
    }

    public String getCallUrl() {
        return this.callUrl;
    }

    public Instant getStartTime() {
        return this.startTime;
    }
}

When the call is answered by whoever you sent the call to, Bandwidth will send a callback/webhook with a JSON body to the URL you specified when you created the call. You can send BXML verbs back to Bandwidth in response to the callback/webhook in order to create new actions on the call. Some simple Java and Spring server code that would make the call play some text-to-speech audio and then hang up could look like this:

package com.firstapp.bandwidth

import com.bandwidth.voice.bxml.verbs.Hangup;
import com.bandwidth.voice.bxml.verbs.Response;
import com.bandwidth.voice.bxml.verbs.SpeakSentence;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;

@RestController
public class VoiceCallback
   @PostMapping("/voiceCallback")
   @ResponseStatus(HttpStatus.OK)
   public String voice(@RequestBody VoiceCallback callback) {
      if (callback.getEventType().equals("answer")) {
         SpeakSentence speakSentence = SpeakSentence.builder()
            .text("I am saying something and now will hang up.")
            .voice("julie")
            .build();

            Hangup hangup = Hangup.builder().build();

            Response response = Response.builder().build()
               .add(speakSentence)
               .add(hangup);

            return response.toBXML();
       }

       return "";
   }
}

And that’s it! That’s how simple it is to create your first message and call with a Bandwidth phone number, Bandwidth’s API, and Bandwidth’s Java SDK.

Variable Reference

Here is an explanation of the variables used in the above code that will be unique to your account and use case.

Variable Name Explanation
username your username for the Bandwidth App
password your password for the Bandwidth App
app_id the ID of your messaging or voice application; applications are set within the Bandwidth App and are used associate your Bandwidth phone numbers with URLs for callback/webhooks
from_number when creating outgoing messages or calls, the number you are sending to; this can be your cell phone number for testing or the number of one of your customers
to_number when creating outgoing messages or calls, this is a number you have been assigned by Bandwidth that lives on your Bandwidth App account
account_id your Bandwidth App account ID
url your Bandwidth App account ID

Developing with Bandwidth – Java

Looking for additional information on developing with Java? The webinar below goes into greater detail on the topics presented in this post.