JAJAH Development Blog

Blogs by JAJAH Developers

Archive for the ‘J2ME’ Category

TwitterMobile Review

Sunday, August 9th, 2009

Following my previous review about Twibble mobile application, I was asked to try out TwitterMobile. The application is produced by Tricast Solutions from UK and is written in J2ME so it should work on many mobile phones in the market. However, currently it works only on Sony-Ericsson and Nokia S60 240*320 devices. Lucky for me, I have a Nokia 6210 Navigator phone which have the right screen size, so I could try the application.

Screenshot0019Unlike Twibble, installation process is easy and user friendly. The user selects his phone type, enter his email and phone number and press the download button. Next, the user receives a special SMS message with a link to download the client. Pressing the link open-up the a mobile download page with a link to download the actual client. BTW, the mobile page seems to recognize the mobile model, but it turns out that’s due to the link. Meaning, the mobile site does NOT recognize the device’s user agent. This might cause problems for users who didn’t put the right model at the beginning of the process. It also means that Tricast could have saved 2-3 clicks till the actual download, but, it’s not a biggy.

Download completed, it’s time to test the application. If I had to describe the application user-experience in one word, it will  Screenshot0022have to be – Wow! The GUI is beautiful, just like Tricast say in their site. Using TWUIK reach media engine, the application flows elegantly between tweets and application options. The menu is not your conventional left-button-opens-a-doll-menu, but rather, a cool, mac-like graphic choices. Great job there Tricast!

However, this is where the complements stop and the complains begin; and there’re quite a few of them. First of all, the user is not given a choice to save his password locally. More secured? maybe, but it’s annoying to type my 10-characters password. Next, the phone’s security manager prompt the user many times for web access approval. This is because the application is not signed-in with a certificate. Oh well, I could live with that (still, the GUI make up for it).

We’re not done though. Unlike Twibble, Twitter Mobile doesn’t have the option to open a link inside a tweet. But wait, there’s more! if you want to tweet, you can but there’s no option to attach a picture! How lame is that?! I mean, the main point (at least for me) for having a mobile twitter application, is to tweet about an interesting event and add a picture to it. That in itself was enough to persuade me to stick with Twibble, but it’s not over here.  Want to check your @replies or your @direct-messages? Sorry. You have to pay 1.99£ for that. Yes, you heard me. A fee for a free service. No way,  José.

The bottom line is that the application gets an A+ on the cool factor but fails in usability. Perhaps Tricast is using the client to demonstrate its TWUIK technology, I don’t know. I do know that if they hope to make serious money from the application itself, they will have to enable picture attachment, URL linking and most importantly, free basic services in twitter.

J2ME UI: Text wrapping on Canvas

Tuesday, February 26th, 2008

The drawString() method that is used to write text on the canvas dose not know how to wrap the text, hence,  when using it and writing a long text, only one line will appear and the text will be cut.

In order to have the text written correctly, there is a need to implement a text wrap.

The below function writes the given ‘txt’ on the canvas’s Graphics ‘g’, starting from ‘x’ and ‘y’ coordinates, using the given ‘font’. the area in which the text should be written is ‘width’ and the text is written by the ‘alignment’ . using the alignment you can write text from left to right or from right to left

The function returns the next y coordinate on the canvas, which is the next location for a text to be written. this is good for cases that you want to continue writing on the canvas but with a different font or color.

public int write(Graphics g, String txt, int x, int y,
                         int width, Font font,
                         int alignment ){
    m_font = font;
    m_txt = txt;
    m_length = txt.length();
    m_width = width;
    //reseting
    m_position =0;
    m_start = 0;

    int fontHight = m_font.getHeight() + 1;
    String s;
    g.setFont(m_font);
    while(hasMoreLines()){
    s = nextLine().trim();
    g.drawString(s, x, y, Graphics.TOP|alignment );
    y += fontHight;
    }
    return y;
}
below is the implementation  for the  "helper" functions
private boolean hasMoreLines(){
    return (m_position<(m_length-1));
}
private String nextLine(){
     int maxLength = m_txt.length();
     int next = next();
     if(m_start>=maxLength || next>maxLength)
          return null;
     String s =m_txt.substring(m_start, next);
     m_start = next;
     if((m_txt.length()-1>m_start )&& ((m_txt.charAt(m_start)==‘\n’) ||
        (m_txt.charAt(m_start)==‘ ‘))){
          m_position++;
          m_start++;
     }
     return s;
}

.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

private int next(){
     int i=getNextWord(m_position);
     int lastBreak = -1;
     String line;
     line= m_txt.substring(m_position, i);
     int lineWidth = m_font.stringWidth(line);
     while (i<m_length && lineWidth<= m_width){
         if(m_txt.charAt(i)==‘ ‘ )
            lastBreak = i;
         else if(m_txt.charAt(i)== ‘\n’){
            lastBreak =i;
            break;
         }
         if(++i<m_length){
            i= getNextWord(i);
            line = m_txt.substring(m_position, i);
            lineWidth = m_font.stringWidth(line);
         }
     }
     if(i==m_length && lineWidth<= m_width)
        m_position = i;
     else if(lastBreak == m_position)
        m_position++;
     else if(lastBreak < m_position)
        m_position =i;
     else
        m_position = lastBreak;
     return m_position;
  }
