0
votes

I am trying to pick and crop a picture directly from the gallery, for some reason the crop intent doesn't always work, on some devices its working with the stock gallery, and on some devices its working only with unofficial gallery apps (like my G2).

I know it should work on my device because i have other apps that use the same gallery crop function and its works.

every time i try to open the intent with the stock gallery i get the following message: couldn't find item
(I want the user to pick the image, not pass specific image location)

// Start a intent to get event image from the user
private void getCroppedImage(){
    // Create an output directory for the image
    String timeStamp = new SimpleDateFormat("ddMMMyy_HHmmSSS").format(new Date());
    File dir = new File(Environment.getExternalStorageDirectory ()
            + File.separator
            + "MyApp/Images");

    File picPath = Environment.getExternalStoragePublicDirectory(
        Environment.DIRECTORY_PICTURES);

    File outputPath = new File(dir,"IMG_"+ timeStamp + ".jpg");

    // Make sure that the output dir exists
    if (!dir.exists()){
        dir.mkdirs();
    }

    // Start intent, if available
    Intent cropIntent = new Intent("com.android.camera.action.CROP");
    //cropIntent.setData(Uri.fromFile(picPath));
    cropIntent.setType("image/*");
    cropIntent.putExtra("crop", "true");
    cropIntent.putExtra("outputX", 512);
    cropIntent.putExtra("outputY", 512);
    cropIntent.putExtra("aspectX", 1);
    cropIntent.putExtra("aspectY", 1);
    cropIntent.putExtra("output", Uri.fromFile(outputPath));

    // Verify that the intent will resolve to an activity
    if (cropIntent.resolveActivity(getPackageManager()) != null) {
        startActivityForResult(cropIntent, REQUEST_CODE_CROP_IMAGE);
    }else{
        cropIntent.setAction(Intent.ACTION_GET_CONTENT);
        // Verify that the intent will resolve to an activity
        if (cropIntent.resolveActivity(getPackageManager()) != null) {
            startActivityForResult(cropIntent, REQUEST_CODE_GET_PICTURE);
        }else{
            Toast.makeText(this,"Gallery not detected",Toast.LENGTH_LONG).show();
        }
    }
}

any thoughts?

1

1 Answers

0
votes

try this:

public class CropOptionAdapter extends ArrayAdapter<CropOption> {
    private ArrayList<CropOption> mOptions;
    private LayoutInflater mInflater;

    public CropOptionAdapter(Context context, ArrayList<CropOption> options) {
        super(context, R.layout.crop_selector, options);

        mOptions = options;

        mInflater = LayoutInflater.from(context);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup group) {
        if (convertView == null)
            convertView = mInflater.inflate(R.layout.crop_selector, null);

        CropOption item = mOptions.get(position);

        if (item != null) {
            ((ImageView) convertView.findViewById(R.id.iv_icon))
                    .setImageDrawable(item.icon);
            ((TextView) convertView.findViewById(R.id.tv_name))
                    .setText(item.title);

            return convertView;
        }

        return null;
    }
}

public class CropOption {
    public CharSequence title;
    public Drawable icon;
    public Intent appIntent;
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (resultCode != RESULT_OK)
        return;

    switch (requestCode) {
    case PICK_FROM_CAMERA:
        /**
         * After taking a picture, do the crop
         */
        doCrop();

        break;

    case PICK_FROM_FILE:
        /**
         * After selecting image from files, save the selected path
         */
        mImageCaptureUri = data.getData();
        infoLog("pick from file");
        doCrop();

        break;

    case CROP_FROM_CAMERA:
        Bundle extras = data.getExtras();
        /**
         * After cropping the image, get the bitmap of the cropped image and
         * display it on imageview.
         */
        if (extras != null) {
            photo = extras.getParcelable("data");
            Bitmap circleBitmap = Bitmap.createBitmap(photo.getWidth(),
                    photo.getHeight(), Bitmap.Config.ARGB_8888);

            BitmapShader shader = new BitmapShader(photo, TileMode.CLAMP,
                    TileMode.CLAMP);
            Paint paint = new Paint();
            paint.setShader(shader);

            Canvas c = new Canvas(circleBitmap);
            c.drawCircle(photo.getWidth() / 2, photo.getHeight() / 2,
                    photo.getWidth() / 2, paint);

            img.setImageBitmap(photo);
        }

        File f = new File(mImageCaptureUri.getPath());
        /**
         * Delete the temporary image
         */
        if (f.exists())
            f.delete();

        break;

    }
}

private void doCrop() {
    final ArrayList<CropOption> cropOptions = new ArrayList<CropOption>();
    /**
     * Open image crop app by starting an intent
     * ‘com.android.camera.action.CROP‘.
     */
    Intent intent = new Intent("com.android.camera.action.CROP");
    intent.setType("image/*");

    /**
     * Check if there is image cropper app installed.
     */
    List<ResolveInfo> list = getPackageManager().queryIntentActivities(
            intent, 0);

    int size = list.size();

    /**
     * If there is no image cropper app, display warning message
     */
    if (size == 0) {
        Toast.makeText(this, "Can not find image crop app",
                Toast.LENGTH_SHORT).show();

        return;
    } else {
        /**
         * Specify the image path, crop dimension and scale
         */
        intent.setData(mImageCaptureUri);

        intent.putExtra("outputX", 200);
        intent.putExtra("outputY", 200);
        intent.putExtra("aspectX", 1);
        intent.putExtra("aspectY", 1);
        intent.putExtra("scale", true);
        intent.putExtra("return-data", true);
        /**
         * There is possibility when more than one image cropper app exist,
         * so we have to check for it first. If there is only one app, open
         * then app.
         */

        if (size == 1) {
            Intent i = new Intent(intent);
            ResolveInfo res = list.get(0);

            i.setComponent(new ComponentName(res.activityInfo.packageName,
                    res.activityInfo.name));

            startActivityForResult(i, CROP_FROM_CAMERA);
        } else {
            /**
             * If there are several app exist, create a custom chooser to
             * let user selects the app.
             */
            for (ResolveInfo res : list) {
                final CropOption co = new CropOption();

                co.title = getPackageManager().getApplicationLabel(
                        res.activityInfo.applicationInfo);
                co.icon = getPackageManager().getApplicationIcon(
                        res.activityInfo.applicationInfo);
                co.appIntent = new Intent(intent);

                co.appIntent
                        .setComponent(new ComponentName(
                                res.activityInfo.packageName,
                                res.activityInfo.name));

                cropOptions.add(co);
            }

            CropOptionAdapter adapter = new CropOptionAdapter(
                    getApplicationContext(), cropOptions);

            AlertDialog.Builder builder = new AlertDialog.Builder(this);
            builder.setTitle("Choose Crop App");
            builder.setAdapter(adapter,
                    new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int item) {
                            startActivityForResult(
                                    cropOptions.get(item).appIntent,
                                    CROP_FROM_CAMERA);
                        }
                    });

            builder.setOnCancelListener(new DialogInterface.OnCancelListener() {
                @Override
                public void onCancel(DialogInterface dialog) {

                    if (mImageCaptureUri != null) {
                        getContentResolver().delete(mImageCaptureUri, null,
                                null);
                        mImageCaptureUri = null;
                    }
                }
            });

            AlertDialog alert = builder.create();

            alert.show();
        }
    }
}