I wrote a post about two weeks ago about using the Zipwhip API in Java to send a text message. This post will complete the picture by showing you how to receive a text message via the Zipwhip API. This is a little bit more involved than the previous post. Sending a message simply requires your code to zip off a message via the API which uses HTTP. Receiving, however, requires your code to bind to Zipwhip’s socket server and stay bound in to wait for the moment a text message actually arrives. This means your app must always be running to receive the text message.

As a background, there are a few ways to receive text messages from the Zipwhip network:

  1. Short polling
    You can query Zipwhip’s session/update API once every 10 seconds, or however often, and you will be told what signals you missed such as new messages, messages being marked as read, new contacts, etc. This means you are not getting messages in real-time, however this is a super simplistic method of getting updates or events. This is especially useful in Javascript apps that can’t create sockets.
  2. IP Socket-based push
    You can bind into a socket and get real-time signals from the Zipwhip network. This means that when a text message hits your phone, it will be immediately (within milliseconds) hitting your app. This requires a bit more complexity in your app, but it’s very worthwhile for the best experience.
  3. Post to a URL
    This method allows you to tell the Zipwhip network to post a copy of all of your signals to a URL. This is a very cool feature that Zipwhip gives you, but you must be running your own server at a public address for Zipwhip to be able to reach it. If you have to move your server around, you have to unregister the URL and reregister the URL you want posted to. This solution would not likely be used by consumer apps due to the configuration overhead.

This tutorial will just describe how to do IP Socket-based push because, in my opinion, it’s one of the coolest aspects of the Zipwhip network and the most powerful for the consumer or general developer. It lets you connect from any location at any time, or as many locations as you want, and get all of your signals delivered. So, if I want to run an app on my laptop, my desktop, my tablet, my Ubuntu box, and my Google TV, to get my text messages I can simply bind in via a socket and get copies of texts popping up everywhere I could ever want them. Because the Zipwhip network propagates things such as text messages being marked as read, especially back to my phone, I don’t have to mark a text as read on all of my computers like the way Skype makes me mark messages as read everywhere or the way Outlook makes me expire my envelope in the system tray on all of my machines.

Let’s get started. We need to fire up Eclipse where we’ll make a new Java project from scratch.

image_thumb

image_thumb1

Call the project ZipwhipAPISocketExample. (BTW, you can zoom in on the screenshots by clicking them.)

image

Go to the Libraries tab and make sure you have the ZipwhipAPI Jar added as well as the Log4j Jar. You can get these in your list by clicking on “Add External JARs…”. You will need to download the ZipwhipAPI from here if you don’t already have it. If you don’t have Log4j you can search for it or head over to the Apache Log4j project here. You will also need slf4j which is a small utility that abstracts Log4j to be used in different environments. These log dependencies are just a result of the ZipwhipAPI relying on them. They’re nice to use in your own projects too if you want to.

Zipwhip API Jar (820KB)

If you want to also download the dependencies you can grab the files below. Because these are popular files, you may already have these.

Log4j Jar (ZipwhipAPI.jar depends on this Jar)

Slf4j Jar (ZipwhipAPI.jar depends on this Jar)

image

Hit Finish on the dialog above. You should now have a new project called “ZipwhipAPISocketExample” and a clean Eclipse window with an empty project.

image

Create a new Java class so that we have a file to create our entry point in.

image

Create a package name like com.yourcompany.zwsocket. Of course swap in your name or your company’s name in place of what I typed. Then call the Java class ExampleMain or whatever name you prefer. Make sure to check off to create the “void main()” method so we have an entry point to our example.

image

Click Finish. You should see a new Java class in your editor.

image

Now, replace all of the text with the source code below. You can download it here, or you can cut & paste it.

