Android: Crash after Image Crop when updated OS Version to 5.1.1
Asked Answered
L

3

6

I updated my nexus 5 Android OS version to 5.1.1 and also updated the Google Camera and Google Photos application. After this, when ever I tried to capture image and Crop it, my application crashes with the following Error:

FATAL EXCEPTION: main
Process: com.app.test, PID: 4857
java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=2, result=-1, data=Intent { typ=image/jpeg }} to activity {com.app.test/com.app.test.newActivity.activities.TestActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'android.os.Parcelable android.os.Bundle.getParcelable(java.lang.String)' on a null object reference
        at android.app.ActivityThread.deliverResults(ActivityThread.java:3574)
        at android.app.ActivityThread.handleSendResult(ActivityThread.java:3617)
        at android.app.ActivityThread.access$1300(ActivityThread.java:151)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1352)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:135)
        at android.app.ActivityThread.main(ActivityThread.java:5254)
        at java.lang.reflect.Method.invoke(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:372)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
 Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.os.Parcelable android.os.Bundle.getParcelable(java.lang.String)' on a null object reference
        at com.app.test.newActivity.activities.TestActivity.onActivityResult(TestActivity.java:127)
        at android.app.Activity.dispatchActivityResult(Activity.java:6192)
        at android.app.ActivityThread.deliverResults(ActivityThread.java:3570)
            at android.app.ActivityThread.handleSendResult(ActivityThread.java:3617)
            at android.app.ActivityThread.access$1300(ActivityThread.java:151)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1352)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5254)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)

Previously it was working fine. The code I have used is as follows:

Image Capture code:

try {
    Intent imageCapture = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    if (imageCapture.resolveActivity(getContext().getPackageManager()) != null) {
        imageCapture.putExtra(MediaStore.EXTRA_OUTPUT,  Uri.fromFile(new File(Environment.getExternalStorageDirectory().getAbsolutePath() + Constants.image_path)));
        startActivityForResult(imageCapture, Constants.CAMERA_IMAGE_CAPTURE);
    }
} catch (ActivityNotFoundException anfe) {
    Toast.makeText(getContext(), "device doesn't support capturing images!", Toast.LENGTH_SHORT).show();
}

Image Crop code

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
        super.onActivityResult(requestCode, resultCode, intent);
        if (resultCode == RESULT_OK) {
            if (requestCode == CAMERA_IAMGE_CROP) {
                Bundle extras = intent.getExtras();//intent.getExtras() is always returns NULL here         
                Bitmap thePic = extras.getParcelable("data");
                //setImageOnImageView(thePic);
            } else if (requestCode == Constants.CAMERA_IMAGE_CAPTURE)) {
                processCapturedImage();
            }
        }
    }

    private void processCapturedImage() {
        try {
            String path = Environment.getExternalStorageDirectory().getAbsolutePath() + Constants.image_path;
            File file = new File(path);
            if (file.exists()) {
                BitmapFactory.Options options = new BitmapFactory.Options();
                options.inPreferredConfig = Bitmap.Config.RGB_565;
                Bitmap bm = BitmapFactory.decodeFile(path, options);
                int rotate = AndroidUtils.getRotateValue(file.getAbsolutePath());
                if (rotate != 0) {
                    Debug.print("Profile pic rotation value is not 0.");
                    /****** Image rotation ****/
                    Matrix matrix = new Matrix();
                    matrix.postRotate(rotate);
                    bm = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true);
                }
                picUri = getImageUri(getApplicationContext(), bm);
                performCropAction();
            } else {
                Tools.showToast(EditProfileActivity.this, "Error occurred, please try again.");
            }
        } catch (Exception e) {
            Debug.printException(e);
        }
    }

    private void performCropAction() {
        try {
            Intent cropAction = new Intent("com.android.camera.action.CROP");
            cropAction.setDataAndType(picUri, "image/*");
            cropAction.putExtra("crop", "true");
            cropAction.putExtra("aspectX", 1);
            cropAction.putExtra("aspectY", 1);
            cropAction.putExtra("outputX", AS.getInPixels(100));
            cropAction.putExtra("outputY", AS.getInPixels(100));
            cropAction.putExtra("return-data", true);
            startActivityForResult(cropAction, CAMERA_IAMGE_CROP);
        } 
        catch (ActivityNotFoundException anfe) {
            Toast.makeText(this, "your device doesn't support the crop action!", Toast.LENGTH_SHORT).show();
        }
    }

