Showing posts with label j2me. Show all posts
Showing posts with label j2me. Show all posts

Saturday, September 3, 2011

Google Static Maps API and JavaME

Whether you need a map for your location based application or just for fun, you can use the easiest way ever: Google Static Maps API. In this post, we are going to see how you can get a Map as an Image from a latitude and longitude point. The latitude and longitude can be obtained using Location API which we won't discuss in this post.

When writing this post, I realized there is some license restrictions in the use of Google Static Maps API in mobile Apps... I am posting it anyway just for research purposes, but I must warn you about this restriction:



Google Static Maps API Quick Review
This API lets you get an Image based on a URL and several parameters you can pass in to obtain a personalized map. You can play with the zoom, type of map, size of the image (width, height), markers at locations of the map, etc. There is a limit you have to keep in mind, the use of the API is subject to a query limit of 1000 unique (different) image requests per viewer per day, which is a lot of images... but if you need more, there is also a Premium license. For more information:


OK, what we do is the following:
  • Create a method that receives a latitude and longitude point and the size of the image as parameters.
  • Request the map image using the URL: http://maps.googleapis.com/maps/api/staticmap, and adding some parameters.
  • Create an Image object and return it, so we can show it on screen.

Hands on Lab
Following is the method we were talking about. It has parameters for the latitude and longitude, and also for the width and height of the image we are requesting. The latitude and longitude can be retrieved using Location API, and the width and height can be retrieved using the Canvas class.

public Image getMap(double lat, double lon, 
                                int width, int height) 
throws IOException 
{
    String url = "http://maps.google.com/maps/api/staticmap";
    url += "?zoom=15&size=" + width + "x" + height;
    url += "&maptype=roadmap";
    url += "&markers=color:red|label:A|" + lat + "," + lon;
    url += "&sensor=true";

    HttpConnection http = (HttpConnection) Connector.open(url);
    InputStream in = null;
    byte[] imgBytes = null;
    try {
        http.setRequestMethod(HttpConnection.GET);
        in = http.openInputStream();

        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int n = 0;
        while ((n = in.read(buffer)) != -1) {
            bos.write(buffer, 0, n);
        }
        imgBytes = bos.toByteArray();
    } finally {
        if (in != null) {
            in.close();
        }
        http.close();
    }
    Image img = Image.createImage(imgBytes, 0, imgBytes.length);

    return img;
}

As you may see, it is pretty simple to get the image of the map. The retrieving is pure HTTP request.
Next you can find an image retrieved by Google Static Maps from a location in my home town.


OK, you just saw how simply it would be if no restriction exists... What do you think about that restriction? It's kind of confusing, isn't it?

Anyway, we are going to need to find another way to show maps on our mobile apps.

see ya soon!

References:

Google Static Maps API. [online].
Available on Internet: http://code.google.com/intl/en/apis/maps/documentation/staticmaps/
[accessed on August 20 2011].

Developing Location Based Services: Introducing the Location API for J2ME. 2009. MobiForge [online].
Available on Internet: http://mobiforge.com/developing/story/developing-location-based-services-introducing-location-api-j2me
[accessed on August 20 2011].

Mini App With Location API and Google Maps in Java ME. 2009. Nokia [online].
Available on Internet: http://www.developer.nokia.com/Community/Wiki/Mini_App_With_Location_API_and_Google_Maps_in_Java_ME
[accessed on September 02 2011].

Google Maps API Family. FAQ. Google [online].
Available on Internet: http://code.google.com/intl/en/apis/maps/faq.html#mapsformobile
[accessed on September 02 2011].

Monday, March 14, 2011

Canvas ScreenShot in JavaMe

Due to the previous posts about image encoding and image's bytes, I found an interesting question about how to get a screenshot of a canvas in JavaMe and it turns out to be very simple. Just remember, once you get the mutable (changeable) Image you should encode it in some format (i.e. PNG, JPEG, etc...).

The following is a regular canvas class which paints a smily:

  
//imports...
public class MyCanvas extends Canvas {
    
    /**
     * Creates a mutable image representing a screenshot of the
     * canvas
     * @return Screenshot as a mutable image
     */
    public Image getScreenShot() {
      Image screenshot = Image.createImage(getWidth(), 
                         getHeight());
      Graphics g = screenshot.getGraphics();
      paint(g);
      return screenshot;
    }