ExampleMain.java

 1: package com.yourcompany.zwsocket;
 2:
 3: import com.zipwhip.api.DefaultZipwhipSubscriptionClient;
 4: import com.zipwhip.api.HttpConnection;
 5: import com.zipwhip.api.signals.JsonSocketSignalClient;
 6: import com.zipwhip.signals.Signal;
 7: import com.zipwhip.signals.SignalObserver;
 8:
 9: public class ExampleMain {
 10:
 11:     public static void main(String[] args) {
 12:
 13:         // Create our connection object for the Zipwhip API.
 14:         // This object gets an authenticated HTTP connection to the 
 15:         // Zipwhip network via a login which gets you a sessionKey.
 16:         HttpConnection connection = new HttpConnection();
 17:
 18:         String mobileNumber = "3135551234";
 19:         String password = "mypassword";
 20:
 21:         System.out.println(String.format(
 22:             "Logging into Zipwhip network with mobile:%s, pass:%s",
 23:             mobileNumber, password));
 24:
 25:         try {
 26:             // This method will send a login request to the Zipwhip network and
 27:             // if successful you will get a sesionKey set in your connection object
 28:             // Watch out that you don't run "requestLogin()" too much because if you 
 29:             // create more than 50 sessionKeys within 1 day you will no longer be able 
 30:             // to get a key for 24 hours.
 31:             connection.requestLogin(mobileNumber, password);
 32:             // You can alternately just set your sessionKey from the last time you
 33:             // did a requestLogin(). Just store the sessionKey and use that. It
 34:             // is good for 30 days. Uncomment the line below and set your sessionKey.
 35:             // connection.setSessionKey("2e08a863-4c57-7af6-92c0-b0a120a16778:32423");
 36:
 37:             System.out.println("Got sessionKey:" + connection.getSessionKey());
 38:
 39:             // Set the version to "/" so we use non-signed web service calls
 40:             connection.apiVersion = "/";
 41:
 42:         } catch (Exception e) {
 43:             System.out.println("Failed to authenticate and get sessionKey to Zipwhip network.");
 44:             return;
 45:         }
 46:
 47:         // Zipwhip's HTTP web services client library. It uses the connection object for
 48:         // an authenticated transport.
 49:         DefaultZipwhipSubscriptionClient zipwhipSubscrClient;
 50:
 51:         // Zipwhip's Socket client.
 52:         JsonSocketSignalClient signalClient;
 53:
 54:         // This will create a high level client object that allows you to perform
 55:         // the full suite of tasks against the Zipwhip network such as send texts,
 56:         // create contacts, create groups, etc.
 57:         zipwhipSubscrClient = new DefaultZipwhipSubscriptionClient(connection);
 58:
 59:         // We will create our TCP/IP socket connection as well. You still need an 
 60:         // HTTP client because the Zipwhip API uses HTTP calls in concert with the 
 61:         // socket because the socket only pushes signals to you. If you want to
 62:         // send in a command, you do it over the DefaultZipwhipSubscriptionClient 
 63:         // HTTP client.
 64:         signalClient = new JsonSocketSignalClient(zipwhipSubscrClient);
 65:
 66:         // We need to add our callback methods to the socket client so that
 67:         // we can act upon incoming signals.
 68:         signalClient.addSignalObserver(new SignalObserver() {
 69:
 70:             // This method is called when a push socket signal is received
 71:             @Override
 72:             public void notifySignalReceived(Signal signal) {
 73:                 //log.debug("Signal received with uri " + signal.uri);
 74:                 System.out.println("Signal received with uri " + signal.uri);
 75:                 System.out.println("\t" + signal.rawContent);
 76:             }
 77:
 78:             @Override
 79:             public void notifySignalProviderEvent(boolean isConnected, String message, long frameCount) {
 80:                 System.out.println("Socket status. isConnected:" + isConnected +
 81:                     ", msg:" + message + ", frame:" + frameCount);
 82:             }
 83:         });
 84:
 85:         // Let's finally call the connect method to actually bind in over TCP/IP
 86:         signalClient.connect(connection.getSessionKey());
 87:
 88:         System.out.println("Done with socket test void main(), however socket thread will keep running listening for signals until you kill the process. Thanks for using Zipwhip.");
 89:
 90:     }
 91:
 92: }

After you get the source code into Eclipse, your window should look like below. Remember, you can zoom by clicking the image.

image

You need to set your mobile number and password before you can run the file. If you don’t have a login to the Zipwhip network, you can get one via your carrier if your carrier is a Zipwhip partner.

image

Go ahead and run the code. Just right-click anywhere in the code and choose Run As –> Java Application.

image

When the code runs, you should see output in the Console.

image

