Latest Tweets

 

An Intent to Pick Daisies

One of my favourite things about the Android platform is how easily application can share data using Intents and ContentProviders. They provide a universal basis for Android applications to interoperate and I try to expose them whenever it’s practical, even for something as singular as my Daisy Garden application.

I’ve just published a new version of Daisy Garden and with it, Intents and ContentProviders that enable the users of other Android applications to choose flowers they have grown in Daisy Garden — assuming that the developers choose to support it. And the great thing is that supporting third-party intents is very easy to do (and even if no other developers use them, they will be heavily used to integrate my own applications).


An example of what the user sees when picking a flower.

The Java code embedded below is a self-contained Activity that responds to a tap on the screen by inviting the user to pick a flower and then displaying the flower as a bitmap. There are two basic parts: forming an Intent for the user to pick a flower and forming a Uri to the flower’s bitmap. Both of these aspects can be customized; messaging to the user, and the bitmap size for example.

It’s very simple — more than half the code is boilerplate and comments. And this is what’s really good: in a well structured Android application this functionality is simple to expose too — I’d go as far as saying it’s almost automatic, so there is very little reason not to share (non-sensitive) data between applications.

Having said all this, there is an interesting technical detail here that meant that I had to give some thought to exposing the bitmaps. Daisy Garden is generating the flower bitmaps “on-the-fly” when they are requested from the ContentProvider and it’s not obvious how to share these unless you know a little about how Linux filesystems work. I’ll try to find some time to outline the technique in a subsequent post.

Java code follows:

Change notification

Change notification

Change dialog

Change dialog

Change dismissed

Change dismissed

The Android Market has its deficiencies. I don’t think anyone would deny that. One of the niggles is that there’s no place to list the changes between application versions.

I think this is very important in Android applications because the limited screen space often necessitates moving access to core application functions into the menu. Users who are already familiar with an application may never discover a new feature that has been added to a menu that they opened once and never since.

Instead of lamenting the Android Market’s inability to display my application changes to users, I decided that the information was important enough to move in-app; in the past I’ve simply logged changes on my website. The design I settled on was to introduce a small notification at the top of my main application activity - about the size of a mobile ad - that appears if there is change information to present to the user. The user can tap the notification to read details about the changes in the latest version.

Not all updates will need explanations, so the user may not receive a notification on every update, and users can cancel a notification without bothering to read it. Accidentally dismissing the notification isn’t much of a concern since on the next update the user can page backwards and see the descriptions of previous changes.

This functionality will be included in the next release of Daisy Garden. I think it works well and I hope users like it; the use of animations to show and hide the notification adds extra bit of polish. And I’ve implemented it as a library project, so I’ll be able to introduce it into my other Android projects.

I think every developer should consider adding something similar to their applications.

Sharing is hard to do (safely)

When I developed Daisy Garden for Android one of my goals was to build a simple environment in which people could share something, knowing that there was no possibility of being offended, or of giving offense. I certainly wanted an application where I never needed to be policeman to its users.

Imagining the phone in the hands of, say, a five-year-old child, it turns out that it is harder than one might expect to build something that permits safe and ready sharing; there are many constraints:

Now, collaborative filtering can certainly address these issues, but only after a number of individuals have flagged the offending content. Returning to my example of the five-year-old holding a mobile phone, that child’s parent might not feel that a “flag as inappropriate” link was adequate in this context.

Back to Daisy Garden. In addition to these constraints, sharing necessitates that there is something worth sharing. Further to this, if you want people to share across cultural boundaries, it has to be something universal, something that everyone can appreciate. This is what led me to the idea of flowers, and gardens.

And I’m not as authoritarian within Daisy Garden as the observations above might suggest - where individuals share outside of the application, I’m much more relaxed - for example, users can name their flowers when they share them with others. But now that I’m beginning to add features that will allow users to share their garden designs with all other users of the application, I’m very glad I considered these things before I released the early versions of Daisy Garden.

P.S.

I did want to post/tweet this under the title “How to keep your application genital free”, but didn’t want to offend anyone.

