0

In my App, there is provision of taking picture through Camera and send it for Crop but when the Camera App opens with the sent image and the user crops and clicks on OK, a toast is displayed by the Camera App,

"Unable to save cropped images"

Here is the code I have written for it:

public static void sendImageForCrop(final Activity activity, final Uri mImageCaptureUri){

        final ArrayList<CropOption> cropOptions = new ArrayList<>();

        Intent intent = new Intent("com.android.camera.action.CROP");
        intent.setType("image/*");

        List<ResolveInfo> list = activity.getPackageManager().queryIntentActivities(
                intent, 0);

        int size = list.size();

        if (size == 0) {
            Toast.makeText(activity, "Can not find image crop app",
                    Toast.LENGTH_SHORT).show();
        } else {
            //intent.setData(mImageCaptureUri);
            intent.setDataAndType(mImageCaptureUri, "image/*");

            intent.putExtra("crop", "true");
            intent.putExtra("outputX", 150);
            intent.putExtra("outputY", 150);
            intent.putExtra("aspectX", 1);
            intent.putExtra("aspectY", 1);
            intent.putExtra("scale", true);
            intent.putExtra("return-data", true);

            intent.setFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
            try{
                intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(File.createTempFile("temp", null, activity.getCacheDir())));

            }catch(IOException ioe){
                // It is unfortunate that the Photo can't be cropped.
                // Show a Toast for this.
                Toast.makeText(activity, "The photo couldn't be saved :(. Try clearing the App data.", Toast.LENGTH_SHORT).show();
                return;
            }

            activity.startActivityForResult(i, CROP_FROM_CAMERA);
        }
    }

And here is the toString() of the Intent object:

Intent { act=com.android.camera.action.CROP dat=file:///storage/emulated/0/Snap_1508218098533.jpg typ=image/* flg=0x2 (has extras) }

What might be the problem here?


EDIT: As requested, here is the manifest file:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.example.example"
    android:versionCode="156"
    android:versionName="1.2.54">

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_INTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.READ_CONTACTS" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />

    <uses-permission android:name="com.google.android.apps.photos.permission.GOOGLE_PHOTOS"/>

    <uses-sdk tools:overrideLibrary="com.braintreepayments.api.core,com.android.volley,com.paypal.android.sdk.onetouch.core,com.braintreepayments.api" />

    <uses-feature
        android:name="android.hardware.camera"
        android:required="false" />
    <uses-feature
        android:name="android.hardware.camera.autofocus"
        android:required="false" />
    <uses-feature
        android:name="android.hardware.location.network"
        android:required="false" />
    <uses-feature
        android:name="android.hardware.location"
        android:required="false" />
    <uses-feature
        android:name="android.hardware.location.gps"
        android:required="false" />
    <uses-feature
        android:name="android.hardware.microphone"
        android:required="false" />


    <!-- Tell the system this app requires OpenGL ES 2.0. -->
    <uses-feature
        android:glEsVersion="0x00015000"
        android:required="true" />
    <uses-feature
        android:name="android.hardware.touchscreen"
        android:required="false" />


    <application
        android:name="com.example.example.UILApplication"
        android:allowBackup="true"
        android:hardwareAccelerated="true"
        android:icon="@drawable/applicationlogo"
        android:label="@string/app_name"
        android:largeHeap="true"
        android:theme="@style/Theme.MyTheme">

          <!-- List of Activities here -->


        <provider
            android:name=".provider.GenericFileProvider"
            android:authorities="${applicationId}.provider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/provider_paths" />
        </provider>


    </application>

</manifest>
Manish Kumar Sharma
  • 12,982
  • 9
  • 58
  • 105

3 Answers3

0

I had same problem but I fixed by changing the path of saved image directory as below -:

File croppedImageDirectory = new File(Environment.getExternalStorageDirectory()+"/croppedImage");

Or, see this answer may help you-: stackoverflow.com/a/1976115

May help you

King of Masses
  • 18,405
  • 4
  • 60
  • 77
UltimateDevil
  • 2,807
  • 2
  • 18
  • 31
  • The problem with this solution is that `Environment.getExternalStorageDirectory()` is not guaranteed to be available. https://stackoverflow.com/questions/11463695/fallback-solutions-when-getexternalstoragedirectory-is-not-available – Manish Kumar Sharma Oct 17 '17 at 10:14
0

I think the problem is may be with the path where your trying to save,

try to use like below

public void choosePhoto(View view) {        
    Intent intent = new Intent(Intent.ACTION_PICK, null); 
    intent.setType("image/*");
    intent.putExtra("crop", "true");
    intent.putExtra("aspectX", 1);
    intent.putExtra("aspectY", 1);
    intent.putExtra("outputX", int_Width_crop);
    intent.putExtra("outputY", int_Height_crop);
    intent.putExtra("scale", false);
    intent.putExtra("return-data", true);
    File photo = new File(Environment.getExternalStorageDirectory(), "cropped_image.jpg");        
    intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photo));
    imageUri = Uri.fromFile(photo);
    intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
    startActivityForResult(intent, CHOOSE_PICTURE);         
}
King of Masses
  • 18,405
  • 4
  • 60
  • 77
  • The problem with this solution is that Environment.getExternalStorageDirectory() is not guaranteed to be available. https://stackoverflow.com/questions/11463695/fallback-solutions-when-getexternalstoragedirectory-is-not-available – Manish Kumar Sharma Oct 17 '17 at 10:15
  • External storage is always availab!e. Dont believe every post you read. – greenapps Oct 17 '17 at 13:25
  • @greenapps : Well, the docs say about `getExternalStorageDirectory()`: *Return the primary shared/external storage directory. **This directory may not currently be accessible if it has been mounted by the user on their computer, has been removed from the device, or some other problem has happened.** You can determine its current state with* – Manish Kumar Sharma Oct 17 '17 at 15:10
  • That is a very old doc. Throw it away! Externalstorage has nothing to do with removable media. – greenapps Oct 17 '17 at 15:13
