While working on an AIR Mobile app, either in Flash or Flex, you might want to integrate Twitter API in it. In one of my projects few months back, I wanted to integrate the Twitter API within the app but wasn’t able to find a complete working solution. While searching on the internet, I came across this article on Adobe DevNet. Though any complete example was not available, it proved to be a very helpful starting point. The approach doesn’t uses any specific Twitter API library but instead uses the default oAuth authentication mechanism used by Twitter.

In this article I’ll show you a simple example to create a Twitter API integrated Flex Mobile App that can post to Twitter and also verify user’s credentials.

To start with the project you would need to have two AS3 libraries:

Next, go to https://dev.twitter.com/ and create a new application. Once there, fill in the required details and add a website URL and a callback URL. Make sure what you use as the callback URL as we will need it later in the application.

Flex AIR AS3 Mobile Twitter API

Once done, go to the newly created application and change the Application Access Level to Read and Write. This is required as we will be using our app to publish tweets. Once this is done, take a not of the Consumer Key and Consumer Secret associated with this app. We will need this in our Flex Mobile App.

Next, go to Flash Builder and create a new Flex Mobile App. You can chose any App style, I selected a View Navigator App. Add the Crypto library and oAuth library to your project.

In the first view of the application, we write code to create a connection to the Twitter API, get user’s permission to allow application to read and write to his account, store the user’s access key and access secret locally and using these, read/write to user’s twitter profile. We store the details so that we can re use them for subsequent app accesses. Each time we start the app, we first verify if the locally stored access key and secret is valid.

The code for all this is written below and accompanied by self explanatory comments.

