Java VoIP developers 101
Part 2: Java example on recording VoIP calls, call routing
If you have read the Java guide part 1 and you still have some questions and time, take a look at this advanced guide. After reading this, you will be able to record and log calls and route conversations.
- Download example project:ozeki-voip-java-example-source-advanced.zip
- Reference manual: HTTP API Online Manual
Introduction
On the previous page you have learnt how to make/receive calls and send/receive SMS messages. If you thirst for more knowledge, this guide consists of far more advanced features, like call logging, call routing or call recording.
Part 1: Java example on sending SMS, making VoIP calls
1. Log calls
To log calls, at your PBX choose, through HTTP API, which port to store the changes of the calls. You can do this at Productivity menu, http API menu item, by filling the Call changed URL field at the Configure option. In this example, this is the port 7785 of localhost. Now, make a Java application, which checks this port and gives a http response if a call arrives.
public static void Initialize() { ServerSocket listener = new ServerSocket(7785); while (true) { Socket socket = listener.accept(); InputStream inputStream = socket.getInputStream(); byte[] b = new byte[inputStream.available()]; inputStream.read(b); System.out.println(new String(b)); } } |
First of all, you need to make a ServerSocket object, and with the help of this, you will watch the previously given port. You can accept an incoming request by calling the accept() method, after the invitation, you will get back a Socket object. You can query the incoming http response through this object. But first, you have to call the getInputStream() method of the socket, which returns with an InputStream object. Querying the response is possible in a byte array. You can inform the size of this byte array by the inputstream available() method. Then, with read() method, you can read the response, and this method has to give the byte array as a parameter, which contains the already read bytes. To display the reponse, make a string typed example, with the parameters of the byte array, so you can get back the same array as the string.
2. Record calls
To record calls, at your PBX choose, through HTTP API, which port to store the changes of the calls. You can do this at Productivity menu, http API menu item, by filling Call changed URL field at Configure option. In this example, this is port 7786 of localhost. Then, you need to make a Java application, that checks this port, and gives a http response whether you would like to record the call or not. You can manage it by using <Record>OzML order.
<Record finishedUrl="http://localhost:7787" format="mp3"/> |
It has two attributes: the first is the finishedURL, which gives the URL of the recorded call and the second is format attribute, which shows the format of the record.
public static Initialize() { ServerSocket listener = new ServerSocket(7786); while (true) { Socket socket = listener.accept(); String responde = "HTTP/1.1 200 OKrn" + "Content-Type: text/xmlrn" + "Connection: Keep-Alivern" + "Keep-Alive: timeout=15, max=100rnrn" + "<?xml version="1.0&'quot; encoding="UTF-8"?>" + "<Response><Record finishedUrl=http://localhost:7787 format="mp3"/></Response>"; OutputStream outputStream = socket.getOutputStream(); outputStream.write(responde.getBytes()); outputStream.flush(); } } |
Call recording has two steps. First, watch the port, which was given a Call changed URL at http API, and if a call arrives, send back a <Record> OzML. Watching the port at messages is similar as watching it at calls. To send the responds, first you have to call getOutputStream of socket, which returns with an OutputStream type object. You can send the response through this. To the sending, give the desired response with output stream write() method. It waits for a byte array, so convert the string to a byte array. The easiest way to do this by calling getByte() function.
The next step is to make a Java application, which watches the previously given port. Then, store the incoming response, which is availabe at the URL of RecordUrl attribute.
private static void Initialze() { ServerSocket listener = new ServerSocket(7786); while (true) { Socket socket = listener.accept(); InputStream inputStream = socket.getInputStream(); byte[] b = new byte[inputStream.available()]; inputStream.read(b); System.out.println(new String(b)); } } |
3. Call routing
Besides Dial Plan, it is possible to give a Java method, so you can decide which extension answers the call when forwarding your calls. If you did not forward the call, it will be handle by the rules of Dial Plan. You can enter into the Route interception URL field the path of your method (e.g. http://yoursite.com/RouteCalls/RouteCall) in the Productivity menu's, HTTP API submenu. In this case this is port 7778 of localhost. Your Java application will check this port.
public class Routing { public static void Initialize() { try (ServerSocket listener = new ServerSocket(7788)) { while (true) { try (Socket socket = listener.accept()) { String inputResponse = GetResponse(socket.getInputStream()); String dialedNumber = GetValue(inputResponse, "DialedNumber"); if (dialedNumber.equals("9999")) { String output = "HTTP/1.0 200 OKrn" + "Content-Type: text/xmlrn" + "Connection: Keep-Alivern" + "Keep-Alive: timeout=15, max=100rnrn" + "<?xml version="1.0" encoding="UTF-8"?>rn" + "<Response><Route>9998</Route></Response>"; OutputStream outputStream = socket.getOutputStream(); outputStream.write(output.getBytes()); outputStream.flush(); } } } } } private static String GetResponse(InputStream pInputStream) throws IOException { byte[] b = new byte[pInputStream.available()]; pInputStream.read(b); return new String(b); } private static String GetValue(String pContent, String pInfoName) { String value; int beginIndex = pContent.indexOf(pInfoName); int endIndex = pContent.indexOf("&", beginIndex); value = pContent.substring(beginIndex, endIndex).split("=")[1]; return value; } } |
Checking the calls happensin a similar way to logging calls, with the help of the ServerSocket object. You need to query when there is an incoming call (it is also similar to the query of call logging)with the code above, to forward the calls from port 9999 to port 9998. First, you have to read the value of the DialedNumber attribute. You can manage that with the GetValue function, which waits for the response and the name of the attribute. The function search the index of the attribute first, then defines the index of the next character.
After it cut off the string and the function will divide it by the '=' sign, using the string split method. The split method gives back a string array, its second item, with index 1 will be the target value. It gives back this value.
If you have the attribute value of DialedNumber, test whether it is equal with 9999. If yes, forward the call to extension 9998. To forward the call, you need to send a http response, which content is <Route> OzML order.
<Route Destination="9998" RingTime = "30"/> |
Route order has two attributes: the first is the Destination, which gives the target of the call forwarding, and the RingTime, which refers to how may seconds the extension needs to ring. It is optional, its value is 90 by default. You can read more about Route command here.
Giving back the http response happening with the output stream, similar to Call recording.
Part 1: Java example on sending SMS, making VoIP calls
If you have any questions or need assistance, please contact us at info@ozekiphone.com