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!
Related posts:
- My Hope for Android Over the past two weeks, I've been getting deep into...
- Mapping the Virtual World to the Physical World I'm starting to see a very interesting trend lately with...
Tags: android
-
FirstClown
-
bala_eventurers
-
bala_eventurers