he Java 2 Platform, Micro Edition (J2ME) is targeted at cell phones, smart cards, pagers, and other consumer devices. J2ME technology consists of a virtual machine and a set of APIs suitable for tailored runtime environments for these devices. PHP, on the other hand, is a widely used server-based language to build Web applications. But these two radically different technologies work very well together. In this article you’ll see how they can interact via HTTP (Hyper Text Transfer Protocol). Of course, this is not intended to be a thorough explanation of how HTTP works?you only need to know that HTTP is a request/response protocol. That simply means that the client application performs a request and the server application returns a response.
Figure 1 illustrates a typical HTTP-based Client/Server communication. In this case, the client requests the latest news to a Server sending it the type of news wanted. The Server simply responds to the Client sending it the news requested.
You understand then, that as long as client and server “speak” the same protocol they can communicate without problems. HTTP is the ad hoc protocol for our purposes. In fact, HTTP doesn’t specify which entity is supposed to be either the client or the server. The client can be a Web browser, a mobile device, or anything else, provided that the applications on both ends can communicate through HTTP. For example, suppose you write something like this in PHP:
![]() | |
Figure 1. Client/Server Communication: The figure illustrates the process by which a client requests and receives news from a server. |
echo "Hello World";
The result depends on the client performing the request. If the client is a Web browser then it will display the string “Hello World.” If the client is a mobile phone it will just receive the string “Hello World” as a stream of bytes from the server.
The point is that it’s not hard to get a mobile device, running J2ME to communicate with a server running PHP as long as both use the HTTP protocol.
A Sample Project
As I’m sure many of you developers out there are, I’m fed up with parsing RSS feeds to get information and links. RSS feeds are nothing more than XML files with a particular structure. They are used mainly to represent a set of items published on a Web site. Here’s an RSS feed excerpt:
... -
The title of the first article The description of the first article The link to the full article ... -
The title of the second article ... ...
Each item has title and description elements as well as link elements that point to the full article online (and other elements that are of no interest for this project).
In this article I’ll show you how to design and implement an application for mobile devices that retrieves the latest news from some Web sites that offer RSS feeds as a service. The application will fetch the title and the corresponding description of each article of the RSS feed.
The following images serve to clarify the intent and overall functionality of the application.
|
|
|
I won’t discuss the server side of the application in detail because it just parses the RSS feed?you can find numerous tutorials and articles that explain that process, and both the server PHP code and the client J2ME code are included in the sample code that accompanies this article. The only thing that matters for this article is that the server-side PHP script fetches the titles and the descriptions from the news Web sites (www.nytimes.com and www.bbc.co.uk), and returns them in this fashion:
The title of the first article The description of the first article The title of the second article The description of the second article ...
There are two main reasons for “shrinking” the news feeds this way. First, reducing the number of bytes downloaded from the Web server decreases download costs for clients who pay by byte volume for their mobile devices (which is often the case). Second, the less data you download, the faster the application will be.
Of course, the client side is responsible for restoring the information in a convenient fashion.
Client Side Implementation
On the client side (that is on the mobile device), the code must:
- Build a simple GUI that will:
- Let users select the type of news they’re interested in.
- Display the list of titles of each item.
- Show the complete item selected (title and description).
- Establish a connection with the Web server, providing it with a string representing the type of news the user wants to get.
- Get the actual news sent by the server.
- Parse the “raw” news received from the server and display the results in usable form.
The classes used to accomplish that are:
- WirelessNews, responsible for the GUI.
- NewsFetcher, responsible for connecting to the Web server and retrieving the news items.
- NewsParser, which parses the “raw” news sent by the server.
- News, which represents an item through its title and description
Starting with the simplest, here’s the News class code:
class News { String title; String description; public News(String title, String description) { this.title = title; this.description = description; } public void setTitle(String title) { this.title = title; } public void setDescription(String description) { this.description = description; } public String getTitle() { return title; } public String getDescription() { return description; } }
As you can see there isn’t much to say about this class. It consists entirely of classic “getter” and “setter” methods.
The WirelessNews class
The WirelessNews class is more interesting. The code is shown in Listing 1.
As you can see from the screenshots in Figures 2, 3 and 4, the class needs to create and manage three screens. I called these screens channelsList, titlesList and fmDescription. The first screen shows the list of the available channels. In this context, by channel I mean a type of news, such as “World News”, “US News” etc. The second screen shows the list of the titles of the news fetched by NewsFetcher (you’ll see this class in detail later). The form fmDescription, displays individual item titles and descriptions.
Four commands, cmSelect, cmExit, cmBack, and cmMain handle interface interactions. The first, cmSelect, selects either the type of news to fetch or the title of the article the user wants to fully read. The command cmExit exits the application. The other two commands switch to the previous menu and the main menu respectively.
Since WirelessNews extends the MIDlet class, it must implement its three abstract methods, startApp, pauseApp and destroyApp, which are invoked when the application gets started, paused and destroyed, respectively. The startApp method sets channelsList as the current display. The most important method of this class is commandAction, which is the application event handler, invoked when a command is selected. This method is declared in the CommandListener interface. Here’s the code for commandAction:
public void commandAction(Command c, Displayable d) { //exit command if(c == cmExit) { destroyApp(false); notifyDestroyed(); } //d == channelList if(d == channelsList) { //get the index of the channel selected int channelIndex = channelsList.getSelectedIndex(); //create a class instance of the class to fetch the news NewsFetcher nf = new NewsFetcher( channels[channelIndex], this); //show an alert indicating we are starting a download showAlert("News Downloading..." + "When done it will be displayed on the screen", d); //start the download nf.start(); } //d == titlesList if(d == titlesList) { // back command if(c == cmBack) display.setCurrent(channelsList); // select command. Show the description if(c == cmSelect) showDescription((News)news.elementAt( titlesList.getSelectedIndex())); } //d == fmDescription if(d == fmDescription) { //back command if(c == cmBack) display.setCurrent(titlesList); //main menu if(c == cmMain) { titlesList = null; display.setCurrent(channelsList); } } }
The first thing this method does is check if the button pressed is cmExit, because if it is, the application has to exit, irrespective of which screen is currently active. All other actions, however, depend on the current screen. Because there are three different screens, there are three different cases to analyze in addition to cmExit:
- Case A: The current screen is channelsList. This is a “special” case. It has only one active command?cmSelect. In this case the method retrieves the index of the selected channel and creates a NewsFetcher instance, passing in the string representing the channel and the current MIDlet. After that, it displays an alert to indicate that a download is starting, and launches the actual download by calling start on the NewsFetcher object. You’ll see how NewsFetcher works later on this article. For the moment, it’s sufficient to know that NewsFetcher performs the actual download of the news on a separate thread.
- Case B: The current screen is titlesList. This screen has two options: either the user selected cmBack or cmSelect. For cmBack the method sets channelsList as the current display. For cmSelect the method invokes showDescription, passing in the selected news item. The showDescription method assigns the item’s title and description to frmDescription and sets that as the current screen.
- Case C: The current screen is fmDescription. The options here are cmBack and cmMain. The former switches to titlesList, the latter switches to channelsList.
The remaining method in the Wireless class is showTitles. The method accepts a Vector object representing a list of News objects, a Boolean representing the status of the download (success or failure) and a string representing the type of news. When the status is false, the method shows an alert displaying “bad” news, which is a download failure. When it’s true, on the other hand, it builds a string array containing the titles of the news items just fetched. The method then instantiates titlesList, passing in (among other things) the titles to display. Finally the application displays the list of titles on the mobile device’s screen.
The showAlert method doesn’t requires any additional explanation, because it simply displays a standard alert message.
The NewsFetcher Class
Finally, the NewsFetcher class is responsible for downloading the articles from the Web on a separate thread to maintain the responsiveness of the user interface (see Listing 2).
Note the form of the URL field, for example:
http://localhost:8000/WirelessNews/RSS.php
On my PC, I set the Apache Web Server to listen on port 8000 because I already had IIS listening on the default port 80. However, you’ll need to change the URL string to an appropriate value for your environment. Then, when uploading the PHP files to a “real” Web Server, you will have to change the URL string to a form like this:
http://www.yourwebsite.com/WirelessNews/RSS.php
The core method of NewsFetcher is getNews, as shown below:
private void getNews() throws IOException { InputStream is = null; StringBuffer sb = new StringBuffer(); HttpConnection http = null; try { //append the channel name onto the URL URL += "?channel=" + channelName; //replace not allowed chars in the URL URL = encodeURL(URL); //establish the connection http = (HttpConnection) Connector.open(URL); //set the request method as GET http.setRequestMethod(HttpConnection.GET); //server response if(http.getResponseCode() == HttpConnection.HTTP_OK) { int ch; is = http.openInputStream(); while((ch = is.read()) != -1) sb.append((char) ch); } } catch (Exception e) { System.err.println("Error: " + e.toString()); } finally { if(is != null) is.close(); if(sb != null) news = new String(sb); else news = new String(); if(http != null) http.close(); } Vector v; //extract titles and descriptions from the news if(news != "") { //success //for debug purpose only System.out.println(news); v = (new NewsParser(news)).parse(); midlet.showTitles(v, true, channelName); } else { //failure v = new Vector(); midlet.showTitles(v, false, channelName); } }
This method tries to establish an HTTP connection (type HttpConnection). It first appends the request string to the URL; then it calls the encodeURL method, which encodes the URL, replacing any characters not allowed in a URL string. The core part of the method tries to establish the actual connection with the URL, sets the request method to GET and checks the response from the server. If the response is OK, the method passes the string returned by the response to the showTitles method that you saw in the WirelessNews class.
The NewsParser Class
The server returns “raw” news to the mobile device, which must be parsed to extract the titles and descriptions. NewsParser is the class responsible for doing that. Here’s the code:
class NewsParser { private String rawNews; private int index; public NewsParser(String rawNews) { this.rawNews = rawNews; this.index = 0; } public Vector parse() { Vector v = new Vector(); if(rawNews =="") return v; //extract the news while(index < rawNews.length()) { //extract the title String title = extractText(index, "t"); //extract the description String description = extractText(index, "d"); News news = new News(title, description); v.addElement(news); } return v; } //extract the text (a title or a description //depending on the type parameter) private String extractText(int beginIndex, String type) { String startTag = "<" + type + ">"; String endTag = "" + type + ">"; //find the index of startTag in rawNews, starting //from beginIndex int begin = rawNews.indexOf(startTag, beginIndex); //move 3 chars ahead to point to the beginning of //the actual text (title or descr.) begin += 3; //find the index of endTag in rawNews, //starting from begin int end = rawNews.indexOf(endTag, begin); //update index index = end + 4; //return the actual text representing a title //or a description return rawNews.substring(begin, end); } }
The parse method performs the actual parsing. This method returns a Vector of News objects. NewsParser has two fields: rawNews and index. The former is the string representing the news downloaded from the server. The latter represents a pointer to the character position within rawNews where the parse method begins looking for the next title and description. Here’s an example to clarify. Suppose rawNews is:
A new article has been published on DevX.com This article deals with J2ME, PHP and their interaction Funny saying There are only 10 types of people in the world: those who understand binary and those who don't! ...
When you instantiate a NewsParser instance, index points to the first char of rawNews, which is “<“. When the parse method gets called, it extracts titles and descriptions until it reaches the end of rawNews. It accomplishes this using a helper method, extractText, which receives beginIndex and type as parameters. The first represents the starting character index, which is constantly updated as the method moves through the raw input. The type parameter represents the type of text to extract: “t” for title, or “d” for description. The extractText method extracts the text, updates index to the new value and returns the extracted text. For each title and description extracted, parse creates a News object and adds it to the vector. Finally it returns the vector to the getNews method.
This article has described how J2ME and PHP can interact. As a proof of concept, you have seen how to build a pretty useful application that allows a user to get the latest news from the Web. Of course, you could improve the simple sample project, for example by storing the information retrieved from the Web on the mobile device using RMS (Record Management System). But that’s another story.