The output in the Console window will be similar to the text below. Don’t worry, I changed the phone numbers and other important details in the output like the sessionKey because those are sensitive items of data.

 1: Logging into Zipwhip network with mobile:3134447002, pass:****
 2: log4j:WARN No appenders could be found for logger (com.zipwhip.api.HttpConnection).
 3: log4j:WARN Please initialize the log4j system properly.
 4: Got sessionKey:64abcd3d-9ab6-45ed-aa78-91e4a262169:1
 5: Done with socket test void main(), however socket thread will keep running listening for signals until you kill the process. Thanks for using Zipwhip.
 6: Socket status. isConnected:false, msg:Connecting..., frame:0
 7: Socket status. isConnected:true, msg:Connection Established - Negotiating, frame:0
 8: Socket status. isConnected:true, msg:Connection Established, frame:1
 9: Socket status. isConnected:true, msg:Connection Established, frame:1
 10: Socket status. isConnected:true, msg:Connection Established, frame:2
 11: Socket status. isConnected:true, msg:Connection Established, frame:3
 12: Signal received with uri /signal/message/receive
 13:     {"id":"11218401","content":{"to":"","body":"hey, what's up duder?","bodySize":21,"visible":true,"transmissionState":{"enumType":"com.zipwhip.outgoing.TransmissionState","name":"QUEUED"},"type":"MO","metaDataId":0,"dtoParentId":1,"scheduledDate":null,"thread":"","carrier":"Tmo","deviceId":1,"openMarketMessageId":"","lastName":"Phone","class":"com.zipwhip.website.data.dto.Message","isParent":false,"lastUpdated":"2011-07-03T22:49:17-07:00","loc":"","messageConsoleLog":"Message created on Sun Jul 03 22:49:17 PDT 2011. Setting status code to 4 by default","deleted":false,"contactId":2782629,"uuid":"7e397eb-01ca-4f19-9166-b8d431c52cf","isInFinalState":false,"statusDesc":"","cc":"","subject":"","encoded":true,"expectDeliveryReceipt":false,"transferedToCarrierReceipt":null,"version":1,"statusCode":4,"id":118401,"fingerprint":"29091579","parentId":0,"phoneKey":"samSGH-T729","smartForwarded":false,"fromName":null,"isSelf":false,"firstName":"Sidekick","sourceAddress":"2063984565","deliveryReceipt":null,"dishedToOpenMarket":null,"errorState":false,"creatorId":0,"advertisement":null,"bcc":"","fwd":"","contactDeviceId":1,"smartForwardingCandidate":false,"destAddress":"3134447333","DCSId":"not parsed at the moment","latlong":"","new":false,"address":"ptn:/2063982344","dateCreated":"2011-07-03T22:49:27-07:00","UDH":"","carbonedMessageId":-1,"channel":" ","isRead":false},"scope":"device","reason":null,"tag":null,"event":"receive","class":"com.zipwhip.signals.Signal","uuid":"787cfec2-d094-4e6d-9b59-d8f55486d","type":"message","uri":"/signal/message/receive"}
 14: Socket status. isConnected:true, msg:Connection Established, frame:4
 15: Signal received with uri /signal/conversation/change
 16:     {"id":"8312","content":{"lastContactFirstName":"Sidekick","lastContactLastName":"Phone","lastContactDeviceId":0,"unreadCount":2,"bcc":"","lastUpdated":"2011-07-03T22:49:18-07:00","class":"com.zipwhip.website.data.dto.Conversation","deviceAddress":"device:/3134441232/0","lastNonDeletedMessageDate":"2011-07-03T22:49:27-07:00","deleted":false,"lastContactId":27629,"lastMessageDate":"2011-07-03T22:49:27-07:00","dtoParentId":1,"version":336,"lastContactMobileNumber":"2063981234","id":81312,"fingerprint":"2906579","new":false,"lastMessageBody":"hey, what's up duder?","address":"ptn:/2063983244","dateCreated":"2011-03-17T22:14:24-07:00","cc":"","deviceId":1},"scope":"device","reason":null,"tag":null,"event":"change","class":"com.zipwhip.signals.Signal","uuid":"787cc2-d094-4e6d-9b59-d8f56d","type":"conversation","uri":"/signal/conversation/change"}
 17:

Of course to get the output like that above, you have to send a text message to the phone that you logged in under. Once the text message hits that phone, assuming you have Zipwhip correctly installed on the phone, you will get a text message hitting your application instantaneously. You will see a signal called “/signal/message/receive” popping up in your console window.

That’s it. I hope you’ve enjoyed working with the Zipwhip API using sockets to receive real-time incoming text messages to your phone! Enjoy.

zipwhip

Zipwhip is the productivity tool that lets businesses and customers text each other like friends. Zipwhip text-enables your existing (landline, VoIP, or toll free) business number. With direct connections to tier 1 carriers - Zipwhip is the trusted, scalable solution to business texting.

Join our newsletter
Get the latest business texting news directly in your inbox.