ADC Round 2 top 200 list (by category)

The ADC Round 2 top 200 list isn’t ordered by category so here they are, conveniently ordered so.

I got to rate a number of really good applications that made it on to this list. Sadly I also rated some promising looking ones that aren’t.

(Oh yeah, you will will find Daisy Garden on this list - thanks to everyone who participated in the rating).

Arcade Games

Casual Games

Education & Reference

Entertainment

Lifestyle

Miscellaneous

Multimedia

Productivity

Social

Travel


(previously named top 100 list through a spectacular failure of mental arithmetic)

I just finished uploading a new version of Daisy Garden which – I hope – support high and low density devices. Along with some minor other changes I couldn’t resist adding another garden design to the application.

The garden designs are actually produced on the phone with an application that allows me to build layered tile maps with masks and shadows. Android was an ideal platform for building this tool because:


It allows me to share any code I want to, between the editor and the application because they are running on the same platform.
It allows me to doodle new designs any place I have free time.
I get to see the design (mostly) as other phone users will see it as I design it.
I may get the opportunity to release it in the future, to allow anyone to make their own garden designs.

I just finished uploading a new version of Daisy Garden which – I hope – support high and low density devices. Along with some minor other changes I couldn’t resist adding another garden design to the application.

The garden designs are actually produced on the phone with an application that allows me to build layered tile maps with masks and shadows. Android was an ideal platform for building this tool because:

  1. It allows me to share any code I want to, between the editor and the application because they are running on the same platform.

  2. It allows me to doodle new designs any place I have free time.

  3. I get to see the design (mostly) as other phone users will see it as I design it.

  4. I may get the opportunity to release it in the future, to allow anyone to make their own garden designs.

I’ve been getting to grips with the new drawable density functionality that’s been exposed in Android 1.6 and it’s terrific - it simply saves so much effort when you want to target different screen sizes.

You can see how the layouts (originally designed around HVGA) are faithfully recovered compared with Android 1.5. For example in the first screenshot, the buttons return to the correct proportions, and in the second, the flower reclaims most of the screen estate.


when I say no code changes, all I did was change all pixel dimensions to dips and patch up the “Share” rendering (as described in my last post).

I’ve been getting to grips with the new drawable density functionality that’s been exposed in Android 1.6 and it’s terrific - it simply saves so much effort when you want to target different screen sizes.

You can see how the layouts (originally designed around HVGA) are faithfully recovered compared with Android 1.5. For example in the first screenshot, the buttons return to the correct proportions, and in the second, the flower reclaims most of the screen estate.

  • when I say no code changes, all I did was change all pixel dimensions to dips and patch up the “Share” rendering (as described in my last post).

Loading unscaled bitmaps compatibly in Android 1.5 and 1.6

I’ve just started retargeting my applications for the latest version of Android (1.6) which introduces full support for different screen densities. The responsibility for scaling bitmap resources to match the screen density falls to the BitmapFactory class.

This is a new behaviour applied to existing methods; I haven’t got enough experience with the new SDK to form an opinion, but it looks as though the new functionality will do exactly what you want it to in most situations; it should simply be a case of moving resources to an appropriate ‘density directory’ (see the resources i18n guide for details).

But there are some instances where you don’t want your images scaled to match the screen density. One case is with images that you will scale within your application, usually when drawing them to a canvas. This occurs in my Daisy Garden application – different garden designs are created from a set of masked tiles which I don’t want pre-scaled.

In 1.6 there is support for density independent bitmaps - these can be placed in a “drawable-nodpi” resources folder. Unfortunately it seems that this isn’t properly supported for 1.5 (it appears that bitmaps loaded from this folder always come out as 1px squares). Alternatively, there is also flag: BitmapFactory.Options.inScaled which you can set to false to disable the scaling, but this is new in 1.6 so isn’t available in applications that aim for compatibility with 1.5.

So I think there’s no option but to produce a utility class that switches code path depending on the API number. It’s not a big deal (it took me longer to write this post) but it might save someone else some time. It’s not documented, but simple to use, just call:

UnscaledBitmapLoader.loadFromResource()

import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.os.Build;

public abstract class UnscaledBitmapLoader {

    public static final UnscaledBitmapLoader instance;

    static {
        instance = Integer.parseInt(Build.VERSION.SDK) < 4 ? new Old() : new New();
    }

    public static Bitmap loadFromResource(Resources resources, int resId, BitmapFactory.Options options) {
        return instance.load(resources, resId, options);
    }

    private static class Old extends UnscaledBitmapLoader {

        @Override
        Bitmap load(Resources resources, int resId, Options options) {
            return BitmapFactory.decodeResource(resources, resId, options);
        }

    }

    private static class New extends UnscaledBitmapLoader {

        @Override
        Bitmap load(Resources resources, int resId, Options options) {
            if (options == null) options = new BitmapFactory.Options();
            options.inScaled = false;
            return BitmapFactory.decodeResource(resources, resId, options);
        }

    }

    abstract Bitmap load(Resources resources, int resId, BitmapFactory.Options options);

}

Garden @ QVGA

Garden @ QVGA

Flower @ QVGA

Flower @ QVGA

Sharing @ QVGA

Sharing @ QVGA

About @ QVGA

About @ QVGA

Now that android devices with different screen resolutions are becoming a reality, I just wanted to share these shots of Daisy Garden at QVGA.

Even though I’ve done no direct work to support QVGA in my applications, it always features in my thinking for the UI. One simple approach is to aim for two things in each activity layout:

  1. Ensure the largest component can be scaled or scrolled
  2. Keep a tight limit on the number of other components on screen.

You can see how this approach has worked quite well for Daisy Garden; this is the first time I’ve viewed the app at QVGA resolution, and though there’s definitely work to do, all the layouts look redeemable.

With a number of Android applications laying incomplete in my digital atelier, I felt a pang when Dan Morrill announced that the Android Developer Challenge 2 was open for submissions on Twitter. I&#8217;d had no intention of entering the competition until I read that tweet and felt personally challenged. Rashly, I decided that I could get Moseycode integrated and the rest of the application adapted for ADC2 in a handful of long evenings.

It&#8217;s too early to say whether I&#8217;m going to make it yet, but I&#8217;m glad I&#8217;m shooting for it. This is one of the products of my rapid labour: the ability to publish flowers from your garden as pictures that you can share. Anyone else with the application can import the flower directly from the in-built Gallery application or by scanning the picture with their phone camera.

I really like the idea of this sort of sharing - where the artefact is both appreciable by people and machine readable. I don&#8217;t know how it&#8217;s going to pan out yet, but you can expect more of this approach from my next applications (and not necessarily via moseycodes either).

With a number of Android applications laying incomplete in my digital atelier, I felt a pang when Dan Morrill announced that the Android Developer Challenge 2 was open for submissions on Twitter. I’d had no intention of entering the competition until I read that tweet and felt personally challenged. Rashly, I decided that I could get Moseycode integrated and the rest of the application adapted for ADC2 in a handful of long evenings.

It’s too early to say whether I’m going to make it yet, but I’m glad I’m shooting for it. This is one of the products of my rapid labour: the ability to publish flowers from your garden as pictures that you can share. Anyone else with the application can import the flower directly from the in-built Gallery application or by scanning the picture with their phone camera.

I really like the idea of this sort of sharing - where the artefact is both appreciable by people and machine readable. I don’t know how it’s going to pan out yet, but you can expect more of this approach from my next applications (and not necessarily via moseycodes either).

I&#8217;ve been holding back on releasing Daisy Garden because I really wanted users to have the ability to share their flowers from the first release. Now I&#8217;m wondering whether I can introduce this feature in a sprint and get the application ready for the close of the ADC 2.

I’ve been holding back on releasing Daisy Garden because I really wanted users to have the ability to share their flowers from the first release. Now I’m wondering whether I can introduce this feature in a sprint and get the application ready for the close of the ADC 2.