    /**
     * Painting method
     * @param g Graphic object to which the painting is done
     */
    public void paint(Graphics g) {
      //change to black an paint the whole background
      g.setColor(0x000000);
      g.fillRect(0, 0, getWidth(), getHeight());

      //change to yellow
      g.setColor(0xFFFF00);
      //left|top position of the face so it seems centered
      int xCenter = (getWidth() - 80) / 2;
      int yCenter = (getHeight() - 80) / 2;
      //draw the face
      g.fillArc(xCenter, yCenter, 80, 80, 0, 360);
      //change to black color
      g.setColor(0x000000);
      //left eye
      g.fillArc(xCenter + 20, yCenter + 20, 10, 15, 0, 360);
      //right eye
      g.fillArc(xCenter + 50, yCenter + 20, 10, 15, 0, 360);
      //smile
      g.fillArc(xCenter + 15, yCenter + 50, 50, 10, 180, 180);

    }
  }

Notice that the +getScreenShot():Image method is creating a mutable image of the same width and height of the canvas. It also gets the Graphic object from that image so that the paint method can draw the smily on it.

What to do with the screenshot? As I told you before, it's up to you. You can convert it to bytes, save it using RMS or FileConnection API, send it over the network...etc. But whatever you choose to do, remember to encode it using PNG or JPEG encoders, otherwise your end user may not be able to see or manipulate the image.

see ya soon!

References:

A minimal PNG encoder for J2ME. 2009. [online].
Available on Internet: http://www.chrfr.de/software/midp_png.html
[accessed on March 12 2011].

J2ME Screenshot of a Canvas. March 2010. Forum.Nokia [online].
Available on Internet: http://discussion.forum.nokia.com/forum/showthread.php?191207-J2ME-Screenshot-of-a-Canvas
[accessed on March 12 2011].

PNG Encoding in Java ME. March 2010. Forum.Nokia [online].
Available on Internet: http://wiki.forum.nokia.com/index.php/PNG_Encoding_in_Java_ME
[accessed on March 12 2011].

Tuesday, December 28, 2010

Base64 encode-decode in JavaMe

I want to start this post asking: why do you think you need to encode data? At first, I didn't have a specific answer, so I googled and found some interesting answers and now I can tell you: You want to encode, because you need to transfer binary data through a channel that is designed to deal with textual data. A common example is when you need to transfer an Image inside a JSON String or in a XML message.

We will use the Bouncy Castle library to Encode/Decode binary data in Base64 format. Although this library has a lot more and can be used for Encryption/Decryption using different methods, today we will focus on the Encoding/Decoding part. You can download the library using the following link:


Make sure you download the J2ME version. When you download this version, you'll get the full source code and when you build it, you get a 1.7MB library... which may be too much for a mobile application. Anyway, with the source code you can make a build of some classes and not of all of them. That's how I made a build with only the encoders packages and classes and is just about 14KB. If you need it, just ask for it you can download it using this link.

To work with Base64 in JavaMe (J2ME) the bouncy castle library comes with the org.bouncycastle.util.encoders.Base64 class. Next is how you can use it in your MIDlet:


import org.bouncycastle.util.encoders.Base64;

...
    /**
     * As an example, encodes a String and then it decodes it.
     * Prints to console the result of the encode/decode.
     */
    public void encodeDecodeExample() {
      
        String word = "New word to encode using Base64 also special "
                + "chars like Ñ and ó";
      
        System.out.println("Encoding: ");
        System.out.println(word);
      
        byte[] coded = Base64.encode(word.getBytes());
        String strCoded = new String(coded);
      
        //prints the encoded word
        System.out.println("Result: ");
        System.out.println(strCoded);

        System.out.println("Decoding: ");
        System.out.println(strCoded);
      
        byte[] decoded = Base64.decode(strCoded);
        String strDecoded = new String(decoded);

        //prints the decoded word
        System.out.println("Result: ");
        System.out.println(strDecoded);
    }
...

When the previous code is run, the console output shows the following:




Encoding: 
New word to encode using Base64 also special chars like Ñ and ó

Result: 
TmV3IHdvcmQgdG8gZW5jb2RlIHVzaW5nIEJhc2U2NCBhbHNvIHNwZWNpYWwgY2hhcnMgbGlrZSDRIGFuZCDz

Decoding: 
TmV3IHdvcmQgdG8gZW5jb2RlIHVzaW5nIEJhc2U2NCBhbHNvIHNwZWNpYWwgY2hhcnMgbGlrZSDRIGFuZCDz

Result: 
New word to encode using Base64 also special chars like Ñ and ó


You can see that first it prints the String varible called 'word' encoded, after that it decodes the encoded word and prints the decoded word. You only need to have the byte array of data and invoke the proper methods.

This library is pretty simple to use and it gives you the power of transmit binary data as text. As we mentioned before, if you need to send, for example, an Image as text (JSON String? XML?).

This is a small part of the bouncy castle library. It has many encryption/decryption method to be used in your mobile applications. In future posts we will explore some of these methods to add security to our mobile applications.

This concludes our introduction to Base64 in JavaMe (J2ME), wait for the next post where we will use it to send images from the server to the mobile client using, once again, JSON Strings.

see ya soon!


References:

Base64. 2010. Wikipedia [online].
Available on Internet: http://en.wikipedia.org/wiki/Base64
[accessed on December 28 2010].

The Legion of the Bouncy Castle. bouncycastle.org [online].
Available on Internet: http://www.bouncycastle.org/
[accessed on December 28 2010].

Friday, November 12, 2010

Java ME and JSON

In previous posts, we saw how JSON has been gaining ground as data transmission format. We also introduced GSON, Google’s API to create JSON text from an Object and Objects from JSON text in a fairly simple way, but that can’t be used in Java ME because of the Java Reflection API.

In this post we are going to stand on the mobile client side using JSON ME as application library to create JSON text. The library has disappeared from the JSON’s official web site (http://www.json.org), I'm not sure why, but the project is in the repository of java.net. The steps needed to obtain the source code from java.net SVN to NetBeans can be found in the following link:

If you don’t want to build the source code, contact me so I can send you the library. Once you have the JSON ME .jar file, you are able to implement JSON in your mobile application. Although you have to write more lines of code than when you are using GSON, it is still easy to use and the benefit in terms of ease of data transmission between mobile client and server is worth it!

As a example, we will develop a simple MIDlet that does not have UI, but only the necessary classes from Java ME to be able to generate JSON text from Objects and Objects from JSON text.

Next is the source code of the MIDlet:



import java.util.Vector;
import javax.microedition.midlet.*;
public class JSONMIDlet extends MIDlet {
    public void startApp() {
        Vector clients = new Vector();
        Client client = new Client();
        client.setName("Mr Developer");
        client.setLastName("level 1");
        client.setId("123456");

        //shows the client JSON String
        String jsonOne = Client.toJSON(client);
        System.out.println("***** FIRST OBJECT AS JSON ******");
        System.out.println(jsonOne);
        //add the client to the vector
        clients.addElement(client);

        client = new Client();
        client.setName("Mrs Developer");
        client.setLastName("level 2");
        client.setId("987654");

        //shows the client JSON String
        String jsonTwo = Client.toJSON(client);
        System.out.println("***** SECOND OBJECT AS JSON ******");
        System.out.println(jsonTwo);
        //add the client to the vector
        clients.addElement(client);

        //Now get the Clients Vector JSON String
        String jsons = Client.toJSONs(clients);
        System.out.println("***** ALL OBJECTS AS JSON ******");
        System.out.println(jsons);

        System.out.println("");

        //now map objectos from JSON Strings
        Client newClient = Client.fromJSON(jsonOne);
        System.out.print("***** NAME OF THE NEW FIRST CLIENT = ");
        System.out.println(newClient.getName());

        newClient = Client.fromJSON(jsonTwo);
        System.out.print("***** NAME OF THE NEW SECOND CLIENT = ");
        System.out.println(newClient.getName());

        Vector newClients = Client.fromJSONs(jsons);
        System.out.print("***** SIZE OF THE NEW CLIENT VECTOR = ");
        System.out.println(newClients.size());

        destroyApp(true);
    }

    public void pauseApp() {
    }

    public void destroyApp(boolean unconditional) {
        notifyDestroyed();
    }
}


As you can see, the MIDlet is creating Client Objects with defaults values. Surely in a real application, these data are coming from text fields in a UI. The MIDlet output to the console JSON Strings from these Objects and some attributes of Objects created from JSON strings.

Most of the work is done in the classes you wish to convert to JSON text. The following classes are the key to work with JSON ME:
  • org.json.me.JSONObject: Contains key / value pairs with which the JSON text is built. It also provides the method for obtaining the JSON text.
  • org.json.me.JSONArray: Ordered sequence of values that are separated by commas. These values can be JSONObjects. Practically, it can be understood as an array of JsonObject Objects.

Below is the Client class which implements the methods that convert to and from JSON and makes use of the previously named classes:



import java.util.Vector;
import org.json.me.JSONArray;
import org.json.me.JSONException;
import org.json.me.JSONObject;
public class Client {

    /** Name of the client*/
    private String name;

    /** Constant name of the attribute name*/
    private static final String ATT_NAME = "name";

    /** Last name of the client*/
    private String lastName;

    /** Constant name of the attribute last name*/
    private static final String ATT_LAST_NAME = "lastName";

    /** Identification of the client*/
    private String id;

    /** Constant name of the attribute id*/
    private static final String ATT_ID = "id";

    /**
     * Allows to get the JSON String from the Client passed as parameter
     * @param client Client object to convert to JSON
     * @return JSON String of the Client passed as parameter
     */
    public static String toJSON(Client client)
    {
        return toJSONObject(client).toString();
    }

    /**
     * This method should be used by this class only, that's why it is private.
     * Allows to get a JSONObject from the Client passed as parameter
     * @param client Client Object to convert to JSONObject
     * @return JSONObject representation of the Client passed as parameter
     */
    private static JSONObject toJSONObject(Client client) {
        JSONObject json = new JSONObject();
        try {
            json.put(ATT_NAME, client.getName());
            json.put(ATT_LAST_NAME, client.getLastName());
            json.put(ATT_ID, client.getId());
        } catch (JSONException ex) {
            ex.printStackTrace();
        }
        return json;
    }

    /**
     * Allows to get JSON String from a Vector of Clients
     * @param clients Vector of clients to convert to JSON
     * @return JSON String of the Vector of clients
     */
    public static String toJSONs(Vector clients) {
        JSONArray clientsArray = new JSONArray();
        for (int i = 0; i < clients.size(); i++) {
            Client client = (Client)clients.elementAt(i);

            JSONObject jsonObject = toJSONObject(client);
            clientsArray.put(jsonObject);
        }
        return clientsArray.toString();
    }

    /**
     * Allows to get a Client Object from a JSON String
     * @param jsonText JSON String to convert to a Client Object
     * @return Client Object created from the String passed as parameter
     */
    public static Client fromJSON(String jsonText) {
        Client client = new Client();
        try {
            JSONObject json = new JSONObject(jsonText);

            //check if the JSON text comes with the attribue Name
            if (json.has(ATT_NAME)) {
                //asign the String value of the attribute name to the client
                client.setName(json.getString(ATT_NAME));
            }

            //check if the JSON text comes with the attribue last name
            if (json.has(ATT_LAST_NAME)) {
                client.setLastName(json.getString(ATT_LAST_NAME));
            }

            //check if the JSON text comes with the attribue id
            if (json.has(ATT_ID)) {
                client.setId(json.getString(ATT_ID));
            }
        } catch (JSONException ex) {
            ex.printStackTrace();
        }
        return client;
    }

    /**
     * Allows to get a Vector of Clients from a JSON String
     * @param jsonArray String that contains Clients JSON Text
     * @return Vector of Clients from the String passed as parameter
     */
    public static Vector fromJSONs(String jsonArray) {
        Vector clients = new Vector();
        try {
            JSONArray jsonArr = new JSONArray(jsonArray);
            for (int i = 0; i < jsonArr.length(); i++) {
                //get a single client JSON Object
                JSONObject json = jsonArr.getJSONObject(i);

                //pass the JSON String to the method in order
                //to get the Client Object
                Client client = fromJSON(json.toString());

                clients.addElement(client);
            }
        } catch (JSONException ex) {
            ex.printStackTrace();
        }
        return clients;
    }

    //Getters and Setters...
}

The Client class contains methods that allow us to get a Client Object from JSON text and get the JSON text from a Client Object. As good practice, you can create constants with the attribute names so they can be used in the methods avoiding hard coding. So you can see the big difference with GSON, given that Java ME can’t use the Reflection API, it is necessary to assign values to attributes manually.

Here is the output text that is displayed by the console, once the MIDlet has been run:

***** FIRST OBJECT AS JSON ****** {"lastName":"level 1","name":"Mr Developer","id":"123456"}
***** SECOND OBJECT AS JSON ****** {"lastName":"level 2","name":"Mrs Developer","id":"987654"}
***** ALL OBJECTS AS JSON ****** [{"lastName":"level 1","name":"Mr Developer","id":"123456"},{"lastName":"level 2","name":"Mrs Developer","id":"987654"}] ***** NAME OF THE NEW FIRST CLIENT = Mr Developer ***** NAME OF THE NEW SECOND CLIENT = Mrs Developer ***** SIZE OF THE NEW CLIENT VECTOR = 2

If many classes of your application need to be converted to JSON text, you may create an Interface that defines methods for all classes wishing to implement JSON. A good example of this practice can be found on the following link:

OK that's it for this post, I hope I was clear enough. Any further explanation do not hesitate to contact me.

In the next post we will integrate the pairs Servlet / GSON vs JSON ME / Java ME, so we can communicate mobile clients with servers and vice versa.

See you soon!


References:

Using JavaScript Object Notation (JSON) in Java ME for Data Interchange. Agosto 2008. Oracle [online].
Available on Internet: http://java.sun.com/developer/technicalArticles/javame/json-me/
[accessed on October the 26th 2010].

meapplicationdevelopers: Subversion. 2007. Oracle [online].
Available on Internet: https://meapplicationdevelopers.dev.java.net/source/browse/meapplicationdevelopers/demobox/mobileajax/lib/json/
[accessed on October the 27th 2010].

Java ME (J2ME) JSON Implementation Tutorial/Sample. March 2010. Jimmy’s Blog [online].
Available on Internet: http://jimmod.com/blog/2010/03/java-me-j2me-json-implementation-tutorialsample/
[accessed on November 09 2010].