private int getNextWord(int startIndex){
    int space = m_txt.indexOf(‘ ‘, startIndex);
    int newLine = m_txt.indexOf(‘\n’, startIndex);
    if(space ==-1)
       space = m_length;
    if(newLine ==-1)
       newLine = m_length;
    if(space<newLine)
       return space;
    else
      return newLine;
}

.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

J2ME UI: Implementing a Progress Bar

Thursday, January 3rd, 2008

first we create the Progress Bar object, the is is the simple part )

public class Gauge {
    
    private int m_x, m_y, m_hight, m_width, m_Progress;
    
    public void set(int x, int y, int height, int width ) {
        m_x = x;
        m_y = y;
        m_height = height;
        m_width = width;
    }
    
    public void  setProgress(int progress){
     m_progress= progress;
    }
    
    public void paint(Graphics g){
        if(m_progress>=m_width)
            return;
        g.setColor(0);
        g.drawRect(m_x, m_y-1, m_width, m_height+1);
        
        g.setColor(GuiConstants.JAJAH_COLOR);
        g.fillRect(m_x+1, m_y, m_Progress, m_height);
        g.setColor(GuiConstants.LIST_BACK_COLOR);
        if(m_width-m_Progress>0)
            g.fillRect(m_Progress + m_x, m_y, m_width-m_Progress, m_height);
    }

now we need to use it:

in order to display the Progress Bar, we will display it using a canvas. the canvas will hold a Progress Bar as a member, and it will display it. on that canvas more info can be displayed. note that on each progress update  a repaint occurs. its sufficient to only repaint the progress bar or any updated UI.

public void run() {
        try{
            init();// init params
            m_paintSuper = true;
            repaint();
            boolean run = !connection.callAllowed();// condition for running the bar
            while(run){
                for(int i= 1;i<m_gauge.getWidth()&& run;i++){
                    m_gauge.setProgress(i);
                    Thread.sleep(GAUGE_SPEED); // to make gauge slower
                    repaint();
                    run = !connection.callAllowed();
                }
            }
        }
        catch (Exception e) {
            run();
        }
    }
    
    protected void paint(Graphics g) {
          // things that need to painted only once
          if(m_paintSuper){ 
            super.paint(g);
          }
           m_paintSuper = false;
        }
            
        m_gauge.paint(g);
    }
    

now that we have the canvas ready with the Progress bar and the update of the progress we are left to display the canvas

if(m_gauge == null)
     m_gauge = new GaugeView(null);
// sets the text for the canvas or any other thing to the canvas
m_Gauge.setText(str);         
Display.getDisplay(m_midlet).setCurrent(m_gauge);
Thread t = new Thread(m_gauge);
t.start();

J2ME Porting: UI Issues

Tuesday, January 1st, 2008

Screen Size

when using canvas, make sure that the sizes and location(x, y coordinates) of what you paint are relative to the screen height and width.  for better  performance, cache the height and width instead of using the canvas’s getWidth() and getHeight() functions. (note that even if you have a few canvases, the height and width returned for all canvases are the same, unless if some are fullScreen and some are not). recall that floating numbers are not supported, hence when calculating sizes, divide and multiply by even numbers. bitwise operations are recommended.

the below code illustrates how the title bar and the command bar  are relative to the screen size.  when we will install the application on devices with various screen sizes, the bars will look good and will change according to the screen size.

    requesting_jajah_call_cost
    public void init(){
        m_height = getHeight();
        m_width = getWidth();
        m_titleFontH  = m_titleFont.getHeight();
        m_titleHeight = m_height>>3;
        if(m_titleFontH>m_titleHeight)
            m_titleHeight = m_titleFontH;
    }
    protected void paint(Graphics g) {
        g.setColor(GuiConstants.JAJAH_COLOR);
        g.fillRect(0,0,m_width,m_titleHeight );
        g.fillRect(0, m_height-m_titleHeight,m_width, m_titleHeight);
        
        //drawing color
        g.setColor(GuiConstants.COMMAND_COLOR);
        
        g.setFont(m_titleFont);
        g.drawString(m_Title,m_width>>1,(m_titleHeight-m_titleFontH)>>1,Graphics.TOP|Graphics.HCENTER);
                
    }

 

Handset’s look and feel

different devices are made by different manufactures. each manufactures has its own look and feel. even within the same manufacturer there are differences between models. for example in Nokia devices, the "back" command will usually be the right key, the options/ok will be the left, whereas in some Motorola devices it will be the opposite.  Sony Ericsson devices  have a special key for the "back" command. Today most handsets, in addition of having 2 keys,  have a third key or a "joy stick".

when thinking about the application’s UI you need to decide if the commands ("options", "back", "ok" "call" command in JAJAH Plugin) will be the same for all device models or it will be adjusted to the specific model. I think that the application should be adjusted to the model. I think its important to let the user keep on using his device as he is regular and not forcing him to "learn" a new way. your application should know how to support the special keys that some devices have. there are some articles that recommend using the key Name (i.e. FIRE, RIGHT, LEFT etc.) and not the key code. I found that you can be surprised what you think you will get and what you actually receive. I recommend using the Key code and checking its value for each model. (usually, for models of the same manufacturer, the key codes are the same. in LG, its not..)

more about this issue to come…

Download JAJAH Mobile Plugin to see application example

Jajah is the VoIP player that brought you web-activated telephony.