2009-12-28

I really like Android's EditText

In the last couple of days I enjoyed doing a little bit coding for Android at home. With a J2ME background I was really amazed by the richness of the Android APIs. You have a lot of the Java Standard Edition APIs plus a lot of useful and well thought out APIs for UI and phone related stuff.

I quickly realized that a lot of functionality I thought I have to implement myself is already there. For example I really like the preferences API. On J2ME I had to implement everything myself. Starting from the preferences UI to the preference store.

Also surprising for me was how rich the widgets really are. Let's take the EditText widget. It not only looks really good when rendered on the screen it also has a lot of functionality you can easily use.

For my first application I have a form to enter geocoordinates. They are represented as text like "50:24,123".

After the basics worked I wanted to make the UI a little bit more user friendly by helping the user to enter only valid coordinates.

First I wanted to limit the usable characters to "0123456789:,.-". And it turned out to be quite simple:

NumberKeyListener keyListener = new NumberKeyListener() {

        public int getInputType() {
        return InputType.TYPE_CLASS_NUMBER;
        }

        @Override
        protected char[] getAcceptedChars() {
        return new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.', ':', '-', ',' };
        }
    };

    lonEditText.setKeyListener(keyListener);

But this still doesn't prevent someone from entering something like "1:1:1:1" which is obviously not valid. So I introduced an input filter:

    InputFilter[] filters = new InputFilter[1];

    filters[0] = new InputFilter() {

        public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
        if (end > start) {
            String destTxt = dest.toString();
            String resultingTxt = destTxt.substring(0, dstart) + source.subSequence(start, end) + destTxt.substring(dend);

            if (!resultingTxt.matches("[0123456789]*[\\:]?[0123456789]*[,.]?[0123456789]*")) {

            if (source instanceof Spanned) {
                SpannableString sp = new SpannableString("");
                return sp;
            } else {
                return "";
            }

            }
            
        }

        return null;
        }

    };

lonEditText.setFilters(filters);

