FirstClown

firstclown at firstclown.us

Posts Tagged ‘android’

Adding Icons to Your Android Application

After seeing how easy it is to add an icon to a contact in my new G1 phone, I decided to try and do it in an application of my own. I've sense been asked about it a little bit, so I figured I'd post how to do it on my blog. It's surprisingly easy, but there's quite a few steps involved.

BTW, none if this is original, but I haven't seen anyone really write a up a complete post on how to do it. I reverse engineered the concept and the steps from the great open source project apps-for-android.

UI

To set up the interface for adding the icon, you'll want to add an ImageButton to the edit screen for your items. You can then set the image with:

    protected void showIconButton(String iconUri){
        if(iconUri != null){
            ImageButton iconField = (ImageButton) findViewById(R.id.iconButton);
            iconField.setImageURI(null);
            iconField.setImageURI(Uri.parse(iconUri));
            iconField.invalidate();
        }
    }

You'll need the extra iconField.setImageURI(null); call in there since Android ignores a call to setImageURI that has the same URI is it currently holds. Since I save the new icon image to the same place as the old one, that can be a problem.

You'll also want to have the button set up to select a new image when it's clicked. That will be a simple call to iconField.setOnClickListener(cmdIconListener); in the onCreate method of the Activity.

Button Listener

Now we can create the action the button should take when it's clicked.

    protected OnClickListener cmdIconListener = new OnClickListener() {
        public void onClick(View arg0) {
            Intent i = new Intent("android.intent.action.GET_CONTENT");
            i.setType("image/*"); // We just want images.
 
            //ADD_ICON is a unique integer code for the intent response.
            startActivityForResult(i, AddTea.ADD_ICON); 
        }
    };

You can see we're firing a very simple Intent to get an image. This will allow the user to select an image from their picture gallery, just like the contact application does. It also keeps it generic enough that another application can act on this Intent, too.

Crop the Image

