Tuesday, September 30, 2003

J2ME: Get Weather Forecasts Free

Weather on Demand is one of the most common applications of SMS. Few of weather service examples are:

1. Weather alerts from Verizon .
2. Weather Network and TELUS Mobility's On Demand Weather service and
3. Weather.com's Radar on Mobile Phones.
With a simple MIDlet you can get Weather forcasts free on your phone. US government provides free weather forecasts here. Note that the weather forecasts are not as high quality as commercial services. The simple MIDlet here displays weather at SF(modify the URL to point to your city):




001 import java.io.IOException;
002 import java.io.InputStream;
003 
004 import javax.microedition.io.Connector;
005 import javax.microedition.io.StreamConnection;
006 import javax.microedition.lcdui.Command;
007 import javax.microedition.lcdui.CommandListener;
008 import javax.microedition.lcdui.Display;
009 import javax.microedition.lcdui.Displayable;
010 import javax.microedition.lcdui.Form;
011 import javax.microedition.midlet.MIDlet;
012 
013 
014 /**
015  * MIDlet to display weather forecast for SF.
016  *
017  @author Kumar Mettu
018  @version 1.0
019  *
020  */
021 public class Weather extends MIDlet implements CommandListener {
022 
023     private Display display;
024     //Exit command.
025     private Command  exitCommand = new Command"Exit", Command.SCREEN, );
026     //SF Weather URL.
027     private static final String SF_URL =
028         "http://weather.noaa.gov/pub/data/forecasts/city/ca/san_francisco.txt";
029 
030     /**
031      * Weather MIDlet constructor.
032      */
033     public Weather() {
034        display = Display.getDisplay(this);
035     }
036 
037     /**
038      * This will be invoked when we start the MIDlet.
039      * Display the downloaded data. If an error occurs while downloading
040      * the data display the error to user.
041      *
042      */
043     public void startApp() {
044         try {
045             getViaStreamConnection();
046         catch (IOException e) {
047             Form forecast = new Form("Error Downloading");
048             forecast.append(e.getMessage());
049             forecast.addCommandexitCommand );
050             forecast.setCommandListenerthis );
051             display.setCurrent(forecast);       
052        }
053     }
054 
055     /**
056      * Pause, discontinue ....
057      */
058     public void pauseApp() {
059 
060     }
061 
062     /**
063      * Destroy. Cleanup everything.
064      */
065     public void destroyApp(boolean unconditional) {
066     }
067 
068     /**
069      * Download the weather and display it.
070      *
071      @throws IOException when IO Error occurs while downloading
072      *  data from URL.
073      */
074     private void getViaStreamConnection() throws IOException {
075         StreamConnection sc = null;
076         InputStream in = null;
077         StringBuffer b = new StringBuffer();
078 
079         try {
080           sc = (StreamConnection)Connector.open(SF_URL);
081           in = sc.openInputStream();
082           int ch;
083           while ((ch = in.read()) != -1) {
084              b.append((charch);
085           }
086 
087         finally {
088            if (in != null) {
089               in.close();
090            }
091            if (sc != null) {
092               sc.close();
093            }
094         }
095 
096         Form forecast = new Form("Weather at SF");
097         forecast.append(b.toString());
098         forecast.addCommandexitCommand );
099         forecast.setCommandListenerthis );
100         display.setCurrent(forecast);
101     }
102 
103     /**
104      * Indicates that a command event has occurred on Displayable d.
105      @param c - a Command object identifying the command.
106      @param d - the Displayable on which this event has occurred.
107      */
108     public void commandActionCommand c, Displayable d ){
109         if (c == exitCommand){
110             exit();
111         }
112     }
113 
114   /**
115    * Distroy app when exit button is used.
116    */
117     private void exit(){
118         destroyApp(true);
119         notifyDestroyed();
120     }    
121 
122 }



You can download Weather.jar and Weather.jad directly. Tested on my i88s. Here is the screen snapshot of Motorola i88s simulator:



This can be further extended to support features like:
1. Select the city where you want weather forcast(using kxml)
2. If your phone supports GPS( like my Motorola i88s), you can display weather forecasts for your current location.