0

I know this would be a considered a hack approach by many of you but it works!

intent.putExtra(MediaStore.EXTRA_OUTPUT, (String)null);

Reasoning

Well, I looked up the source of Gallery App in MarshMallow(one of the places the crop was failing; other was the Photos App) and found this method that handles a CROP request:

private void saveOutput(Bitmap croppedImage) {
        if (mSaveUri != null) {
            OutputStream outputStream = null;
            try {
                outputStream = mContentResolver.openOutputStream(mSaveUri);
                if (outputStream != null) {
                    croppedImage.compress(mOutputFormat, 75, outputStream);
                }
            } catch (IOException ex) {
                // TODO: report error to caller
                Log.e(TAG, "Cannot open file: " + mSaveUri, ex);
            } finally {
                Util.closeSilently(outputStream);
            }
            Bundle extras = new Bundle();
            setResult(RESULT_OK, new Intent(mSaveUri.toString())
                    .putExtras(extras));
        } else if (mSetWallpaper) {
            try {
                WallpaperManager.getInstance(this).setBitmap(croppedImage);
                setResult(RESULT_OK);
            } catch (IOException e) {
                Log.e(TAG, "Failed to set wallpaper.", e);
                setResult(RESULT_CANCELED);
            }
        } else {
            Bundle extras = new Bundle();
            extras.putString("rect", mCrop.getCropRect().toString());
            File oldPath = new File(mImage.getDataPath());
            File directory = new File(oldPath.getParent());
            int x = 0;
            String fileName = oldPath.getName();
            fileName = fileName.substring(0, fileName.lastIndexOf("."));
            // Try file-1.jpg, file-2.jpg, ... until we find a filename which
            // does not exist yet.
            while (true) {
                x += 1;
                String candidate = directory.toString()
                        + "/" + fileName + "-" + x + ".jpg";
                boolean exists = (new File(candidate)).exists();
                if (!exists) {
                    break;
                }
            }
            try {
                int[] degree = new int[1];
                Uri newUri = ImageManager.addImage(
                        mContentResolver,
                        mImage.getTitle(),
                        mImage.getDateTaken(),
                        null,    // TODO this null is going to cause us to lose
                                 // the location (gps).
                        directory.toString(), fileName + "-" + x + ".jpg",
                        croppedImage, null,
                        degree);
                setResult(RESULT_OK, new Intent()
                        .setAction(newUri.toString())
                        .putExtras(extras));
            } catch (Exception ex) {
                // basically ignore this or put up
                // some ui saying we failed
                Log.e(TAG, "store image fail, continue anyway", ex);
            }
        }
        final Bitmap b = croppedImage;
        mHandler.post(new Runnable() {
            public void run() {
                mImageView.clear();
                b.recycle();
            }
        });
        finish();
    }

You see the statement, if (mSaveUri != null) {. It handles the case where we provide a null Uri. The assumption is that the 3rd party App is likely to handle the case where we provide a null Uri.

Now, I tested it with a couple of Apps and it worked. But by no means, this solution is an ideal one.

Manish Kumar Sharma
  • 12,982
  • 9
  • 58
  • 105