This Intent will return an image URI that we then want to crop:

    protected void onActivityResult(int requestCode, int resultCode, Intent data){
        // See which child activity is calling us back.
        switch (requestCode) {
        case AddTea.ADD_ICON:
            // This is the standard resultCode that is sent back if the
            // activity crashed or didn't doesn't supply an explicit result.
            if (resultCode != RESULT_CANCELED){
                Intent i = new Intent("com.android.camera.action.CROP");
                i.setClassName("com.android.camera", "com.android.camera.CropImage");
                i.setData(data.getData());
                Log.d(TAG, "path: " + data.getData().getPath());
                i.putExtra("noFaceDetection", true);
                i.putExtra("outputX", iconWidth);
                i.putExtra("outputY", iconHeight);
                i.putExtra("aspectX", iconWidth);
                i.putExtra("aspectY", iconHeight);
                i.putExtra("scale", true);
 
                if(iconUri == null){
                    ContentValues values = new ContentValues();
                    values.put(android.provider.MediaStore.Images.Media.TITLE, name + " Icon");
                    values.put(android.provider.MediaStore.Images.Media.BUCKET_ID, "STeaP_Tea_Timer_Icons");
                    values.put(android.provider.MediaStore.Images.Media.BUCKET_DISPLAY_NAME, "STeaP Tea Timer Icons");
                    values.put(android.provider.MediaStore.Images.Media.IS_PRIVATE, 1);
                    iconUri = getContentResolver().insert(android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values).toString();
                }
                i.putExtra("output", Uri.parse(iconUri));
                startActivityForResult(i, CROP_ICON);
            }
            break;

We're basically just sending another Intent after getting the first one back. Here we are sending the Intent to a specific Activity, the com.android.camera.CropImage Activity. This Activity will crop the image and save the image, so we need to pass all the information we want the image saved with. The important ones are:

  • noFaceDetection - Unless you're looking for people, you'll want this to be true.
  • outputX - The width of the resulting image. In pixels.
  • outputY - The height of the resulting image. In pixels.
  • aspectX, aspectY - The aspect ratio of the crop square. Don't set these if you want the user to pick whatever size they want, otherwise set them to what you want.
  • scale - Whether you want the image scaled to the dimensions you set. Almost always should be true.
  • android.provider.MediaStore.Images.Media.IS_PRIVATE - Set to true if you don't want all of your little icons clogging up the Android Pictures app.

The insert command on the ContentProvider will hand you back the images URI so you can store it with the rest of your item's data. In my example, if I already have a URI for the icon, I just overwrite it with the new cropped image, no need to create another one.

Now we just need to handle the result from the Crop Intent:

case AddTea.CROP_ICON:
            if (resultCode != RESULT_CANCELED) {
                Log.d(TAG, "Data String: " + iconUri);
                showIconButton(iconUri);
            }
        default:
            break;

And now you've got your icon stored in the ContentProvider and the URI in your application. Easy as that!

Mapping the Virtual World to the Physical World

I'm starting to see a very interesting trend lately with everyone moving to mobile internet devices like the iPhone and Android. To call those cell phones is kind of a misnomer since the cell phone part of these devices is probably the least used part. They are much more suited to being mobile internet devices and GPS units then mere cell phones. But they're leading to an interesting phenomenon:

The Ability to Map Virtual Objects to the Physical World

I think a lot of the applications coming out for these devices are focusing on "social" aspects of computers and, while they're suited to that, I think there will be another class of applications that will have more to do with mapping virtual objects to the physical place you are now. I know there have been "location aware" applications, but I think that soon we will even be going beyond just awareness and more "location mapping" applications.

A great example of this that I've seen recently is Sekai Camera from tonchidot that allows you to tag real world objects like you would a wiki. Looking through the camera on a mobile device shows you, on top of the real world object, tags and objects that other users have attached to those things. Look through the camera at a restaurant you're standing in front of and maybe a bubble pops up to show recent reviews or current menu items or even recent health inspector reports. Choosing between three different restaurants that are right next to each other and picking a place to eat lunch at just got a lot easier. No more searching for the restaurants and clicking through a bunch of screens to get to this information; I know where you are, where you're looking and what has been tagged in that location and I just make it available to you.

There's also the idea of location-based to do lists. I'm actually building one for Android where you tag your to do items with a tag like "store" and then add GPS data to the tag to say where the store is. The same could be done for "home" and "work" tags. Then, when you open the to do list on your device, the proper to do items pop up depending on where you are. You could say this is just a "location aware" application, but I think it gets more subtle than that at this level because you really have tags these items with a location and they kind of live there to a certain degree. And nothing is stopping you from tagging them with multiple tags. I also see "global tags" like "gas_station" that would have them pop up at a gas station, any gas station.

I know there have been some location messaging (think Twitter with GPS tags, so you only see it if you're at that location. Great for scavenger hunts!) applications thought about too, but I haven't seen any of them take off. The critical mass type apps are going to have a hard time until more people have these devices and are using them in this way. But I think it's coming and I hope to be able to contribute something along the way.

What location mapping applications would you like to see?

My Hope for Android

Over the past two weeks, I've been getting deep into Google Android development and I'm pretty excited about it. It'll be amazing to see a fully open source platform for mobile phones and it looks like it'll be adopted by all the major carriers (except ATT, for obvious reasons). I'm also glad to hear a lot of talk from the industry about how this could change everything from the standpoint of smart phones, a traditionally locked-down and stagnant area of technology that's always had a lot of potential.

The application APIs are also quite amazing. They allow things like multi-threading, so an application can run in the background while other apps are running, the ability to install by download, so vendors can't lock down what apps you can run, and the handling of events, so if I don't like the default SMS app, I can write my own or install a better one that I like better. Carriers will have to play along to keep everything open and playing friendly, but T-Mobile has already said that they will, so any other carrier will have a hard time selling a locked down version at this point.

With the release of the first Android based phone, the not-so-hot IMO G1, we're seeing these phones coming to market. Here's what I'm hoping happens:

  1. The T-Mobile G1 gets released on Oct. 22nd as the first Android powered phone. It'll only be the first phone for the platform, so it's by no means the end-all-be-all. It'll also be SIM-locked to T-Mobile.
  2. I'm hoping that it'll only be a few weeks after that when Google open sources the entire Android codebase. We already know that they will and I'm hoping it's sooner rather than later.
  3. Once Android is open sourced, it'll start getting ported to other phones, either via the manufacturers of those phones or by open source developers. I'm really hoping it gets to the Nokia phones and other HTC phones sooner rather than later.
  4. Once that happens, you'll be free to use whatever phone you want with whatever carrier you want and still get all the great features of Android; the OS itself, the one API needed for all Android phones and all the apps to be written, and already written, for the platform.

If those things do happen like I hope they will, I think we'll really start to see the power of an open platform for mobile. If it was just going to be the G1 and that was it, it really wouldn't be all that exciting, but I think everything is set up to have this take off if it ends up being as open as Google seems to be leading on about.

FirstClown is powered by WordPress
Entries (RSS) and Comments (RSS).