Home >
This is excerpted from Chapter 18 of the Adobe AIR 1.5 Cookbook by David Tucker, Marco Casario, Koen De Weggheleire, and Rich Tretola. The book includes hands-on recipes to help you solve a variety of tasks and scenarios often encountered when using Adobe AIR to build Rich Internet Applications for the desktop.
Consuming Twitter APIs
Problem
You want to access the Twitter APIs web services.
Solution
Twitter was born from the simple idea of communicating quickly with friends via brief text messages, but its success also contributed to its transformation, and today the service is also used for commercial purposes to communicate new initiatives, software releases, and much more.
Note
According to Wikipedia, Twitter is a free social networking and microblogging service that allows users to send updates (otherwise known as tweets), which are text-based posts of up to 140 characters. Updates are displayed on the user’s profile page and delivered to other users who have signed up to receive them. The sender can restrict delivery to those in their circle of friends (delivery to everyone being the default). Users can receive updates via the Twitter website, instant messaging, SMS, RSS, or email, as well as through an application such as Twitterrific or Facebook. For SMS, four gateway numbers are currently available: short codes for the United States, Canada, and India, and a United Kingdom number for international use. Several third parties offer the ability to post and receive updates via email.
This is a sampling of AIR applications that consume Twitter’s APIs:
Twhirl (http://www.twhirl.org)
Spaz (http://funkatron.com/spaz); developed using Ajax
Snitter (http://getsnitter.com)
Tweetr (http://www.tweet-r.com)
This recipe uses Twitter’s APIs to create a simple AIR application with ActionScript and JavaScript that displays the most recent messages and account details.
Discussion
Twitter provides its own set of APIs to consume its web services and create mashups that use its services. This solution will use the simplest approach to consume Twitter’s APIs, without carrying out the authentication procedure to retrieve information about protected users who aren’t friends.
Note
You can find more information to study Twitter’s APIs at the following addresses:
http://apiwiki.twitter.com/Twitter: The API home page
http://apiwiki.twitter.com/REST+API+Documentation: API documentation, which is a reference for developers building tools that talk to Twitter
http://groups.google.com/group/twitter-development-talk: Twitter Development Talk, where you can talk about your Twitter applications with other developers
http://code.google.com/p/twitterscript: An ActionScript 3 library for accessing Twitter APIs.
ActionScript/Flex
An open source library that began as a Twitter project, the twitterscript ActionScript 3 library (http://apiwiki.twitter.com) is a great help when using the Twitter APIs with ActionScript.
It’s quite easy to use this library. After you download TwitterApi.swc and import it into your Flash or Flex project, you can import and use its classes. For example, the loadUserTimeline method of the Twitter class allows you to load the timeline of a user by assigning it a nickname as a parameter:
tw = new Twitter();
tw.addEventListener(TwitterEvent.ON_USER_TIMELINE_RESULT, loadedUserTimeline );
tw.loadUserTimeline( nick );
The nick parameter contains the screen name of the Twitter user. The ON_USER_TIMELINE_RESULT event of the TwitterEvent class is triggered when the list of the timeline of messages is loaded. In the loadedUserTimeline event handler, you can load the messages in a variable, which will then be used as a data provider in the application:
private function loadedUserTimeline( evt:TwitterEvent ):void
{
var timeline:Array = evt.data as Array;
// populate messages list dataprovider
var twitStatus:TwitterStatus;
for each( twitStatus in timeline )
{
_timelineDP.addItem( twitStatus );
}
_logedUserProfile = twitStatus.user;
}
The data property of the event object contains an array of timeline messages. With a for...each loop, you can control all the TwitterStatus objects in the timeline messages.
The complete ActionScript class that pulls the latest messages from a Twitter user using a nickname is as follows:
package com.oreilly.aircookbook.bonus
{
import mx.collections.ArrayCollection;
import mx.controls.Alert;
import twitter.api.Twitter;
import twitter.api.data.TwitterStatus;
import twitter.api.data.TwitterUser;
import twitter.api.events.TwitterEvent;
public class TwitterConn
{
private var tw:Twitter;
private var _userDetails:TwitterUserVO;
public function get userDetails():TwitterUserVO
{
return _userDetails;
}
private var _logedUserProfile:TwitterUser;
public function get logedUserProfile():TwitterUser
{
return _logedUserProfile;
}
private var _timelineDP:ArrayCollection;
public function get timelineDP():ArrayCollection
{
return _timelineDP;
}
public function TwitterConn()
{
tw = new Twitter();
tw.addEventListener( TwitterEvent.ON_USER_TIMELINE_RESULT, loadedUserTimeline );
_timelineDP = new ArrayCollection();
}
public function loadUserTimeline( nick:String ):void
{
if( nick == "" )
return;
tw.loadUserTimeline( nick );
}
// called when user timeline is returned from webservices
private function loadedUserTimeline( evt:TwitterEvent ):void
{
// access timeline messages array
var timeline:Array = evt.data as Array;
// clear previous messages list contents
_timelineDP.removeAll();
// if no timeline found for specified user
// exit function execution
// user probably doesn't exists
if(timeline == null || timeline.length == 0 )
{
return;
}
var twitStatus:TwitterStatus;
for each( twitStatus in timeline )
{
_timelineDP.addItem( twitStatus );
}
_logedUserProfile = twitStatus.user;
_userDetails = new TwitterUserVO();
_userDetails.source = logedUserProfile.profileImageUrl;
_userDetails.name = logedUserProfile.name;
_userDetails.screenName = logedUserProfile.screenName;
_userDetails.location = logedUserProfile.location;
_userDetails.url = logedUserProfile.url;
_userDetails.description = logedUserProfile.description;
}
}
}
The class creates the instance of the Twitter class in the constructor and creates an event listener for the TwitterEvent.ON_USER_TIMELINE_RESULT event.
In the loadedUserTimeline event handler, called when a response user timeline is returned from web services, you check whether there is a timeline of messages for the specific screen name that was passed to the function; if a timeline doesn’t exist, the function will exit. This check is carried out by verifying whether the timeline.length property is different from zero.
In the userDetails property, an ActionScript Value object is instanced and saved as TwitterUserVO.as, a simple class that transports data, to which you assign the properties contained in the TwitterStatus class and in its user: twitStatus.user property. This information belongs to the user for which you loaded the message timeline. The ActionScript Value object TwitterUserVO.as simply contains a list of properties:
package com.oreilly.aircookbook.ch16
{
[Bindable]
public class TwitterUserVO
{
public var source:String;
public var name:String;
public var location:String;
public var url:String;
public var description:String;
public var screenName:String;
public function TwitterUserVO()
{
}
}
}
For the sake of brevity, in this Value object the properties have been declared as public. To follow object programming best practices, you should encapsulate the properties of a class to make it more secure and declare the properties as private so they can be exposed and be get and set with the public getter/setter methods.
The AIR application that defines the user interface elements is as follows:
<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication
xmlns:mx="http://www.adobe.com/2006/mxml"
width="550">
<mx:Script>
<![CDATA[
import mx.core.IFlexDisplayObject;
import com.oreilly.aircookbook.bonus.TwitterConn;
import com.oreilly.aircookbook.bonus.TwitterAuthor;
import mx.managers.PopUpManager;
[Bindable]
private var twclass:TwitterConn = new TwitterConn();
private function showDetails():void
{
var myPopUp:IFlexDisplayObject = PopUpManager.createPopUp (this,
TwitterAuthor, true);
TwitterAuthor( myPopUp ).twitterDetails = twclass.userDetails;
PopUpManager.centerPopUp( myPopUp );
}
]]>
</mx:Script>
<mx:HBox>
<mx:Label text="Insert your Twitter username: " />
<mx:TextInput id="userTxt" />
<mx:Button id="userBtn"
label="Read latest message"
click="twclass.loadUserTimeline(userTxt.text);authorBtn.visible = true" />
</mx:HBox>
<mx:List dataProvider="{twclass.timelineDP}"
labelField="text" width="496" height="166"/>
<mx:LinkButton id="authorBtn" visible="false" label="See Twitter Account Details"
click="showDetails()" />
</mx:WindowedApplication>
The application has a TextInput control and a Button control that allow the users to insert their Twitter nicknames and download their timeline message lists. This list of messages is associated as a data provider to a List control through the timelineDP property of the ActionScript class that you created previously: dataProvider="{twclass.timelineDP}".
Finally, a LinkButton control allows you to open a pop-up window, controlled by the PopUpManager class, to which you pass the ActionScript Value object in the userDetails
property:
private function showDetails():void
{
var myPopUp:IFlexDisplayObject = PopUpManager.createPopUp (this, TwitterAuthor, true);
TwitterAuthor( myPopUp ).twitterDetails = twclass.userDetails;
PopUpManager.centerPopUp( myPopUp );
}
The second parameter that is passed to the createPopUp method of the PopUpManager class is an MXML component saved as TwitterAuthor.mxml. This component will be a subclass of the TitleWindow class, will take the Value object as a parameter, and will print its properties in the Flex controls:
<?xml version="1.0" encoding="utf-8"?>
<mx:TitleWindow xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute" title="Twitter Account Details"
width="320" height="240"
showCloseButton="true"
borderAlpha="1.0"
creationComplete="addEventListener( CloseEvent.CLOSE, closeMe );">
<mx:Script>
<![CDATA[
import mx.managers.PopUpManager;
import mx.events.CloseEvent;
import com.oreilly.aircookbook.bonus.TwitterUserVO;
[Bindable]
public var twitterDetails:TwitterUserVO;
private function closeMe( event:CloseEvent ):void
{
PopUpManager.removePopUp( this );
}
]]>
</mx:Script>
<mx:Image source="{twitterDetails.source}" x="10" y="12"/>
<mx:Label x="91" y="10" text="{twitterDetails.name}" />
<mx:Label x="89" y="36" text="{twitterDetails.screenName}" />
<mx:Label x="89" y="62" text="{twitterDetails.url}" />
<mx:Label x="89" y="88" text="{twitterDetails.location}" />
<mx:TextArea x="90" y="114" text="{twitterDetails.description}" />
</mx:TitleWindow>
JavaScript/HTML
For JavaScript, the TwitterJs library allows you to obtain a list of messages in your own web page. Created by remy sharp (http://remysharp.com), the TwitterJs library is available at http://code.google.com/p/twitterjs/downloads/list.
Download the zip file, extract it directly in the project folder, and import the file twitterjs/src/twitter.js.
The getTwitters method returns a list of messages. The parameters you can pass are as follows:
id(String): This is the username.count(Int): This can be 1–20, and it defaults to 1. The maximum limit is 20.prefix(String): This is in the format'%name% said'. It defaults to blank.clearContents(Boolean): This removes the contents of the element specified incssIdOfContainer; it defaults totrue.ignoreReplies(Boolean): This skips over tweets starting with@, and it defaults tofalse.template(String): This is the HTML template to use forlielements. This defaults to a predefined template.enableLinks(Boolean): This “linkifies” the text, and it defaults totrue.timeout(Int): This is how long before triggeringonTimeout. It defaults to 10 seconds ifonTimeoutis set.onTimeoutCancel(Boolean): This completely cancels the Twitter call if it times out. It defaults tofalse.onTimeout(Function): This is the function to run when the timeout occurs. This function is bound to the element specified with it.
The example in AIR uses the same approach as the previous solution. One web page incorporates a second web page through an iframe container, which carries out the JavaScript call to the Twitter APIs.
This is the code of the parent web page:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script type="text/javascript" src="frameworks/AIRAliases.js" />
<script type="text/javascript" src="frameworks/AIRIntrospector.js" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>AIR Cookbook: 18.3 Consuming Twitter APIs (JavaScript)</title>
</head>
<body>
<h1>AIR Cookbook: 18.3 Consuming Twitter APIs (JavaScript)</h1>
<iframe
id="twitter"
src="tweetrIframe.html"
sandboxRoot="http://SomeRemoteDomain.com/"
documentRoot="app:/" width="500" height="500"
/>
</body>
</html>
The core of the application is in the tweetrIframe.html page that is loaded in the iframe. In this web page, after importing the TwitterJs library, call the getTwitters method, which will return the message timeline.
This is the complete code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html lang="en">
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<title>Twitter Plugin</title>
<link rel="stylesheet" href="twitterjs/test/twitter.css" type="text/css" media="screen"
charset="utf-8" />
<script src="twitterjs/src/twitter.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript" charset="utf-8">
var twitter_id = '765942';
function loadMsg()
{
var nick = document.getElementById( 'location' ).value;
if (nick == 'Insert your Twitter nickname' || nick == '') { nick = 'marcocasario'}
getTwitters('msg', {
id: nick,
prefix: '<img height="16" width="16" src="%profile_image_url%" />
<a href="http://twitter.com/%screen_name%">%name%</a> said: ',
clearContents: false, // leave the original message in place
count: 10,
withFriends: true,
ignoreReplies: false,
template: '<span class="twitterPrefix"><img height="16" width="16"
src="%user_profile_image_url%" />
<span class="twitterStatus">"%text%"</span> <em class="twitterTime">
<a href="http://twitter.com/%user_screen_name%/statuses/%id%">%time%</a></em>'
});
}
</script>
</head>
<body id="page">
<input id="location" type="text" value="Insert your Twitter nickname" />
<input type="submit" name="go" id="go" value="Show Tweets" onclick="loadMsg()" />
<div class="twitters" id="msg">
<p></p>
</div>
</body>
</html>
The page displays a text input where users can insert their screen names used in Twitter and a button that, once it is clicked, invokes the loadMsg function. This function takes the value in the text input and, in turn, launches the getTwitters method from the TwitterJs library. This method, according to the parameters that are specified for it, returns the message timeline for the Twitter user who is specified in the text input. If the text input is left empty, the default nickname is marcocasario (my personal nickname).
Skip to another section of the Adobe AIR 1.5 Cookbook, Chapter 18, Developing Mashup AIR Applications:
Consuming Yahoo Maps Web Services | Consuming Flickr Web Services
Go to the catalog page for the Adobe AIR 1.5 Cookbook. Download the PDF of this entire chapter. View the book's table of contents.




Facebook Application Development
this is the worst article I ahve come across, I just hope and pray that this does not represent a real excerpt from the book, first of all the proposed html and script for HTML / Javascript AIR application doesn't work, and to even get to a point to realize it doesn't work you have to clean up the terrible html, tags invalid, tag not closed it's a joke...
gravely disappointing