<!--?xml version="1.0" encoding="utf-8"?-->
<!-- Place non-visual elements (e.g., services, value objects) here -->
<![CDATA[                       import mx.events.FlexEvent;                         import org.iotashan.oauth.OAuthConsumer;            import org.iotashan.oauth.OAuthRequest;             import org.iotashan.oauth.OAuthSignatureMethod_HMAC_SHA1;           import org.iotashan.oauth.OAuthToken;           import org.iotashan.utils.OAuthUtil;            import org.iotashan.utils.URLEncoding;                      // App Constants            public const TWITTER_CONSUMER_KEY:String = "XXXXXXXXXXXXX";             public const TWITTER_CONSUMER_SECRET:String = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";                        // API URLs             public const VERIFY_CREDENTIALS:String = "https://api.twitter.com/1.1/account/verify_credentials.json";             private var twitterRequestURL:String = "https://api.twitter.com/oauth/request_token";           private var twitterAuthURL:String = "https://api.twitter.com/oauth/authorize";          private var twitterTokenURL:String = "https://api.twitter.com/oauth/access_token";                      public var twitterAccessObj:Object = {};            private var requestToken:OAuthToken;            private var accessToken:OAuthToken;             private var oAuthConsumer:OAuthConsumer;            private var twitterWebView:StageWebView;            private var webViewStartLocation:int;           private var accessRequest:OAuthRequest;             private var thisProfile:Object = {};                        protected var signature:OAuthSignatureMethod_HMAC_SHA1 = new OAuthSignatureMethod_HMAC_SHA1();                      // View Creation Complete           private function onCreationComplete(event:FlexEvent):void           {               //Read details from any existing file               readTwitterAccess();                                //Check if the Access Key and Access Token already Exist                if(twitterAccessObj.accessKey && twitterAccessObj.accessSecret)                 {                   verifyAccessToken();                }               else                {                   oAuthConsumer = new OAuthConsumer(TWITTER_CONSUMER_KEY, TWITTER_CONSUMER_SECRET);                   var oauth:OAuthRequest = new OAuthRequest(OAuthRequest.HTTP_MEHTOD_GET, twitterRequestURL, null, oAuthConsumer);                    var request:URLRequest = new URLRequest(oauth.buildRequest(new OAuthSignatureMethod_HMAC_SHA1()));                  var loader:URLLoader = new URLLoader(request);                  loader.addEventListener(Event.COMPLETE,onLoaderComplete);               }           }                       //Loaded Twitter Access Token Request URL           private function onLoaderComplete(e:Event):void             {               requestToken = OAuthUtil.getTokenFromResponse(e.currentTarget.data);                var authRequest:URLRequest = new URLRequest('http://api.twitter.com/oauth/authorize?oauth_token=' + requestToken.key);                              // StageWebView to Authorize the App                twitterWebView = new StageWebView();                twitterWebView.viewPort = new Rectangle(0, navigator.actionBar.height, width, height);              twitterWebView.stage = this.stage;              twitterWebView.assignFocus();               twitterWebView.loadURL(authRequest.url);                twitterWebView.addEventListener(LocationChangeEvent.LOCATION_CHANGE, onLocationChange);             }                       // Web View Location Change             private function onLocationChange(e:LocationChangeEvent):void           {               var location:String = e.location;                               //Here we need to extract the oAuth Verifier URL from the redirect URL              if(location.search("rjdesignz") != -1)              {                   var oAuthVerifier:String = location.substr(location.search("oauth_verifier") + 15);                     onPin(oAuthVerifier);               }           }                       // We now have the PIN, use this            private function onPin(oAuthVerifier:String):void           {               var params:Object = new Object();               params.oauth_verifier = oAuthVerifier;                              accessRequest = new OAuthRequest(OAuthRequest.HTTP_MEHTOD_GET, twitterTokenURL, params, oAuthConsumer, requestToken);               var accessUrlRequest:URLRequest = new URLRequest(accessRequest.buildRequest(new OAuthSignatureMethod_HMAC_SHA1()));                 var accessLoader:URLLoader = new URLLoader(accessUrlRequest);               accessLoader.addEventListener(Event.COMPLETE, onAccessRequestComplete);             }                       // Got the required details. Dispose the web view and write details to local storage.           private function onAccessRequestComplete(e:Event):void          {               accessToken = OAuthUtil.getTokenFromResponse(e.currentTarget.data);                 twitterAccessObj.accessKey = accessToken.key;               twitterAccessObj.accessSecret = accessToken.secret;                                 twitterWebView.dispose();               postConainer.includeInLayout = true;                postConainer.visible = true;                                writeTwitterAccess();           }                       // Post the message on Twitter          private function onPostToTwitter(e:MouseEvent):void             {               busyInd.visible = true;                 var params:Object = {};                 params.status = postTxtArea.text;               var consumer:OAuthConsumer = new OAuthConsumer(TWITTER_CONSUMER_KEY, TWITTER_CONSUMER_SECRET);              var token:OAuthToken = new OAuthToken(twitterAccessObj.accessKey, twitterAccessObj.accessSecret);               var postRequest:OAuthRequest = new OAuthRequest(OAuthRequest.HTTP_MEHTOD_POST, "https://api.twitter.com/1/statuses/update.xml", {status:postTxtArea.text}, consumer, token);                                var urlRequest:URLRequest = new URLRequest(postRequest.buildRequest(new OAuthSignatureMethod_HMAC_SHA1()));                 urlRequest.method = URLRequestMethod.POST;                              urlRequest.url = urlRequest.url.replace("&status=" + URLEncoding.encode(params.status), "");                urlRequest.data = new URLVariables("status=" + postTxtArea.text );                              var loader:URLLoader = new URLLoader(urlRequest);               loader.addEventListener(Event.COMPLETE, onTwitterPostComplete);                 loader.addEventListener(IOErrorEvent.IO_ERROR, onTwitterIOError);               loader.addEventListener(HTTPStatusEvent.HTTP_STATUS, onTwitterHttpStatus);          }                       // Credentials already exist, verify these              public function verifyAccessToken() : void          {               busyInd.visible = true;                 trace("verify access token");               var consumer:OAuthConsumer = new OAuthConsumer(TWITTER_CONSUMER_KEY, TWITTER_CONSUMER_SECRET);              var token:OAuthToken = new OAuthToken(twitterAccessObj.accessKey, twitterAccessObj.accessSecret);               var oauthRequest:OAuthRequest = new OAuthRequest( "GET", VERIFY_CREDENTIALS, null, consumer, token );               var request:URLRequest = new URLRequest( oauthRequest.buildRequest( signature, OAuthRequest.RESULT_TYPE_URL_STRING ) );                 request.method = "GET";                                 var loader:URLLoader = new URLLoader( request );                loader.addEventListener( Event.COMPLETE, verifyAccessTokenHandler );                loader.addEventListener(IOErrorEvent.IO_ERROR, onTwitterIOError);               loader.addEventListener(HTTPStatusEvent.HTTP_STATUS, onTwitterHttpStatus);          }                       //Successfully Posted on Twitter            private function onTwitterPostComplete(e:Event):void            {               busyInd.visible = false;                postTxtArea.text = "";              trace("Tweet Success!");            }                       // Twitter IO Error             private function onTwitterIOError(e:IOErrorEvent):void          {               busyInd.visible = false;                trace("Tweet IOError!");            }                       // Twitter HTTP Status Error            private function onTwitterHttpStatus(e:HTTPStatusEvent):void            {               trace("Tweet HttpStatus!");             }                       // Access Token Exists          protected function verifyAccessTokenHandler(event:Event):void           {               trace("Valid Access Data Exists");                              busyInd.visible = false;                postConainer.includeInLayout = true;                postConainer.visible = true;            }                       public function readTwitterAccess():void            {               var file:File = File.applicationStorageDirectory.resolvePath("tw.file");                var fileStream:FileStream = new FileStream();               if(file.exists)                 {                   fileStream.open(file, FileMode.READ);                   var obj:Object = fileStream.readObject() as Object;                     twitterAccessObj.accessKey = obj.twitterAccessKey;                  twitterAccessObj.accessSecret = obj.twitterAccessSecret;                    fileStream.close();                 }               else                {                   trace("No File Present");               }           }                       public function writeTwitterAccess():void           {               var file:File = File.applicationStorageDirectory.resolvePath("tw.file");                var fileStream:FileStream = new FileStream();               fileStream.open(file, FileMode.WRITE);              var obj:Object = {};                obj.twitterAccessKey = twitterAccessObj.accessKey;              obj.twitterAccessSecret = twitterAccessObj.accessSecret;                fileStream.writeObject(obj);                fileStream.close();             }                   ]]>



This is just a simple example to show how you can post to Twitter using oAuth library in an AIR Mobile App.

Hope you find this a helpful one.

UPDATE: Check this newer post which uses Twitter API 1.1