Wednesday, October 26, 2011

Verify jad signature

Because midlet signing works a little bit differently, you need to use jadtool to verify the signature:

java -jar %wtk_home%/bin/jadtool.jar -showcert -certnum 1 -inputjad myJadFile.jad

Output of this will be something like:


Subject: C=US, ST=CA, L=Santa Clara, O=dummy CA, OU=JCT, CN=thehost
Issuer : C=US, ST=CA, L=Santa Clara, O=dummy CA, OU=JCT, CN=thehost
Serial number: 3d3ece8a
Valid from Wed Jul 24 08:58:02 PDT 2002 to Sat Jul 21 08:58:02 PDT 2012
Certificate fingerprints:
MD5: 87:7f:5e:64:c8:dd:b4:bf:35:39:76:87:99:9b:68:82
SHA: 9d:c0:88:ce:08:83:cd:e6:fe:13:8b:26:f6:b4:df:e2:da:3c:25:98
To show all certificate details:
java -jar %wtk_home%/bin/jadtool.jar -showcert  -all -inputjad <input_jadfile>

Tuesday, October 18, 2011

LWUIT scrolling problem

LWUIT scrolling works most of the times, however, I had problems with scrolling in a view like this:

I had some non-focusable multiline text area at the bottom of the screen and pressing down when focus is on cancel button did not scroll it.

There may be a better fix, but my quick (and dirty) fix was that, I added a focusable invisible item at the bottom !


    this.setLayout(new BoxLayout(BoxLayout.Y_AXIS));

    Component invisibleItem = createInvisibleItem();

    this.addComponent(input1);
    this.addComponent(input2);
    this.addComponent(buttonOk);
    this.addComponent(buttonCancel);
    this.addComponent(textAreaLong);
this.addComponent(invisibleItem); buttonCancel.setNextFocusDown(invisibleItem); } private void createInvisibleItem() { Component component = new Container(); component.setNextFocusDown(component); //to protect any jump }

LWUIT List border

I was again having some interesting problem with LWUIT border. I had different kind of border for the normal list item and focused list item in the UI design. So obviously I had two UIID ListRenderer and ListRendererFocus defined in the theme.

But somehow the focused border was not getting painted !!

I didnt have much time to dig into details, but manually changing the border in ListCellRenderer fixed this.



public class MyListRenderer extends Label implements ListCellRenderer {
    //...

   /** To draw the background of the focused item. */
   private Label focus = new Label("");
   
   /** Border set by lwuit theme. */
   private Border originalBorder;

   public ListChannelRenderer() {
       //..other stuffs...
       originalBorder = getStyle().getBorder();
   }

   /**{@inheritDoc} */
   public Component getListCellRendererComponent
            (List list, Object value, int index, boolean isSelected) {
       //...change label content based on list index

       //When selected, we want to draw the focused border only, 
       // that's why setting to null
       //Lwuit draws only the original background even for focused
      if (list.getSelectedIndex() == index && list.hasFocus()) {
           this.getStyle().setBorder(null);
      } else {
           this.getStyle().setBorder(originalBorder);
      }
      return this;
   }

   /**{@inheritDoc} */
   public Component getListFocusComponent(List list) {
      return focus;
   }
}

Monday, October 17, 2011

LWUIT background with border

I wanted to separate the list items by a simple horizontal line. So I had created a custom border, which simply draws a line at the bottom of the component. This list itself did not have any background color, i wanted to show the Form behind it, so I had set the background transparency to 0 for the list.

Recently we had a change in the UI design and i needed to add a gradient. And surpise!! Background is not getting drawn. I changed the transparency, of course, changed the color using res editor, then for testing changed in the code.. no luck!

Then I started checking how a component paints its background...

       
   protected void paintBackground(Graphics g) {
        if (isBorderPainted()) { 
        // isBorderPainted()  =   getStyle().getBorder() != null;

            Border b = getBorder();
            if (b != null && b.isBackgroundPainter()) {
                b.paintBorderBackground(g, this);
                return;
            }
        }
        if (getStyle().getBgPainter() != null) {
            getStyle().getBgPainter().paint(g, bounds);
        }
    }

Ok!! As you can see, if there is a border, border is responsible to paint the background (so that it can take care of rounded corners etc nicely?). And obviously i didnt notice that when I was implementing that simple line border.

I quickly fixed my problem by changing the ListMod class (overridden from LWUIT list)

  

class ListMod extends List {

/**
 * Normally when there is border, background painting is done by border.
 * This flag is used to override that default behavorio. False means background is painted by Style, rather than by Border.
 */
private boolean paintBackgroundByBorder = false;
 
protected void paintBackground(Graphics g) {
 if (paintBackgroundByBorder) {
    super.paintBackground(g);
 } else {
    if (getStyle().getBgPainter() != null) {
            getStyle().getBgPainter().paint(g, getBounds());
    }
}

}

Friday, October 14, 2011

Instanceof and equals

Today I stumbled upon a code that someone committed to the project.
    if ( this.getClass().equals(A.class) )
Although it was a working piece of code and so far I believe no bug was caused by it, however, I think it's a little dangerous code. It depends on the context and what this method is intended to do, but most likely the programmer just wants to know whether this object is from class A. Very unlikely that someone will create a method to check 'this' is an object of exactly class A (something is wrong in the design then?). So preferably, instanceof should be used instead of using equals, unless you know exactly what you are doing.
    if ( (this instanceof A) )

This getClass violates  Principle of least astonishment . It means in ambiguous cases, it should be designed so that user is least surprised. 




About this principle, wikipedia has a good example. Let's say you are typing a password on some web and then suddenly your friend sends a chat message and the instant messenger took the focus. Ops! You pressed enter to find that your password is just sent to your friend. Although for instant messaging it may be a nice feature to take the focus so that you can respond quickly, however to avoid these kinda surprises, this need to be avoided.

A good discussion about this topic:
http://www.artima.com/intv/bloch17.html

Sunday, October 2, 2011

Skype Android installation problem

I had an old version of skype in my Dell Streak 5. When skype first launched the video call support for android, I was kinda excited and tried to install that immediately. But oops... installation failed saying
"insufficient storage available". 

What?? I thought I had too many pics / videos... but no.. plenty of space was available. I still tried to free up some more from device memory.

No luck! Then I googled it up and it appeared, I was not alone. Lots of ppl were having the same problem. Apparently the problem happens when someone tries to upgrade to skype newer version. And to fix that, some 'com.skype.raider' folder need to be removed from /data/data/ folder, which requires super user permission and you have to root your device.

 So far I never found a strong need to root my device. But now I got one :). But rooting experience was not so smooth. Just listing my attempts in case some one else is also trying to root dell streak

  • z4root temporary root did not work. (Yes, according to some forums, I took the battery off, rebooted and gave enough time)
  • z4root permanent root did not work.
  • Universal Androot did not work.
  • Finally GingerBreak worked just fine! (Thanks GingerBreak).
I had the unlocked Dell Streak 2.2.2.

And the instruction to remove that com.skype.raider from /data/data folder actually resolved the problem. Skype finally got installed.

I was almost going to lean back on the couch and make some happy video calls, but skype ruined it again. It did not support front facing camera, not in android 2.2. Arrrrrgs!!!