0
votes

I am taking images using the camera on an Android phone. After the image is taken, I pass the full image as a uri to the crop intent (com.android.camera.action.CROP). However, when the crop intent comes back, it returns in the parcelable at thumbnail size. I have tried to save the image from the camera in a file and send the uri of the file instead but it doesn't open the image in the crop intent. How can I get the full size image that I cropped in the crop intent from the parcel it sends back? Here is some of the code I am using:

public void onActivityResult(int requestCode, int resultCode,
        Intent intent) {
    if (resultCode != Activity.RESULT_CANCELED) {
        Uri uri = null;
        switch (requestCode) {
        case FILE_SELECT_CODE:
            if (intent.getData() != null) {
                uri = intent.getData();
                cropSelectedPicture(uri);
            }
            break;
        case PICTURE_SELECT_CODE:
            uri = intent.getData();
            if (uri == null) {
                Bundle bundle = intent.getExtras();
                Bitmap photo = null;
                if (bundle != null) {
                    photo = bundle.getParcelable("data");
                }
                finishChangeProfilePicture(photo);
            } else {
                cropSelectedPicture(uri);
            }
            break;
        case FILE_CROP_CODE:
            Bundle extras = intent.getExtras();
            Bitmap thePic = extras.getParcelable("data");
            uri = extras.getParcelable("uri");
            finishChangeProfilePicture(thePic);
            break;
        }
    }
    super.onActivityResult(requestCode, resultCode, intent);
}

public void showCamera() {
    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    intent.putExtra("crop", "true");
    intent.putExtra("outputX", pictureWidth);
    intent.putExtra("outputY", pictureHeight);
    intent.putExtra("aspectX", pictureWidth);
    intent.putExtra("aspectY", pictureHeight);
    intent.putExtra("scale", true);
    intent.putExtra("return-data", true);
    try {
        cordova.startActivityForResult(
                this, Intent.createChooser(intent, "Take Picture"),
                PICTURE_SELECT_CODE);
    } catch (android.content.ActivityNotFoundException ex) {
        // Potentially direct the user to the Market with a Dialog
        Toast.makeText(context, "Please install a Camera application.", 
                Toast.LENGTH_SHORT).show();
    }
}

public void cropSelectedPicture(Uri uri) {
    Intent intent = new Intent("com.android.camera.action.CROP");
    intent.setDataAndType(uri, "image/*");
    intent.putExtra("crop", "true");
    intent.putExtra("outputX", pictureWidth);
    intent.putExtra("outputY", pictureHeight);
    intent.putExtra("aspectX", pictureWidth);
    intent.putExtra("aspectY", pictureHeight);
    intent.putExtra("scale", true);
    intent.putExtra("return-data", true);

    PackageManager packageManager = context.getPackageManager();
    List<ResolveInfo> activities = packageManager.queryIntentActivities(intent, 0);
    if (activities.size() > 0) {
        for (int i = 0; i < activities.size(); i++) {
            String label = (String) activities.get(i).loadLabel(packageManager);
            if (label.equals("Crop picture")) {
                ActivityInfo activity = activities.get(i).activityInfo;
                ComponentName name = new ComponentName (activity.applicationInfo.packageName,
                                                        activity.name);
                intent.setComponent(name);
            }
        }
    }

    try {
        cordova.startActivityForResult(this, intent, FILE_CROP_CODE);
    } catch (android.content.ActivityNotFoundException ex) {
        Toast.makeText(context, "Please install a Cropping program", Toast.LENGTH_SHORT).show();
    }
}
1
Android does not have a CROP Intent: commonsware.com/blog/2013/01/23/…CommonsWare
@CommonsWare I have seen your blog post posted on this question all over. What I have not seen is any recommendations -- outside of those libraries on your post. That Crop intent that doesn't exist works fine when the Gallery is installed. But when it uses the Google+ photos app, well, it blows apart and nothing happens.TheLettuceMaster
@KickingLettuce: "That Crop intent that doesn't exist works fine when the Gallery is installed" -- and when the Gallery is not modified by a device manufacturer or ROM modder, and so long as the Gallery app elects to maintain this undocumented and unsupported API, and so long as the user chooses the Gallery app. And the Gallery app does not exist on all devices, replaced by Google+ Photos (as you noted) or other apps (at the behest of a device manufacturer or ROM modder).CommonsWare
@CommonsWare I get all of that. It works fine, in a very specific situation. Unfortunately, that situation is more and more not being presented. So what is the alternative?TheLettuceMaster
Pick a library. I personally haven't had a need for one, so I haven't tried them. The ones in my blog post came up while searching; the link in this comment is an Android Arsenal category for image cropping. There are probably others. I simply am trying to steer people away from using something unreliable, rather than steering people toward some specific other solution.CommonsWare

1 Answers

1
votes

Okay, so what I had to do was save the uri from the camera intent and then save the image to that intent when coming out of the crop intent. I had tried this once before but it was to an internal file to the app instead of to the content resolver. (Fair warning: This is a cordova project, not a native android project, so if you are having trouble with the Media.getBitmap line, then remove the cordova.getActivity() part and that should make it work) Here is what I changed:

public void onActivityResult(int requestCode, int resultCode,
        Intent intent) {
    if (resultCode != Activity.RESULT_CANCELED) {
        switch (requestCode) {
        case FILE_SELECT_CODE:
            if (intent.getData() != null) {
                uri = intent.getData();
                cropSelectedPicture();
            }
            break;
        case PICTURE_SELECT_CODE:
            uri = intent.getData();
            if (uri == null) {
                Bundle bundle = intent.getExtras();
                Bitmap photo = null;
                if (bundle != null) {
                    photo = bundle.getParcelable("data");
                }
                finishChangeProfilePicture(photo);
            } else {
                cropSelectedPicture();
            }
            break;
        case FILE_CROP_CODE:
            Bitmap theUriPic;
            try {
                theUriPic = Media.getBitmap(cordova.getActivity().getContentResolver(), uri);
                finishChangeProfilePicture(theUriPic);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            break;
        }
    }
    super.onActivityResult(requestCode, resultCode, intent);
}

public void cropSelectedPicture() {
    Intent intent = new Intent("com.android.camera.action.CROP");
    intent.setDataAndType(uri, "image/*");
    intent.putExtra("crop", "true");
    intent.putExtra("outputX", pictureWidth);
    intent.putExtra("outputY", pictureHeight);
    intent.putExtra("aspectX", pictureWidth);
    intent.putExtra("aspectY", pictureHeight);
    intent.putExtra("scale", true);
    intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
    intent.putExtra("return-data", true);

    PackageManager packageManager = context.getPackageManager();
    List<ResolveInfo> activities = packageManager.queryIntentActivities(intent, 0);
    if (activities.size() > 0) {
        for (int i = 0; i < activities.size(); i++) {
            String label = (String) activities.get(i).loadLabel(packageManager);
            if (label.equals("Crop picture")) {
                ActivityInfo activity = activities.get(i).activityInfo;
                ComponentName name = new ComponentName (activity.applicationInfo.packageName,
                                                        activity.name);
                intent.setComponent(name);
            }
        }
    }

    try {
        cordova.startActivityForResult(this, intent, FILE_CROP_CODE);
    } catch (android.content.ActivityNotFoundException ex) {
        Toast.makeText(context, "Please install a Cropping program", Toast.LENGTH_SHORT).show();
    }
}