Thursday, December 1, 2011

Hauwei IDEOS adb driver


It was a little bit tricky to install the driver on windows, because I could not find any OEM driver from Hauwei. However, with it can be added as an Android Composite ADB interface easily.

To do that, first make sure you have download Google provided driver.


  1. Launch the SDK and AVD Manager by double-clicking SDK Manager.exe, at the root of your SDK directory.
  2. Expand the Third party Add-ons and Google Inc. add-ons.
  3. Check Google Usb Driver package and click Install selected.
  4. Proceed to install the package. When done, the driver files are downloaded into the <sdk>\extras\google\usb_driver\directory.
Once you have the driver, go to <sdk>\extras\google\usb_driver\ and add the following lines to android_winusb.inf. Make sure to create a backup of the inf file first.


;Huawei IDEOS
%SingleAdbInterface%        = USB_Install, USB\VID_12D1&PID_1038
%CompositeAdbInterface%     = USB_Install, USB\VID_12D1&PID_1038&MI_01

So basically it looked like following as I added the lines after Google nexus one 



;Google NexusOne
%SingleAdbInterface%        = USB_Install, USB\VID_18D1&PID_0D02
%CompositeAdbInterface%     = USB_Install, USB\VID_18D1&PID_0D02&MI_01
%SingleAdbInterface%        = USB_Install, USB\VID_18D1&PID_4E11
%CompositeAdbInterface%     = USB_Install, USB\VID_18D1&PID_4E12&MI_01
%CompositeAdbInterface%     = USB_Install, USB\VID_18D1&PID_4E22&MI_01
;Huawei IDEOS
%SingleAdbInterface%        = USB_Install, USB\VID_12D1&PID_1038
%CompositeAdbInterface%     = USB_Install, USB\VID_12D1&PID_1038&MI_01


[USB_Install]
Include = winusb.inf
Needs   = WINUSB.NT


[USB_Install.Services]
Include     = winusb.inf
AddService  = WinUSB,0x00000002,WinUSB_ServiceInstall



That's it! Now just give this driver location for the IDEOS...
In details for Windows 7:

To install the Android USB driver on Windows 7 for the first time:
  1. Connect your Android-powered device to your computer's USB port.
  2. Right-click on Computer from your desktop or Windows Explorer, and select Manage.
  3. Select Devices in the left pane.
  4. Locate and expand Other device in the right pane.
  5. Right-click the device name (such as Nexus S) and select Update Driver Software. This will launch the Hardware Update Wizard.
  6. Select Browse my computer for driver software and click Next.
  7. Click Browse and locate the USB driver folder. (The Google USB Driver is located in <sdk>\extras\google\usb_driver\.)
  8. Click Next to install the driver.

Thursday, November 10, 2011

RMI Registry port may be used error

I have got a new (a bit more powerful) workstation and was installing everything there. I started downloading all new versions of the tools that I have been using, like new Eclipse, JDK 1.7 etc.

Then when I ran Nokia S40 5th edition emulator, I go this error:

The internal RMI registry port 1099 may be in use by another application.




I tried to change the port, killed all other java apps, but no luck.

In the end, the problem turned out to be a jdk/jre bug. Apparently, the bug surfaced since 1.6 u 29. Here is the bug report. in sdk release note.

So switching to older JDK should fix the problem. I uninstalled jdk and installed JDK1.6 update 23 and it's working fine now!

Friday, November 4, 2011

Android code coverage

Unit tests are definitely a programmer's good friend (when done properly), watching the back and confirming that everything is working alright.

Code coverage is a friend of the unit tests, telling unit tests how well he has covered up his friend.

Anyways, I will give a quick and short instruction here about android unit testing.

Guess what? This is really simple if you have ever written any unit tests before for Java apps. It's all the same

  • First step, create a separate project for unit testing. When you create this project in Eclipse, eclipse will ask you to point to the existing project that you are going to test.
  • Write some unit tests. You will create test cases by extending AndroidTestCase class
  • Run the test, and see if the test method is actually being executed or not. Tests will be run in the emulator / device like a normal app, and will notify to eclipse. Use Eclipse > Show View > JUnit to see the result. There are notes about it in the same link I mentioned above.
  • Now getting the coverage report could not be any simpler:
    • create the ant script for building the test project. Open command prompt and go to your test project directory:
      • android update test-project -m <your_main_project_full_path> -p .
    • and run
      • ant coverage
Done!!!
Look for the coverage directory under test project and a nice report it waiting there.

Now if you are running in windows you may get this error
 "<something like File or SDK > was unexpected at this time.", 
then ant could not find some path. I hate windows "Programs Files" directory, cause that contains a space and space is an enemy for ant. So try Installing your sdk in a path that does not contain any space, and that should resolve it.



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!!!

Friday, September 30, 2011

Android Bitmap heap

If you have been developing an app for Android that uses a lot of Images (I wonder which app does not), then very likely you have faced
OutOfMemoryError: bitmap size exceeds VM budget.
Then you probably tried to see who is using memory using DDMS and got a big surprise that heap size usage is much smaller than you expected. It could be that you saw the app heap was less than 4MB when you got out of memory error.

The interesting fact is, Android decided to handle the bitmaps differently in memory. The bitmap pixel data were not stored in java application heap, but rather in native memory. That's why those big chunks of data were not shown in the heap. Although when android is calculating the max allowed memory, it is counting those native memory allocations (and you get OutOfMemoryError even when heap is not full).

Although the pixel data are stored differently, typically you don't need to free those memory manually. If no one is referencing to the bitmap, pixel data will be automatically cleared up with the bitmap in next garbage collection cycle. Advanced developers can use
Bitmap.recycle()
method to clear those. Recycle does not clear the native memory immediately, rather marks it for garbage collector, so that on next gc run it's cleared.

