PHP and HTTPService Chat

So about 2 weeks ago I decided that I should look through requests in the Adobe Cookbooks and see if I can contribute.  I found a few that I may work on in the future but the first one I started with was a request for a chat program in AIR using PHP, MySQL, and HTTPService.  Really I have a pretty simple solution to this question.  I don’t know if this is exactly what the person was looking for but it works.

The short answer is to create a PHP web service that can store messages typed into the chat and return a list of chats after a specific time period.  Then setup a timer that polls the webservice every X number of minutes.

Below is the long answer with some sample code.

MySQL Database

Obviously you can store whatever you want in the database.  I chose to store very basic information including an id, username, timestamp, message, and IP address.

</p>
<p>CREATE TABLE IF NOT EXISTS `chatmessages` (<br />
`id` bigint(20) NOT NULL AUTO_INCREMENT,<br />
`username` varchar(255) NOT NULL,<br />
`received` bigint(20) NOT NULL,<br />
`message` longtext NOT NULL,<br />
`ipaddress` varchar(20) NOT NULL,<br />
PRIMARY KEY (`id`)<br />
) ENGINE=MyISAM  DEFAULT CHARSET=latin1;</p>
<p>

PHP Webservice

I will include the complete PHP source in the final project as well but as I mentioned the webservice needs to insert a message and get a list of messages after a timestamp. Below is the SQL that I used based on the table above:

</p>
<p>$query = sprintf("INSERT INTO `chatmessages` (`username`, `received`, `message`, `ipaddress`) VALUES ('%s', %d, '%s', '%s')",<br />
mysql_real_escape_string($username),<br />
time(),<br />
mysql_real_escape_string($message),<br />
mysql_real_escape_string($_SERVER['REMOTE_ADDR'])<br />
);</p>
<p>
</p>
<p>$query = sprintf("SELECT * FROM chatmessages WHERE `received` >= %d",<br />
$timestamp<br />
);</p>
<p>

AIR Application

You will first need to setup an HTTPService to consume the PHP service.  If you are using Flex 4 you can place this in the <fx:Declarations> section of the file:

</p>
<p><fx:Declarations><br />
<s:HTTPService id="service"<br />
url="{serverUrl}"<br />
useProxy="false"<br />
method="POST"<br />
fault="service_faultHandler(event)"<br />
result="service_resultHandler(event)"/><br />
</fx:Declarations></p>
<p>

Then setup a timer that runs every 5 seconds or so.  When the timer completes you will call the webservice and download all of the messages since the last time you checked.  You also probably want to manually download the information anytime the client submits a message.

</p>
<p>private function startTimer(length:Number = 5000):void {<br />
pollTimer = new Timer(length, 1);<br />
pollTimer.addEventListener(TimerEvent.TIMER_COMPLETE, timerTick);<br />
pollTimer.start();<br />
}</p>
<p>private function timerTick(event:TimerEvent):void {<br />
getChatMessages(lastUpdated);<br />
updateTimestamp();<br />
}</p>
<p>private function getChatMessages(timestamp:Number = 0):void {<br />
service.send({method: OP_GET_CHATS, format: format, timestamp: timestamp});<br />
}</p>
<p>

To send a message you simply make a call to the web service:

</p>
<p>private function createChatMessage(message:String):void {<br />
service.send({method: OP_CREATE, format: format, username: username, message: message});<br />
}</p>
<p>

That’s it!

Conclusion

Other than handling the chat messages that are downloaded that is pretty much it.  This really is a simple solution and to be truly functional you would have to add more functionality into the application.  For example, you would want to make sure that no one else is logged in with a specific username.  You may also want to add in a table that keeps track of who is logged in and logged out.  That is slightly more difficult but essentially you would add in a logout button and then also add an event listener to detect when the app is closed.  You may also want to add in the functionality to have chat rooms.  All of these additions are simply extensions of this application.

The full source code for PHP, MySQL, and AIR are available at http://code.google.com/p/airchatexample/.

Finding a Better Solution

Polling just isn’t as desirable as you might think.  A better solution is to use RTMFP which allows you to create P2P connections.  For the short term you could create a chat application that uses the Adobe Cirrus service. There are a couple of good sample applications that use Cirrus:

I may, at some future point, do another example using Adobe Cirrus but I haven’t had time to do that yet.


Best WordPress Code Highlighting Plugin

Does anyone have a recommendation for which plugin to use for code highlighting in WordPress?  The one I use now is Qoate Simple Code Snippets and it works OK.  But it doesn’t do whitespace or syntax highlighting.


PopUpList for Mobile