Monday, September 29, 2003

M$: MSBuild - M$ version of ANT

Microsoft is coming up with a build tool(MSBuild). MSBuild is the next generation build engine and platform for Visual Studio .NET. Microsoft has a session about the new build system during Microsoft Professional Developers Conference 2003.
From introduction it looks like it will ship with the .NET redistributable and not Visual Studio. Also it appears that MSBuild will be an XML based Ant like tool with XML files to drive the build. Of course a similar build tool exist as Nant.
This is yet another block that has been missing in .NET (compared to J2EE) that Microsoft decided to fill.

Saturday, September 20, 2003

J2SE: Taking screen snapshots in JAVA

As programmers many a times we need take snap shots of our screens. If we can take snap shot in java why use OS specific way to take a snap shot?
Here is a simple code example of taking snapshot in java (Either PNG format or JPEG format):




01 import java.awt.AWTException;
02 import java.awt.Dimension;
03 import java.awt.Rectangle;
04 import java.awt.Robot;
05 import java.awt.Toolkit;
06 import java.awt.image.RenderedImage;
07 import java.io.File;
08 import java.io.IOException;
09 import javax.imageio.ImageIO;
10 
11 /**
12  * A Simple program that saves current screen snapshot.
13  * Supported formats png and jpg.
14  * Usage java ScreenSnapShot <<outputfilename>>
15  *
16  @author Kumar Mettu
17  @version 0.61
18  */
19 public class ScreenSnapShot {
20 
21     public static void main(String[] argsthrows IOException,AWTException {
22 
23         String saveFileName = "default.png";
24         String saveFileFormat = "png";
25 
26         if (args.length > 0)
27             saveFileName = args[0];
28 
29         if (saveFileName.toLowerCase().endsWith(".png")) {
30             saveFileFormat = "png";
31         else if (saveFileName.toLowerCase().endsWith(".jpg"||
32                    saveFileName.toLowerCase().endsWith(".jpeg")) {
33             saveFileFormat = "jpg";
34         else {
35             System.err.println("Only png and jpg formats are supported.");
36             System.exit(1);
37         }
38 
39         // get current sceen size for snapshot.
40         Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
41         Rectangle screenRect = new Rectangle(screenSize);
42 
43         // create current screen snapshot
44         RenderedImage image = (new Robot()).createScreenCapture(screenRect);
45 
46         if (ImageIO.write(image, saveFileFormat, new File(saveFileName))) {
47             System.out.println("Screen snap shot is saved as :" + saveFileName);
48         else {
49             System.out.println("Unable to save snap shot");
50         }
51     }
52 }



This code requires J2SE1.4. There is no real use of this code unless you extend it to make use of it(like taking snapshots at fixed intervals etc...).

Friday, September 19, 2003

General: China to help Europe develop GPS rival

New Scientist reports China has joined a European effort to develop a new global satellite navigation system that would offer a more accurate civilian alternative to the Global Positioning System. The Galileo system will be precise to within a meter, while the civilian GPS service is accurate to around 10 meters. This development adds to the consternation of the U.S. military, which controls the GPS and currently enjoys the option of downgrading the civilian service during military conflicts.

Sunday, September 14, 2003

Microsoft links with Motorola to launch mobile phone

Telegraph | Money | Microsoft links with Motorola to launch mobile phone: "Microsoft's bid to dominate the market for mobile phone operating systems will receive a boost today when the US software giant launches its first phone with a major handset maker."

Untold story:In a related product launch Steve Ballmer, Chief Executive Officer Microsoft Corp announced general availability of the Blue Screen of Death sized down for use in Motorola handset

Friday, September 12, 2003

J2SE: A nice tool to learn API differences

JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared. This is very useful for describing exactly what has changed between two releases of a product. Only the API (Application Programming Interface) of each version is compared. It does not compare what the source code does when executed.

Sample Reports:
Comparing J2SE1.4.0 and J2SE1.4.1
Comparing J2SE1.3.1 and J2SE1.4

Tuesday, September 09, 2003

J2ME: Turning your phone into web Server.

I wrote a simple midlet which turns my Phone into simple web server. To keep the code simple, I removed the additional GPS capabilities. Currently the web server listens to port 8000 and repsonds "Hello, I am Kumar Mettu's Phone. Thanks for Visiting" for all requests that are sent to this tiny web server. Note that this code is tested only on Motorola i88s with Nextel Total Connect Service.

Here is the code for the tiny web server:




001 import java.io.IOException;
002 import java.io.InputStream;
003 import java.io.PrintStream;
004 
005 import javax.microedition.io.Connector;
006 import javax.microedition.io.StreamConnection;
007 import javax.microedition.io.StreamConnectionNotifier;
008 import javax.microedition.lcdui.Display;
009 import javax.microedition.midlet.MIDlet;
010 
011 /**
012  * MIDlet working as simple personal WebServer.
013  * Currently this serves simple HTTP GET operation.
014  *
015  @author Kumar Mettu
016  @version 0.61
017  */
018 
019 public class WebServer extends MIDlet {
020 
021     private Display display;
022 
023     StreamConnectionNotifier scn = null;
024 
025     /**
026      * Default constructor.
027      */
028     public WebServer() {
029        display = Display.getDisplay(this);
030     }
031 
032     /**
033      * This will be invoked when we start the MIDlet
034      */
035     public void startApp() {
036         try {
037             scn =(StreamConnectionNotifier)Connector.open("serversocket://:8000");
038             while (true) {
039                 StreamConnection sc = (StreamConnection)scn.acceptAndOpen();
040 
041                 // service the connection in a separate thread
042                 Connection c = new Connection(sc);
043                 c.start();
044             }
045 
046 
047         catch (IOException e) {
048             //Handle Exceptions any other way you like.
049             //No-op
050         }
051     }
052 
053     /**
054      * Pause, discontinue ....
055      */
056     public void pauseApp() {
057         try {
058             if (scn != null)
059                 scn.close();
060         catch(Exception e) {
061         }
062 
063     }
064 
065     /**
066      * Destroy. Cleanup everything.
067      */
068     public void destroyApp(boolean unconditional) {
069         try {
070             if (scn != null)
071                 scn.close();
072         catch(Exception e) {
073         }
074     }
075 
076     /**
077      * Thread to handle client request.
078      */
079     class Connection extends Thread
080     {
081 
082         public Connection(StreamConnection c) {
083             client = c;
084         }
085 
086         /**
087          * Handles client request.
088          */
089         public void run() {
090             InputStream s = null;
091             PrintStream out = null;
092             StringBuffer b = new StringBuffer();
093             try {
094 
095                 s = client.openInputStream();
096 
097                  //Ignore reading request to reduce the amount of data
098                  //transfered to Phone.
099                 /*int ch;
100                 while((ch = s.read()) != -1) {
101                     b.append((char) ch);
102                 }
103                 System.out.println(b.toString());*/
104 
105                 out = new PrintStream(client.openOutputStream());
106                 String response =
107                              "&lt;HTML&gt;"+
108                              "&lt;HEAD&gt;"+
109                                 "&lt;TITLE>Kumar's Location&lt;/TITLE&gt;"+
110                              "&lt;/HEAD&gt;"+
111                              "&lt;BODY&gt;Hello, I am Kumar Mettu's Phone. "+
112                                      "Thanks for Visiting.&lt;/BODY&gt;"+
113                              "&lt;/HTML&gt;";
114                 out.println("HTTP/1.0 200 OK\n");
115                 out.println(response);
116 
117             }
118             catch (Throwable ioe) {
119                 //Handle Exceptions any other way you like.
120                 //No-op
121             }
122             finally {
123                 try {
124                     if (s != null)
125                         s.close();
126                     if (out != null)
127                         out.close();
128                     if (client != null)
129                         client.close();
130                 }
131                 catch (IOException ioee) {
132           //Handle Exceptions any other way you like.
133           //No-op
134                 }
135             }
136         }
137 
138         private StreamConnection client;
139     }
140 
141 }
142   



I know there is no business value for this web server. But hey turning phone into a web server and viewing it serve web pages to browser is fun :-)