As you can see, Bundle extras = intent.getExtras(); The intent.getExtras() here is always returns NULL.

Any help is really appreciated! Thanks.

Ladylike answered 17/6, 2015 at 11:12 Comment(4)
Android does not have a CROP Intent. There are many image cropping libraries available for Android; please use one.Bourg
but same code works below 5.1.1. In 5.1.1 the app crashes with exception. { java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=1, result=0, data=null} to activity {camera.test.demo/camera.test.demo.SimpleCameraGalleryDemo}: java.lang.NullPointerException: Attempt to invoke virtual method 'android.os.Bundle android.content.Intent.getExtras()' on a null object reference }Ladylike
"but same code works below 5.1.1" -- there are several thousand Android device models. I feel very confident that you have not tested on all of them, or even many of them. Most likely, you have tested on only one or two of them. Sloppy developers assume that undocumented, unsupported, and unofficial Intent actions will be supported on all devices. Talented developers use a library.Bourg
The code at following link is also not working on OS 5.1.1. But below 5.1.1 it's working fine. I think it's OS specific issue!!! code.tutsplus.com/tutorials/…Ladylike
S
7

Above android 5.0 Crop function return URI in onActivityResult so handle it with version of phone accordingly.

Bitmap selectedBitmap;
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
Bundle extras = data.getExtras();
selectedBitmap = extras.getParcelable("data");
}
else{
Uri uri = data.getData(); 
selectedBitmap=MediaStore.Images.Media.getBitmap(this.getContentResolver(),uri);
}

Hope this helps!

Shaduf answered 25/7, 2016 at 11:56 Comment(0)
N
2

I have same problem. The new CROP action doesn't use method onActivityResult(). Resolution: copy file to folder where you want to save cropped image, start "com.android.camera.action.CROP" with file copied earlier. When user clicks "Save" button after crop - the new copied file will be replaced with cropped image. Ask me if you have any questions.

Nesta answered 6/7, 2015 at 9:39 Comment(2)
can you please explain more about your solution.Nigritude
@Nigritude All Done. You can check new comment below.Nesta
N
2

@nikash Solution number one: If you want use only standard android Camera's Crop activity, you should know that the new (Android 5.1.1) Camera's crop activity doesn't return anything for onActivityResult() method. It just crops the image you provide. If you will provide Crop Activity with original image - it will replace the original image with new cropped one. It can't save it separately. You can create a copy of the original image (don't put this copy to your application's data folder, cause Camera's crop activity has no permissions to work with any files in your activity's folder). After, you can send to Camera's crop activity the new link of copied image. Then, after cropping, you can move cropped (before copied) image to any folder you want.

Solution number two: Better than first. You can use this image cropper: https://android-arsenal.com/details/1/207

Second solution is better than first one. Easy to use, easy to implement, and you don't care about other devices bugs. It will work everywhere without standard Camera's Crop Activity. Your application could be API7 and above. Don't forget to put "compile 'com.edmodo:cropper:1.0.1'" to your gradle file. Compile. And enjoy.

Example usage: Main activity:

Intent cropIntent = new Intent(Main.this, CropActivity.class);
cropIntent.putExtra("from", input.getAbsolutePath());
cropIntent.putExtra("to", output.getAbsolutePath());
startActivityForResult(cropIntent, CROP_IMAGE);

Crop activity:

Bitmap bmp = BitmapFactory.decodeFile(new File(getIntent().getExtras().getString("from")).getAbsolutePath());
cropImageView.setImageBitmap(bmp);
saveButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                getIntent().putExtra("bitmap", cropImageView.getCroppedImage());
                setResult(RESULT_OK, getIntent());
                finish();
            }
        });

After you can receive it in Main activity:

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (resultCode == RESULT_OK && data != null && requestCode == CROP_IMAGE)
    {
        croppedBitmap.setImageBitmap((Bitmap) data.getParcelableExtra("bitmap"));
    }
}

Crop Image Activity layout should contain:

<com.edmodo.cropper.CropImageView
    xmlns:custom="http://schemas.android.com/apk/res-auto"
    android:id="@+id/CropImageView"
    android:layout_centerVertical="true"
    android:layout_centerHorizontal="true"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    custom:aspectRatioX="5" />

Here you can find more about usage: https://github.com/edmodo/cropper/wiki

Nesta answered 10/7, 2015 at 8:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.