With the recent post Debugging A Swipe Gesture I included the functionality to view the history of swipes in the application.  I didn’t highlight this functionality in the previous post but I added a new component to the Day2DayDevelopment library called PopUpList.  This is a simple component but it is a mobile popup that displays a list with a close button.  The image below is from the Debugging A Swipe Gesture application.

To popup the PopUpList component you use the following code:

</p>
<p>var window:PopUpList = new PopUpList();<br />
window.listData = history;<br />
window.labelFunction = historyList_labelFunction;<br />
PopUpManager.addPopUp(window, this);<br />
PopUpManager.centerPopUp(window);</p>
<p>

This is a simple example but I thought I would highlight it.  Again the component is available in the Day2DayDevelopment library I am slowly putting together and the example is in the GestureDebugging example.


Debugging A Swipe Gesture

One of the problems that you run into with mobile applications is working with gestures. The emulator that you use with Flash Builder Burrito  does not have any way of simulating swipe gestures.  You can test the swipes on a device if you have one handy but even then it is annoying to push the application to your device every time you  need to test the gestures.  This example will demonstrate a way to use View States to debug swipe gestures from the built-in emulator.

Begin by creating a Flex Mobile Project and within the firstView of the project and add a couple of states.

</p>
<p><s:states><br />
<s:State name="GestureSwipeEnabled"/><br />
<s:State name="GestureSwipeDisabled"/><br />
</s:states></p>
<p>

These two View States are the primary component of this example.  Next add a creationComplete event listener on the View.  The eventListener has to check and see if gestures are supported by the device.

<br />
Multitouch.inputMode = MultitouchInputMode.GESTURE;</p>
<p>if (Multitouch.supportedGestures == null || Multitouch.supportedGestures.length == 0 || Multitouch.supportedGestures.indexOf(TransformGestureEvent.GESTURE_SWIPE) == -1) {<br />
this.currentState = "GestureSwipeDisabled";<br />
}<br />
else {<br />
this.currentState = "GestureSwipeEnabled";<br />
}</p>
<p>

Set the View State accordingly based on the abilities of the device.  Now place a border of buttons (1 on the top, bottom, left, and right) around the View.  You can do this a variety of ways.  I chose to use a combination of HGroup and VGroup containers.  With Flex 4 View States are different than previous versions.  You can now specify includeIn or excludeFrom (which are mutually exclusive) for each component.  For each of the buttons add the property “includeIn=’GestureSwipeDisabled'”  What the View State does is shows the buttons if gestures are not enabled on the device and hides them if they are.

Add a click event listener to each button and dispatch the event accordingly. Below is an example of what the button MXML would look like this:

<br />
<s:Button id="cmdRight" label="" width="20" height="100%" click="cmdRight_clickHandler(event)" includeIn="GestureSwipeDisabled"/></p>
<p>

Below are some screenshots of the app running in different emulators and one from an Android Nexus One.

The source code for this project can be found on Google Code at http://code.google.com/p/hero-gesture-debugging/ This project requires a component in the Day2DayDevelopment library available at http://code.google.com/p/day2daydevelopment/ The library is open source so feel free to download it.


What is PressAndTapGestureEvent?

So I have been looking at some of the gesture possibilities with Flex Hero and ran in to one call PressAndTapGesture.  Now I am not exactly sure what a press and tap is but it sounds like you press with one finger and tap with the other.  Or maybe it is press and hold and then release.  Well I wanted to figure it out to see if I could use it in a sample that I am working on so I built a simple example project.  Now the problem is that the emulator does not support gestures.  So I pushed it out to an Android Nexus One and am unable to get the event to fire.

So as I tweeted earlier DUMB QUESTION ALERT what is a press and tap gesture?  The description of it in the docs is this: “The PressAndTapGestureEvent class lets you handle press-and-tap gesture on touch-enabled devices. Objects that inherit properties from the InteractiveObject class capture the primary touch point (press) and a secondary point (tap) in the dispatched event object. The press-and-tap gesture is typically used to raise a context-sensitive popup menu.” To me that sounds like pressing down with one finger and tap with a second which I have tried and it does tend to bring up the default context menu which allows for copy and paste.  However, I cannot reproduce the event on the device.

I have uploaded a sample Flash Builder project.  If anyone else can figure out how to generate the Press and Tap event that would be great.  I added a button to manually dispatch the event and the event listener is working.  I apparently just don’t know how to do the right gesture.

Here is the sample Flash Builder project: http://www.day2daydevelopment.com/wp-content/uploads/2010/12/PressAndTap_Example.fxp


Pages:12345