Thursday, December 17, 2009

Single Jar theory

This month there was a Sun Tech Days event at São Paulo, Brazil.
I could not be there, but I am thankful they shared the slides.

The only presentation about Java ME was JavaME: Building Cool Interfaces with the Lightweight UI Toolkit (PDF document). I think there are also other cool things on Java ME, but the event is a lot smaller than Java ONE and there was more interesting stuff on Java Standard and Enterprise. A Java ME event? Lets hope there will be a new Java Mobile, Media & Embedded Developer Days - Latin America.

Back to the presentation. At slide 26 there is this interesting suggestion about Easy deployment with One JAR.
I think this is the right way of thinking, but the presentation is about LWUIT being the answer.

I advocate the Adaptive User Interface for some time now and agree it is hard to achieve with only LCDUI and Canvas.
But I do not like the LWUIT overhead. To me 50K is still too much (slide 78).

My applications are small ones (below 15k) and I will keep them this way.
They focus on one feature and try to do it right: with good user experience.

Will I ever use LWUIT? Maybe. I might need an specially difficult UI - very hard to implement from scratch - and end up using this toolkit.
But I will first try doing it with Canvas (slide 19). If I can not do it this way I will still have learned something from it.

Related Topics:

Tuesday, December 15, 2009

Blog audience

Since 26 April 2009 I am following this blog statistics with Google Analytics and it had 566 visiting users (855 pageviews).
There are days days when I do not have a single visit, but it usually goes from two to six a day.
The most interesting part of the statistics for me is the Map Overlay, where we can see from which part of the wordl the visits came from.
Below is the world map with all 54 countries that have visited this blog and the number of visits for each.

The top 10 countries are:


  • Brazil: 255

  • United States: 56

  • India: 32

  • Portugual: 22

  • Poland: 21

  • Germany: 18

  • Sweden: 10

  • United Kingdom: 9

  • Turkey: 8

  • Russia: 8


It is natural to me to see so many visits from Brazil as I am Brazilian and have metioned this blog where I lecture and also at Brazil JUGs.
If you have a blog or a site you should really use some analytics tool.
It is very satisfaying to see all these different visits on the world map.

Related topics:

Monday, December 14, 2009

Books 1.3

Last week I have posted all changes I made for Books version 1.3, they are listed below on Related Topics.
I also updated my blog entry on Books.
But the first place I notified the world about this version was on
this tweet update.

Related Topics:

Friday, December 11, 2009

Reading UTF-8 streams

If you have a byte array with Unicode characters encoded with UTF-8 you can create a String from it with the following constructors:

String(byte[] bytes, int off, int len, String enc) 
String(byte[] bytes, String enc)


This is useful when reading from local files. But what can you use if you are reading an UTF-8 stream?

You can use class java.io.InputStreamReader with the following constructor:

InputStreamReader(InputStream is, String enc)


After you have the InputStreamReader instance you can create a char array buffer and use the following method:

public int read(char[] cbuf, int off, int len)


For example:

InputStreamReader in = new InputStreamReader(
inputConnection.openInputStream(), "UTF-8");
char [] buff = new char[1024];
int len = in.read(buff, 0, buff.length);

while (len > 0) {
// use buff characters, like
// String s = new String(buff, 0, len)

len = in.read(buff, 0, buff.length);
}


But I have used only in.read(buff) and did not have a problem with it.

This also applies for Java Standard and Enterprise editions.

Thursday, December 10, 2009

Showing error messages

Exceptions are a powerful feature of Java.
Applications may recover from expected error situations and present meaningful messages to the user.

But when you catch an unexpected exception? What should you present to the user?

I propose to show a generic error message prefix requesting user feedback like:

"There was an unexpected situation, please send an email to a@b.c with the following details: "

The details are the Exception class name and, if available, the message.
Below is a method to handle exceptions this way, it should be placed in a class that extends MIDlet:


public void showExceptionAlert (Exception e) {
StringBuffer msg = new StringBuffer(getErrorMessage());
Display d = Display.getDisplay(this);

msg.append(e.getClass().getName());
if (e.getMessage() != null) {
msg.append("\n").append(e.getMessage());
}

d.setCurrent(
new Alert(getErrorTitle(), msg.toString(),
null /*alertImage*/, AlertType.ERROR),
d.getCurrent());
}


getErrorMessage() and will load the prefix getErrorTitle() the Alert title based on current locale (i18n).

Related topics:

Wednesday, December 9, 2009

Full Screen Repaint

If for any reason you have to override getWidth or getHeight methods in a class that extends Canvas, the calls to repaint() might not update the whole display.

And this is an expected behaviour. Check below documentation from API:

public final void repaint()

Requests a repaint for the entire Canvas. The effect is identical to

repaint(0, 0, getWidth(), getHeight());


If you want to always update the whole display when calling repaint() add the following method to your class:


public void repaint() {
super.repaint(0, 0, super.getWidth(), super.getHeight());
}

Tuesday, December 8, 2009

Color Distance

We can represent a color in Java ME using integer literals. The four bytes represent different aspects of the color:

  • Transparency: also known as Alpha channel. Indicates if the color should we drawn as solid or translucid

  • Red: the red component

  • Green: the green component

  • Blue: the blue component



In a previous post I pointed how to get the handset theme color dinamically with Display.getColor.
But I came to a situation where I could not use COLOR_HIGHLIGHTED_BACKGROUND with COLOR_HIGHLIGHTED_FOREGROUND.
The colors were too "close". Like dark gray over black.

My work around was to add a color distance verification. Lets imagine that the three color components are the axis of a 3D system.
To calculate the distance between two colors (two points) I just need to apply the below method:


public static int colorDistance (int c1, int c2) {
int r1 = (c1 & 0xff0000) >> 16;
int g1 = (c1 & 0x00ff00) >> 8;
int b1 = c1 & 0x0000ff;
int r2 = (c2 & 0xff0000) >> 16;
int g2 = (c2 & 0x00ff00) >> 8;
int b2 = c2 & 0x0000ff;

// http://en.wikipedia.org/wiki/Euclidean_metric
return sqrtRound(((r2 - r1) * (r2 - r1)) +
((g2 - g1) * (g2 - g1)) +
((b2 - b1) * (b2 - b1)));
}


I chose that if color distance if below or equal to 40 I should use black color for foreground and white color for background.

Related topics:

Monday, December 7, 2009

Square Root Rounding

Since CLDC 1.1 Java ME applications can use floating point operations like sin, cos, tan, sqrt, etc. All these methods are available at java.lang.Math class.

Some applications needs square root floating point precision and will have to use double variables. Other applications need only an approximation and this is what I present here.

Lets first take a look at how I create my square pyramid. To start we draw two colums with the base number and its square:








BaseSquare
00
11
24
39
416


Now we place all other numbers between the squares.








BaseSquare and other numbers
0
      values <= 0   
1
          1  2         
2
       3  4  5  6      
3
    7  8  9 10 11 12   
4
13 14 15 16 17 18 19 20


The square root approximation of these numbers is the same as the square root of the center value. For example, sqrtRound(7) == 3, sqrtRound(6) == 2.

Below is the source code:

public static int sqrtRound (int value) {
if (value <= 0) {
return 0;
}

int i = 1;
int j = 2;

// search for range where value is between two square values
while ((i * i) <= value && value > (j * j)) {
i++;
j++;
}

int d = (j * j) - (i * i) + 1;

if ((value - (i * i)) < (d / 2)) { // round down
return i;
} else { // round up
return j;
}
}