Intent for selecting wallpaper with wallpaper region highlighting

I would like to know if it's possible to create an Intent that makes the gallery cropper show wallpaper highlighting.

Assuming you want your app to behave properly across all Android devices, the answer is no. Neither the cropping activity nor the highlighted crop-view is part of the public API; both are internal to the Gallery 3D app. In other words, you could spend all the time in the world trying to find an Intent action to get this to magically work for you, but the fact is that some devices simply won't support it. For example, many devices, such as the HTC Sense and Samsung Galaxy, have customized Android versions that have their own gallery app. Since these Gallery apps are specific to the companies that designed them, these devices won't necessarily have a CropImage class for you to launch.

That being said, in order to guarantee that your application works across all devices, you'll have to incorporate the cropping code directly into your project. And if for some reason you find a way to launch the crop activity with an Intent, you should test to see whether the com.android.gallery3d package exists at the very least, and handle it somehow.

I have included below a work-around that might help you incorporate the Android code into your project. I don't currently have access to a tablet running Honeycomb/ICS so I can't be more specific with regards to how to get it working on newer versions of Android, but I imagine it involves similar analysis and a bit of copying and pasting from the com.android.gallery3d package.


Reusing the "Crop Activity" on Android 2.x

I tested this on my Nexus One and just before the soft "crop-rectangle" popped up, I got the following logcat output:

I/ActivityManager(   94): Starting: Intent { 
    act=android.intent.action.CHOOSER 
    cmp=android/com.android.internal.app.ChooserActivity (has extras) } from pid 558
I/ActivityManager(   94): Starting: Intent { 
    act=android.intent.action.ATTACH_DATA 
    dat=content://media/external/images/media/648 
    typ=image/jpeg 
    flg=0x3000001 
    cmp=com.google.android.gallery3d/com.cooliris.media.Photographs (has extras) } from pid 558
I/ActivityManager(   94): Starting: Intent { 
    dat=content://media/external/images/media/648 
    cmp=com.google.android.gallery3d/com.cooliris.media.CropImage (has extras) } from pid 558

So from what I can tell, the sequence of events that occurs when you perform this action is as follows:

  1. You navigate to an image in the gallery and select "set as...". An ActivityChooser pops up and you select "Wallpaper".
  2. This selection fires an Intent with action ATTACH_DATA and component com.cooliris.media.Photographs, which is a class in the Android framework that serves as a "wallpaper picker" for the camera application; it just redirects to the standard pick action. Since we have given the Intent a URI that specifies the image to set as the wallpaper, this class will inevitably execute the following code (see the class's onResume method):

    Intent intent = new Intent();   
    intent.setClass(this, CropImage.class);
    intent.setData(imageToUse);
    formatIntent(intent);
    startActivityForResult(intent, CROP_DONE);
    
  3. This fires another Intent that starts the CropImage Activity... this is where you specify the cropped area using the soft-rectangle. When you specify the crop, the result is set to RESULT_OK with requestCode = CROP_DONE. The Photographs Activity switch-cases over these two constants and then sets the wallpaper accordingly (see the Photographs class's onActivityResult method).

Unfortunately, for whatever reason the Android team decided to removed these functionalities from the SDK beginning with API 4 (Android v1.6)... so if you wanted to fire an Intent to perform these exact sequence of events, it would require you to sift through the com.cooliris.media package, and to copy and paste the relevant classes into your project. In my past experience, doing this is often more trouble than it is worth (unless it is to perform a relatively simple action) but it is definitely possible.

Here is a nice tutorial on how you might go about simplifying the process... it requires you to copy and paste 12 Java classes into your project as opposed to the entire com.cooliris.media package. These classes together should be enough to correctly fire up the CropImage Activity, but you will have to set the wallpaper manually upon the CropImage Activity's result.

Also note that the sample code provided assumes that you want to crop immediately after a picture is taken by the camera. In order to, for example, start the CropImage Activity with a pre-selected image from the gallery, you'd call,

Intent i = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(i, ACTIVITY_SELECT_IMAGE);

and then in onActivityResult, (if requestCode == ACTIVITY_SELECT_IMAGE and resultCode == RESULT_OK), launch the CropImage Activity with the Uri data given in the onActivityResult's third argument (see the sample code for an example on how to launch the Activity).

If anything, hopefully this will help point you in the right direction. Let me know how it goes and leave a comment if you want me to clarify anything.


I this will help:

public class CropSelectedImageActivity extends Activity {

    @Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
            photoPickerIntent.setType("image/*");
            startActivityForResult(photoPickerIntent, 1);
}

    public void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
            if (resultCode == RESULT_OK) {
                    final Bundle extras = data.getExtras();
                    Uri photoUri = data.getData();
                    if (photoUri != null) {
                            Intent intent = new Intent("com.android.camera.action.CROP");
                    //intent.setClassName("com.android.camera", "com.android.camera.CropImage");

                    intent.setData(photoUri);
                    intent.putExtra("outputX", 96);
                    intent.putExtra("outputY", 96);
                    intent.putExtra("aspectX", 1);
                    intent.putExtra("aspectY", 1);
                    intent.putExtra("scale", true);
                    intent.putExtra("return-data", true);            
                    startActivityForResult(intent, 1);
                    }
            }
    }
}

taken from: ImageCropper