(Please note that this is just an example and the code isn't production quality.)

That was easy and a lot better. Unfortunately you can still enter invalid coordinates like "999:99.123".

First I thought of getting all the magic into the regexp but first I don't like regexp-magic so much and second I wanted to see how I can give the user some feedback about the validity of the entered data.

I decided to implement a TextWatcher and validate the data in "afterTextChanged".

There I just tried to parse the coordinate and in case of an error I wanted to inform the user. My first approach was to use a Toast but it turned out that EditText already has everything I needed.

The code looked like this:

    if(coordinateValid){
        lonEditText.setError(null);
    } else {
        lonEditText.setError("Coordinate is invalid.");
    }

This is not the actual source but it shows what I wanted to show: Use setError to indicate a problem with the text contained in that EditText.

When the invalid field has focus the error is displayed. If it's not focused there is an icon showing that something is wrong with the content of this field.

That was easy and it's more than I had expected. Thanks Android!

2009-12-24

Fragmentation is inevitable

Many J2ME developers are complaining about device fragmentation. And I agree that it's one of the hardest challenges when developing portable MIDlets.

Recently similar things are said about Android. (see http://androidandme.com/2009/11/news/what-does-android-fragmentation-look-like/ )

And even on the iPhone there are similar problems. And I think that those problems are inevitable when you don't want to stick to old and outdated technology.

But why does fragmentation occur? What are the reasons for it?

  • Different software / hardware vendors. Even if the specs are very similar the details of an implementation can make the difference. This affects J2ME a lot. Luckily Android devices are more similar in terms of OS implementation but the hardware varies. The iPhone is the clear winner here. There's only one vendor. (Well this is in my opintion one of the few things that are good about having one vendor only.)
  • Software evolution.  (i.e. new versions) Software normally gets better and better with each revision and usually users want to use the latest features. But not all users can or want to update their devices. So you have to deal with multiple versions.
  • Hardware evolution. New devices have higher screen resolutions, more memory, more sensors etc.  If you want to make use of those new capabilities and don't want to break compatability with less powerful devices you have to write smart applications.

In the end device fragmentation is the consequence of device evolution. And we have to live with it because it won't go away.

Even controlled platforms like the iPhone are affected by this. Not as much as others but even iPhone developers have to deal with it. The next big change to that platform might be the introduction of new HD models with higher screen resolutions. We will see how those developers can deal with it. On other platforms people are already used to different screen sizes but I guess only few iPhone developers today think about screen size.

2009-11-19

My guess on the fate of Symbian

According to the blog "The Really Mobile Project" Nokia is going to replace Symbian with Maemo on the high-end smartphones.

While Maemo looks quite cool I think this isn't the end of Symbian. Instead it might become the end for S40 since my guess is that Nokia will start to use Symbian for mid-range and - in the long term - for low-end phones. (Although I don't expect it to power ultra-low-cost phones like the 2330 anytime soon.)  Both market segments are not suitable for a heavy-weight like Maemo.

This makes a lot of sense since Nokia invested a lot of money into the platform and Symbian might be much more future-prove than the proprietary S40 platform.

Beside that Symbian (S60) is still one of the best platforms to run J2ME on.

Maemo: It will have to compete with Android and iPhone. I don't know if it will really gain momentum.

But only time will tell.

2009-11-16

Hello, Android

Although Android was very appealing to me from the start I hesitated to play with it. Until now.

First I installed the SDK and was amazed by the plethora of possibilities. Compared to the quite limited J2ME world Android felt like pure freedom. I was so amazed that I bought myself a G1 from Ebay immediately.

I still have to explore a lot of the possibilities Android offers but I have seen enough to say I really like it.

I still like J2ME because it's still challenging to create useful software in such a constrained environment but it's amazing how much one can do on Android with quite a few lines of code.

The only problem with Android is the amount of apps which are already available on the Android Market. I found a solution for everything I needed up to now. While that is nice for the users it's problematic for developers. Creating something new is really hard. But you can always try to create a better app than the others.

2009-11-03

Coverage Analysis on J2ME

Since I do TDD also on J2ME I also want to analyze the code coverage. We all know that green doesn't mean good but red definitely means bad. So I think coverage analysis is a good thing.

While for JSE/JEE there are a lot of options things are different on J2ME.

I only know of two free projects.

The first one is JInjector by Google. (http://code.google.com/p/jinjector/)

You can do much more than coverage analysis with it. (In fact I think that coverage analysis in JInjector is just a by-product.)

BUT it's not easy to configure and to use. So I had a look at Cobertura for J2ME ( http://www.cobertura4j2me.org/ ).

It's pretty easy to use and integrates nicely with ANT. So I use it. There's only one big drawback: It's terribly slow!

On one of my MIDlets running the tests with Cobertura4J2ME took 7 minutes while running the tests without took only 38 seconds.

Unfortunately there doesn't seem to be any activity on this project so I will either have to live with it or fix it myself. (I really like to do that but currently I just don't have the time for it).

2009-10-26

The house building metaphor

I really like metaphors. They make it easier to understand and explain complex and abstract things easily. One of the most used metaphors in software development is the house building metaphor.

But unfortunately it isn't a good fit for modern software development,

First of all a house is built from the basement to the roof. One floor after another.

In software development we have layers but usually we don't complete a whole layer before starting to work on the next one.

Also if we do test driven development for example we are constantly refactoring (which is the equivalent of reconstruction of the house). If I would see workers constantly building, moving and removing walls I would be very irritated but it's basically what we are doing with constant refactoring.

Another difference is that you can't start to build the house without an exact plan. You shouldn't differ from the plan by more than a few millimeters but in software development it's often counterproductive to have a big plan. (But you should have a plan anyway but "Big design upfront" is really an anti-pattern)

Additionally the customer usually doesn't change it's mind while it's house is being built. But it's not an exception that the software developer's customer comes up with new and changed requirements during the development phase.

But unfortunately I don't have an idea for a better software building metaphor.

2009-10-22

Premature optimization is the root of all evil - also on J2ME

There are a lot of valuable resources on the internet with a lot of tips and tricks to reduce the size and improve the performance of MIDlets.

One comprehensive resource can be found here: http://sergioestevao.com/midp/?p=21

If you really have to optimize the above link and a lot more you can find on the internet can help you.

But you should really think twice before applying one of these tricks.

In general you should reserve a realistic amount of time at the end of the project to optimize for size and performance and make the application fly on all the desired handsets. This step might take a considerable amount of time. The best strategy to deal with that is to have a clean code base to start with. Development is a lot faster when working on clean code.

Before entering the optimization phase you should NOT sacrifice clean code for size and speed. In the long term writing clean code and using clever algorithms will make a big difference. A good software design and methodologies like test driven development is the most important thing for being successful. Otherwise you will end up with unmaintainable and messy code.

Remember that optimizing clean code is a lot easier than cleaning weirdly optimized code.

Additional I believe in the following guidelines
  • Don't optimize if you don't need to. Stop optimizing as soon as possible. Enough is enough.
  • Don't do what a bytecode optimizer / obfuscator can do for you. (e.g. method inlining makes getter and setters cost you nothing)
  • Optimize step by step. Measure the effect of each optimization. If it doesn't pay off - roll it back. The internet if full of performance optimization myths (not only regarding J2ME) so don't believe what you can't measure yourself.
  • Create a new branch for the optimization. Keep the clean code for later addition of features. Keep the clean version up to date. (i.e. don't fix bugs only in the optimized version)
  • Focus on the hot-spots of code where small changes have a big impact. There is no need to pollute the whole code when 20 percent would do the trick.

Remember that all of these suggestions are just suggestions. If you are writing a J2ME action game for low-end phones you might have to do more optimization than when you are writing a web-service client for high-end phones. As a rule of thumb optimize as late as possible.

2009-10-20

ProGuard 4.4 has some problems (with MIDlets)

Recently I found out that obfuscating one of my MIDlets with ProGuard 4.4 resulted in a broken application. The application did start and most of it worked but some of the features were broken.

The good thing is: After going back to 4.2 everything was fine again.

Unfortunately I hadn't had the time to investigate more on this but if you run into similar problems when using a more recent version of ProGuard you are warned by now.