27 November 2010

Send SMS Text Message from Java/Groovy - via Twitter

Writing code to send an SMS text message is fairly easy on a smart phone like an Android.  But from a desktop, sending texts is still a mess, not always free, and/or requires a phone connected to your server.

I simply want to send a message to my phone when my app receives some data.  I don't need a complex library with lots of setup nor do I want to sign up for a pay service.

Now this isn't the cleanest solution to text from an app but Twitter can send messages to your phone when people you follow update their status, when someone mentions or replies to you, or when you get a direct message.

My last two write-ups, "Send a Simple Tweet with OAuth and Groovy" and "Send a Direct Message Tweet with Groovy" showed how easy it is to use Java/Groovy and the Twitter4J library to send messages to your own Twitter account or a message to anyone else.

By sending a tweet to an account that you follow or a Direct Message to your own account, Twitter can be setup to forward that message to a phone that you associate with your account.

Simply go to your Twitter account, Settings, Mobile and follow the easy instruction. Then use one of the sample apps from my previous posts and tweet-text away!

Note:
  • This only allows you to tweet-text to phones that have been setup to follow accounts. 
  • This does not allow you to send a text to a cell phone not registered with Twitter.
  • This works for what I need.
  • Do you know a better/easier, free method?  Write a comment!


What do you think? Leave a comment.

Send a Direct Message Tweet with Groovy

Alright.  Using the Twitter4J library and Groovy, I've beaten down the OAuth beast and have a simple example app to send a "update status" tweet.

Now instead of sending a message to my own account, let's do a real easy mod to send a Direct Message to a specific user   Using the same app as before, the only changes needed are:

  • import DirectMessage
  • change from twitter.updateStatus(message) to twitter.sendDirectMessage(screenName, message)
import twitter4j.DirectMessage;
import twitter4j.Twitter
import twitter4j.TwitterFactory
import twitter4j.Status
import twitter4j.http.AccessToken
import twitter4j.http.RequestToken
import java.io.BufferedReader
import com.thoughtworks.xstream.XStream

try{

   Twitter twitter = new TwitterFactory().getInstance();

   // set key and secret that you get from Twitter app registeration at:
   //     http://dev.twitter.com/pages/auth#register
   twitter.setOAuthConsumer("Your Consumer key", "Your Consumer secret");

   // load access token if it exists
   AccessToken accessToken = null
   def tokenFile = new File("accessToken.xml")

   if (tokenFile.exists()) {
      def xstream = new XStream()
      tokenFile.withInputStream { ins -> accessToken = xstream.fromXML(ins) }
      twitter.setOAuthAccessToken(accessToken)
   } 

   else {

     // get the URL to request access to Twitter acct
     RequestToken requestToken = twitter.getOAuthRequestToken();
     String authUrl = requestToken.getAuthorizationURL()
     System.out.println("Open the following URL and grant access to your account:");
     System.out.println(authUrl);

     // take the PIN and get access token
     System.out.print("Enter the PIN:");
     BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
     String pin = ""
     pin = br.readLine();
     accessToken = twitter.getOAuthAccessToken(requestToken, pin);

     // persist token
     def xstream = new XStream()
     xstream.classLoader = getClass().classLoader
     new File("accessToken.xml").withOutputStream { out -> xstream.toXML(accessToken, out) }
   }

   String message = "from Groovy w/ token" + accessToken.getToken()
   String screenName ="ScreenNameToSendTo"

   DirectMessage directMessage = twitter.sendDirectMessage(screenName, message)
   System.out.println("Direct message sent to " + directMessage.getRecipientScreenName());

} catch (Exception e) {
   e.printStackTrace();
}

What do you think? Leave a comment.

Sending a Simple Tweet with OAuth and Java/Groovy

Come on, man!  What used to a be a simple task to send a tweet is now a OAuth nightmare.

A year or so ago, I built that tweet-a-w/e thing that sniffed XBee chirps and sent them to a twitter account that kindly routed them to my cell phone.

I have a need now to receive an XML stream, parse out a few tidbits and then send the results out as a SMS text message.  Remembering that tweet-a-w/e app, I thought that I would again leverage Twitter to send the text message.  All I need to do is send a tweet via a Twitter API and have my account set up to send the content to a phone number.

This time my XML receiver is in Java/Groovy, so I grabbed the latest Twitter4J, glanced at the UpdateStatus example and tried a quick test with Groovy.
import twitter4j.Twitter  
import twitter4j.TwitterFactory  
import twitter4j.Status  
    
Twitter twitter = new TwitterFactory().getInstance("myAcct","myPassword");  
Status status = twitter.updateStatus("from Groovy");  
System.out.println("Successfully updated the status to [" + status.getText() + "].");  
Did that work?  Of course not.  Authentication FAIL.

