Tcoz Tech Wire

Discoursing on trends and technologies interesting to Tim Consolazio, sole proprietor of Tcoz Tech Services, specializing in Flash/Flex/Air, iPhone, Facebook, Twitter, and related technologies.

"Technology from an indie software developer's perspective".

Sunday, May 31, 2009

TcozTwitter: A Twitter Client using Adobe Air and the Flex Mate Framework - Day 3

TcozTwitter: A Twitter Client using Adobe Air and the Flex Mate Framework - Day 3

As @lancearmstrong says, "onward".

This is a continuation of TcozTwitter: A Twitter Client using Adobe Air and the Flex Mate Framework - Day 2, in which I decided to complete a number of technical exercises by building a Twitter desktop client using the Twitter API, Adobe Air and the Mate Framework.

This time around, I completed two major steps: the full parsing of a tweet with all associated data (so that I can display the message info finally), and preliminary incorporation of ads, which I tried to make as unobtrusive as possible.

Parsing the tweets turned out to be easy. If you want to get an idea of the XML that makes up a tweet, take a look at this file, which is a dump of the raw XML returned from the service call I discussed in the day 1 article. Make sure you view the source of the page; if you just click the link and view it as a regular web page, it'll look like an endless string of jumbled user data.

If you look at the XML, you see that a user's data is actually represented by an element called "status" that contains two parts; a top-level set of children that holds the message info, and a child element called "user", which contains all the user info, like name, id, number of followers, etc. Manager_Tweets gets fed all that XML when it returns from the EventMap handler (see days 1 and 2 for an explanation of this), breaks it up into an array of "status" elements, and pushes them onto Model_Tweets as an array of new Data_Tweet objects. So, whenever I want to grab the current list of public tweets, I just have to call Model_Tweets.getInstance ( )._publicTweets, and I'll get back an array of Data_Tweets. As I get more tweets, I just keep pushing them onto these waiting arrays on Model_Tweets, so I get a running list of tweets for the entire user session. As I work with different kinds of tweets, like Area, Trends, and different accounts, I'll just add more service calls to the EventMap, add more arrays to Model_Tweets, and push new Data_Tweets onto them.

Each Data_Tweet object gets one "status" element, which it cuts up into two XML fragments: the message, and user, parts. I then iterate each of the child elements in both parts and push the values onto objects, with the element names as the property names. The end result; each Data_Tweet exposes two objects, one with all that user's message info, and one with all that user's identity info.

The code in Data_Tweets that does the chopping up looks like this. Note that I've created two arrays filled with the property names I'm interested in, then I iterate those arrays, using the property names as the identity of the XML elements I want. This is sort of a lazy man's way of pseudo-typing data; eventually I'll probably just use real properties so that code hinting and such reveals the properties like any other typed object. But for now, this is a good, fast way to get the job done, and I am still using the actual property names instead of something made up.

_messageInfoProps = [ "created_at",
etc. etc. ];

_userInfoProps = [ "id",
etc. etc. ];

_messageInfo = new Object ( );
_userInfo = new Object ( );

var xml : XML = XML ( data );
for ( var each : String in _messageInfoProps )
_messageInfo [ _messageInfoProps [ each ] ] = XML ( xml [ _messageInfoProps [ each ] ] ).text ( ).toString ( );

var userPropsList : XMLList = xml.user;
var userPropsXML : XML = XML ( userPropsList.toXMLString ( ) );
for ( each in _userInfoProps )
_userInfo [ _userInfoProps [ each ] ] = XML ( userPropsXML [ _userInfoProps [ each ] ] ).text ( ).toString ( );

There's really nothing to it; get the XML from the Mate handler, pass it to Manager_Tweets, which breaks it into a list of "status" elements, then itereate that list, feeding each element to a new Data_Tweet, which parses the data into the pseudo-typed objects, then push those Data_Tweet objects onto a waiting array in Model_Tweets. I now have a subsystem to receive, parse, and store, tweets. For now I'm just using public ones, but I'm willing to bet that account-specific ones are no different.

Now onto the money shot: ads. ARGH, I know, god damn ads. But c'mon; I'm investing time and effort, not to mention using software and hardware I purchased, and so on; it'd be nice to actually make some money doing this, or at least, show that I understand how to do it, which is a great demo item for getting contract work.

I decided right away, that however I implemented ads, I wanted to make sure:

- The ad impression (an industry term for showing an ad) is immediately visible, but unobtrusive.
- There is only one "forced impression" per user session, and it won't last more than five seconds.
- There needs to be a way to view the ad again in case the user is interested.
- I want to be free to tweak this at will.

The implementation:

- The ad appears at the bottom of the app for five seconds, then fades out.
- After fading out, the ad is replaced with a very thin, translucent bar at the bottom of the app.
- This "ad bar" displays a message "Click to see the [name of advertiser] ad".
- When you click the bar, it shows the ad again for five seconds. If you never click it, you'll never see another ad.
- When you click the ad, it opens a browser window for the target URL.

Regarding freedom to tweak, that means, not compromising this unobtrusive design in any way, which means, I can't pander to the requirements of any particular ad agency. So, I actually set up my own ad server. I'm using the latest version of OpenAds, which is a free and full-featured ad server, used by such techno-luminaries as TechCrunch. I've worked with OpenAds before, but never actually built out an instance of it. I was pleased to find, OpenAds is simple to set up and simple to use. Just go through the instructions and tutorials carefully, and you'll have a full-featured, industrial strength ad server, with campaign provisioning and tracking, even marketing integration, all ready to go. From Flash, you make XML-RPC calls to the OpenAds server, it runs its logic, and returns an ad it selects as an XML response containing the info to display, like URL of the ad, target when you click it, etc.

To get started, I have a friend that owns a business called Genius Ride; he leases smart cars, delivered right to your door. I took his ad, dumped it into the OpenAds system, and set up an advertising campaign with it. The Flash client calls OpenAds when it starts, requests an ad (which at this time always returns genius ride, because it's the only campaign I'm running), and displays it as previously mentioned.

The screenshots below show the current in-progress state of the TcozTwitter desktop client.

As always, thanks for visiting.

With ad:

After ad fades:


Labels: , , , , , , , ,