Search code examples
androidandroid-activitycropandroid-crop

refactor performCrop() method out of activity class


I have a PerformCrop method which works perfectly.

I want to move it to my 'util' class so i can call it in other activities. There are complications to this in that it uses intents which return to the calling class. I think this should be no issue but maybe i'm incorrect.

Here is what i have tried and the issue i am seeing

  1. I cut and paste performCrop() to my util class.
  2. I had an error at 'startActivityForResult(cropIntent, CROP_IMAGE);' where it didnt recognise the method so i extended the class with 'Extends Activity'
  3. When it runs it errors and im not 100% sure why but an exception is caught

'java.lang.NullPointerException: Attempt to invoke virtual method 'android.app.ActivityThread$ApplicationThread android.app.ActivityThread.getApplicationThread()' on a null object reference'

Here is the method, below that is the 'onActivityResult' method. Can anyone tell me how to move the performCrop() to a non Activity extended class?

Code

public void performCrop(Uri picUri)
{
    final int CROP_IMAGE = 2;
        /*
* PERFORM CROP
* this must take into account he fact we may not have a crop method on phone, or the diff ways diff OS crop
 */
    //NEXUS 5 OS 5 is example of this branch
    // take care of exceptions
    try {
        // call the standard crop action intent (the user device may not
        // support it)

        Intent cropIntent = new Intent("com.android.camera.action.CROP");
        // indicate image type and Uri
        cropIntent.setDataAndType(picUri, "image/*");
        // set crop properties
        cropIntent.putExtra("crop", "true");
        // // indicate aspect of desired crop
        cropIntent.putExtra("aspectX", 1);
        cropIntent.putExtra("aspectY", 1);
        // // // indicate output X and Y

        // retrieve data on return
        cropIntent.putExtra("return-data", true);
        // start the activity - we handle returning in onActivityResult
        startActivityForResult(cropIntent, CROP_IMAGE);
    }
    // respond to users whose devices do not support the crop action
    catch (ActivityNotFoundException anfe)
    {
        Toast toast = Toast.makeText(this,"This device doesn't support the crop action! Exception: " + anfe.toString(),Toast.LENGTH_SHORT);
        toast.show();
    }
    catch (OutOfMemoryError e)
    {//NOT TESTED AS HW DOES NOT GO HERE
        System.out.println("out of memory");
    }
    catch (Exception e)
    { //NOT TESTED AS HW DOES NOT GO HERE
        Display display = this.getWindowManager().getDefaultDisplay();
        Point size = new Point();
        //display.getSize(size);
        int width = size.x;
        int height = size.y;
        Intent cropIntent = new Intent("com.android.camera.action.CROP");
        // indicate image type and Uri
        cropIntent.setDataAndType(picUri, "image/*");
        // set crop properties
        cropIntent.putExtra("crop", "true");
        // // indicate aspect of desired crop
        cropIntent.putExtra("aspectX", 2);
        cropIntent.putExtra("aspectY", 1);
        // // indicate output X and Y
        cropIntent.putExtra("outputX", width);
        cropIntent.putExtra("outputY", 200);
        // retrieve data on return
        cropIntent.putExtra("return-data", true);
        // start the activity - we handle returning in onActivityResult
        startActivityForResult(cropIntent, CROP_IMAGE);
    }
}

Called from Activity when the camera intent returns successful result. Note the crop intent will also retun to this method.

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
    // TODO Auto-generated method stub
    if (resultCode==RESULT_OK )
    {
        if(requestCode == CAMERA_IMAGE) //reply from camera
        {
            toolbox.performCrop(uri); //crop the picture
        }

        if(requestCode == CROP_IMAGE) //reply from crop
        {
           /* Bitmap bmp = getBitmap(uri);
            imgView.setImageBitmap(bmp);*/
            Bundle extras = data.getExtras();
            if (extras != null) {
                Bitmap bmp = extras.getParcelable("data");
                imgViewProfilePic.setImageBitmap(bmp);
            }
        }

        if (requestCode == PICK_IMAGE_FROM_GALLERY) //reply from gallery
        {
            Uri selectedImage = data.getData();
            uri = data.getData();
            toolbox.performCrop(uri);
        }
    }
}

Solution

  • Create A Class name CropImage, put your method performCrop() in it and call it from wherever you want as,

                    CropImage cropImage = new CropImage(this);
                    cropImage.performCrop(uri);
    

    The CropImage claas would look like,

    public class CropImage {
    Context context;
    
    public CropImage(Context context) {
        this.context = context;
    }
    
    public void performCrop(Uri picUri)
    {
        final int CROP_IMAGE = 2;
        /*
        * PERFORM CROP
        * this must take into account he fact we may not have a crop method on phone, or the diff ways diff OS crop
        */
        //NEXUS 5 OS 5 is example of this branch
        // take care of exceptions
        try {
            // call the standard crop action intent (the user device may not
            // support it)
    
            Intent cropIntent = new Intent("com.android.camera.action.CROP");
            // indicate image type and Uri
            cropIntent.setDataAndType(picUri, "image/*");
            // set crop properties
            cropIntent.putExtra("crop", "true");
            // // indicate aspect of desired crop
            cropIntent.putExtra("aspectX", 1);
            cropIntent.putExtra("aspectY", 1);
            // // // indicate output X and Y
    
            // retrieve data on return
            cropIntent.putExtra("return-data", true);
            // start the activity - we handle returning in onActivityResult
            ((Activity)context).startActivityForResult(cropIntent, CROP_IMAGE);
        }
        // respond to users whose devices do not support the crop action
        catch (ActivityNotFoundException anfe)
        {
            Toast toast = Toast.makeText(context,"This device doesn't support the crop action! Exception: " + anfe.toString(), Toast.LENGTH_SHORT);
            toast.show();
        }
        catch (OutOfMemoryError e)
        {//NOT TESTED AS HW DOES NOT GO HERE
            System.out.println("out of memory");
        }
        catch (Exception e)
        { //NOT TESTED AS HW DOES NOT GO HERE
            Display display = ((Activity)context).getWindowManager().getDefaultDisplay();
            Point size = new Point();
            //display.getSize(size);
            int width = size.x;
            int height = size.y;
            Intent cropIntent = new Intent("com.android.camera.action.CROP");
            // indicate image type and Uri
            cropIntent.setDataAndType(picUri, "image/*");
            // set crop properties
            cropIntent.putExtra("crop", "true");
            // // indicate aspect of desired crop
            cropIntent.putExtra("aspectX", 2);
            cropIntent.putExtra("aspectY", 1);
            // // indicate output X and Y
            cropIntent.putExtra("outputX", width);
            cropIntent.putExtra("outputY", 200);
            // retrieve data on return
            cropIntent.putExtra("return-data", true);
            // start the activity - we handle returning in onActivityResult
            ((Activity)context).startActivityForResult(cropIntent, CROP_IMAGE);
        }
    }
    }