Good news is things have changed at Honeycomb. Honeycomb onwards bitmap payloads are stored in the heap, as you would normally expect. Ahh, it's so nice to debug stuffs and see exactly how the memory is being consumed by those bitmaps.


Thursday, September 29, 2011

Weak Reference

For performance reasons, you typically want to keep the cpu expensive stuffs loaded in cache, so that everytime that does not need to be computed. Caching the images is perhaps the most common example.

But you surely don't want to keep that heavy images loaded forever. At some point, when no body is using it, you want it removed. A non-strong reference, for example, Soft reference or Weak reference, comes very handy in caching. Unfortunately CLDC1.1 does not support soft reference, you can rely on weak reference only. CLDC 1.0 supports none (but probably none but grandpas use CLDC1.0 devices, and hopefully you are not writing an app for them).

Using a Weak reference cannot be any simpler.


WeakReference weakRef = new WeakRefernce(null);

public void putToCache(Image data) {

   weakRef = new WeakReference(data);

}



public Object getUsingCache() {

  Image data = (Image) weakRef.get();

  if (data == null) {

     data = createImage();

     putToCache(data);

  }

  return data;

}


By the way, For Android, there is a little (!) problem... check http://code-gotcha.blogspot.com/2011/09/softreference.html

Disable Dismiss command in Nokia alert

Did you ever had this problem that there is an unexpected 'dismiss' command in nokia alerts while writing a j2me app?

I found this very annoying. I had an app where I wanted to show an infinite progress alert, and I didnt want to have any cancel button there (it was a short save operation).

I tried adding a command with space, empty string to replace the default dismiss command, but did not work. Finally the solution that worked for me was:
  • Add a command with string "\u200b" (zero width space)
  • add an empty commandlistener
Code snippet:



/**
* Creates and returns an Alert with the message. 
* If noOptionForUser/code> is set as true, 
* Alert will have it's own CommandHandler to consume all
* user events, Alert will have an 'invisible' Command to remove DISMISS_COMMAND
* and timeout will be set as Alert.FOREVER. If noOptionForUser/code> is false,
* it will just add the gauge with indefinite progress alert.
* @param message message to be displayed
* @param noOptionForUser if true, user is not given any option to choose. 
* Alert will have it's own commandHandler to consume all events.
* @return an Alert object with an INDEFINITE mode gauge attached to it
*/
public static Alert getProgressAlert(String message, boolean noOptionForUser)
{
  Alert alert = new Alert(null,message, null, AlertType.INFO);
  Gauge gauge = new Gauge(null, false, Gauge.INDEFINITE,
                                           Gauge.CONTINUOUS_RUNNING);
  alert.setIndicator(gauge);
  if(noOptionForUser) {
     alert.setCommandListener(new CommandListener() {
           public void commandAction(Command cmd, Displayable disp) {
           }
     });
     alert.setTimeout(Alert.FOREVER);
     alert.addCommand(new Command("\u200B", Command.OK, 1));//we dont like to see the DISMISS command, so adding an invisible command
  }
  return alert;
}

Wednesday, September 28, 2011

SoftReference problem in Android


Looks like Android VM does not honor the soft reference properly.

To improve the UI performance, I had written a two level cache for our Android and J2ME app. One cache stores the downloaded data (mostly images) to disk, I call it persistent cache. Another cache keeps the Bitmaps in heap, intuitively called runtime image cache.

When an UI element needs an image, app first checks in the runtime cache, if not found, checks the persistent cache (and puts that to runtime cache when found). If it still does not find, it will download it from server. LRU item is automatically removed after caches are full. Cache becomes full when item count reaches some predefined limit.

I had written this first for j2me apps (and reused it in android project), and used hard references. That worked nicely.. until some large images started coming. Bitmaps were too huge and it pretty soon filled up the heap.

So I thought I would use SoftReference for Android and WeakReference for J2ME implementations (unfortunately CLDC does not support soft reference). When I quickly wrote few test codes, my cache started behaving very weirdly. UI elements almost never found the images from runtime cache... cache was totally pointless!!

Looks like dalvik has some bug. It removes the soft references even when there is plenty of memory. Well, this is not really a bug, because it is quite legal to remove the soft references whenever, there cannot be any guarantee, however, the expected general behavior is that soft references should not be cleared unless there is pressure from heap usage. Dalvik developers seem to be aware of this issue and it still exists in 2.3.4. http://code.google.com/p/android/issues/detail?id=20015

After digging a bit more, I found that when dalvik intends to collect 'some' soft references, in reality it removes all. So basically, either all soft references are collected or nothing is collected during mark and sweep.

Now I am implementing some logic to cache so that it can limit the items by heap usage also. But would be nice to use soft reference in runtime cache, and I would be relaxed knowing whenever heap is running low, images will be cleared from cache automatically.

is user a monkey

I was looking for some method to know about the free heap amount in Android, and I stumbled upon this in ActivityManager class:

boolean isUserAMonkey()
Returns "true" if the user interface is currently being messed with by a monkey.

ActivityManager#isUserAMonkey()

Haha.. and then immediately a recently reported bug of our project flashed... the bug said, someone tried to press refresh 20 times without giving a break!! Yapp.. isUserBeingAMonkey was surely true then :D

Oh.. there was also a report that some of our testers have rotated the screen over 600 times in the same view!! I wish I could call this isUserBeingAMonkey() at that time!!


Anyways, actually Monkey is a program that generates random touches, clicks, gestures etc for application stress testing.