Caught: 401:Authentication credentials were missing or incorrect.
{"errors":[{"code":53,"message":"Basic authentication is not supported"}]}
TwitterException{exceptionCode=[15bb6564-00e5bee0], statusCode=401, retryAfter=0, rateLimitStatus=null, version=2.1.7}

What the heck?  Basic Authentication is not supported?  Darn it, what is this stupid OAuth thing about?  Here's the Twitter page "Authenticating Requests with OAuth" that looks real interesting to read.  Arghhhhh.  I just want to send a flippin' tweet, I really don't have time to research this at Hueniverse.

After some more quick Googling, this isn't as bad as it first looks.It boils down to getting a key and secret pair.  The steps are:
  • Goto Twitter and register your app.
  • You'll get a consumer key and secret which are similar to the public and private keys used in protocols such as ssh. 
  • Use the key and secret to sign every request you make to the Twitter API
import twitter4j.Twitter  
import twitter4j.Twitter
import twitter4j.TwitterFactory
import twitter4j.Status
import twitter4j.http.AccessToken
import twitter4j.http.RequestToken
import java.io.BufferedReader

try{

   Twitter twitter = new TwitterFactory().getInstance();

   // set key and secret that you get from Twitter app registeration at:
   //     http://dev.twitter.com/pages/auth#register
   twitter.setOAuthConsumer("Your Consumer key", "Your Consumer secret");

   // get the URL to request access to Twitter acct
   RequestToken requestToken = twitter.getOAuthRequestToken();
   String authUrl = requestToken.getAuthorizationURL()
   System.out.println("Open the following URL and grant access to your account:");
   System.out.println(authUrl);

   // take the PIN and get access token
   System.out.print("Enter the PIN:");
   BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
   String pin = ""
   pin = br.readLine();
   AccessToken accessToken = twitter.getOAuthAccessToken(requestToken, pin);

   String message = "from Groovy w/ pin" + pin
   Status status = twitter.updateStatus(message);
   System.out.println("Successfully sent " + message);

} catch (Exception e) {
   e.printStackTrace();
} 

Ok, so that works.  But every time you run the program, you need to go and fetch the darn token.  According to Twitter, the token doesn't expire, so let's persist the thing.

I like using XStream to serialize Java/Groovy objects to/from XML.  A quick update to the code above lets us save an XML file that we can reload as needed.
import twitter4j.Twitter
import twitter4j.TwitterFactory
import twitter4j.Status
import twitter4j.http.AccessToken
import twitter4j.http.RequestToken
import java.io.BufferedReader
import com.thoughtworks.xstream.XStream

try{

   Twitter twitter = new TwitterFactory().getInstance();

   // set key and secret that you get from Twitter app registeration at:
   //     http://dev.twitter.com/pages/auth#register
   twitter.setOAuthConsumer("Your Consumer key", "Your Consumer secret");

   // load access token if it exists
   AccessToken accessToken = null
   def tokenFile = new File("accessToken.xml")

   if (tokenFile.exists()) {
      def xstream = new XStream()
      tokenFile.withInputStream { ins -> accessToken = xstream.fromXML(ins) }
      twitter.setOAuthAccessToken(accessToken)
   } 

   else {

     // get the URL to request access to Twitter acct
     RequestToken requestToken = twitter.getOAuthRequestToken();
     String authUrl = requestToken.getAuthorizationURL()
     System.out.println("Open the following URL and grant access to your account:");
     System.out.println(authUrl);

     // take the PIN and get access token
     System.out.print("Enter the PIN:");
     BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
     String pin = ""
     pin = br.readLine();
     accessToken = twitter.getOAuthAccessToken(requestToken, pin);

     // persist token
     def xstream = new XStream()
     xstream.classLoader = getClass().classLoader
     new File("accessToken.xml").withOutputStream { out -> xstream.toXML(accessToken, out) }
   }

   String message = "from Groovy w/ token" + accessToken.getToken()
   Status status = twitter.updateStatus(message);
   System.out.println("Successfully sent " + message);

} catch (Exception e) {
   e.printStackTrace();
}

The serialized Access Token looks like this:


  5555555-AbCdEF
  1oKiOlOlOlOl
  
    oauth_token=5555555-AbCdEF
    oauth_token_secret=1oKiOlOlOlOl
    user_id=007
    screen_name=bond

  
  bond
  007

Notes:

For the above examples, I used:
  • Groovy Version: 1.7.0 JVM: 1.6.0_22
  • Twitter4J 2.1.7  For this, I copied only the twitter4j-core-2.1.7.jar into the Groovy lib folder.  On Linux, this is /usr/share/Groovy/lib
  • XStream 1.3.1  For this, I copied the xstream-1.3.1.jar and xpp3_min-1.1.4c.jar into the Groovy lib
What do you think? Leave a comment.