Search code examples
androidandroid-activitylifecyclestartactivityforresult

startActivityForResults not working when the child activity calls another activity


I have 3 activities say A, B and C.

A calls B.

When B doesn't call C it returns to A. But when B calls C it doesn't return to A, the app stops.

Now the real problem is, from activity A I want to call an image picker and crop the image. That's Activity B which crops and calls C for picking image.

Activity A:

    iv_profile_pic.setOnClickListener(new  View.OnClickListener() {//iv_profile_pic is an ImageView
        @Override
        public void onClick(View view) {
            Intent i=new Intent(MainActivity.this,profile_pic_chooser.class);
            i.setFlags(0);
            MainActivity.this.startActivityForResult(i, 999);

            Toast.makeText(getApplicationContext(),"Reached",Toast.LENGTH_SHORT).show();

        }
    });

@Override
    public void onActivityResult(int requestCode, int resultCode, Intent data)
    {
        if (requestCode == 999) {
            Bitmap image=data.getParcelableExtra("picture");

            iv_profile_pic.setImageBitmap(image);


        }
    }

Activity B:

It has 2 buttons. Load and Crop. Load when clicked calls ImageChooserIntent and chooses an image which is opened in B with guidlines to crop.

Crop when clicked should return back to A the cropped image.

If crop is called without calling load, it returns to A with null, of-course. But if Load is clicked first and then Crop is called, the app simply stops.

 public void onLoadImageClick(View view) {

        startActivityForResult(getPickImageChooserIntent(), 200);
 }

public void onCropImageClick(View view) {
        Bitmap cropped =  mCropImageView.getCroppedImage(500, 500);
        if (cropped != null) {
            mCropImageView.setImageBitmap(cropped);
            iv.setImageBitmap(cropped);

            Intent returnIntent = new Intent();
            returnIntent.putExtra("picture", cropped);
            setResult(Activity.RESULT_OK, returnIntent);
            finish();
        }
    }

@Override
    protected void onActivityResult(int  requestCode, int resultCode, Intent data) {
        if (resultCode == Activity.RESULT_OK) {
            Uri imageUri =  getPickImageResultUri(data);

            // For API >= 23 we need to check specifically that we have permissions to read external storage,
            // but we don't know if we need to for the URI so the simplest is to try open the stream and see if we get error.
            boolean requirePermissions = false;
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M &&
                    checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED &&
                    isUriRequiresPermissions(imageUri)) {

                // request permissions and handle the result in onRequestPermissionsResult()
                requirePermissions = true;
                mCropImageUri = imageUri;
                requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 0);
            }

            if (!requirePermissions) {
                mCropImageView.setImageUriAsync(imageUri);
            }
        }
    }

Solution

  • I got a workaround. The most probable problem I was facing was:

    I was using an external library for cropping the image. This library did 2 things.

    First, selected an image using imageChooser intent.

    Second, Cropped that image.

    After the library cropped the image, it wasn't saving the cropped image in local/external storage. But I was trying to pass it back to parent directory.

    There's the problem. The file doesn't exist and still I am trying to use it. The application terminates.

    So my workaround was,

    • Save the bitmap in storage

    • Pass the Uri to parent

    • Extract that Uri from child

    • Make bitmap from that Uri

    • Apply on the ImageView

    So Activity B had:

    public void onCropImageClick(View view) {
            Bitmap cropped =  mCropImageView.getCroppedImage(500, 500);
            if (cropped != null) {
                mCropImageView.setImageBitmap(cropped);
                iv.setImageBitmap(cropped);
                File externalStorageDirectory = Environment.getExternalStorageDirectory();
                externalStorageDirectory= new File(externalStorageDirectory , "FOLDERNAME");
    
                if(!createDirIfNotExists(externalStorageDirectory)){
                    Toast.makeText(this,"Failed creating Directory!",Toast.LENGTH_SHORT).show();
                }else{
    
                    File filename=new File(externalStorageDirectory, String.valueOf(Calendar.getInstance().getTimeInMillis())+".PNG");
                    FileOutputStream out = null;
                    try {
                        out = new FileOutputStream(filename);
                        cropped.compress(Bitmap.CompressFormat.PNG, 100, out); // cropped is your Bitmap instance
                        // PNG is a lossless format, the compression factor (100) is ignored
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        try {
                            if (out != null) {
                                out.close();
                                Intent returnIntent = new Intent();
                                returnIntent.putExtra("picture", Uri.fromFile(filename));
                                setResult(RESULT_OK, returnIntent);
                                finish();
    
                            }
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
    
                }
    
            }
            //Toast.makeText(this,mCropImageUri.toString(),Toast.LENGTH_SHORT).show();
    
    
        }
    

    And Activity A had:

    @Override
        public void onActivityResult(int requestCode, int resultCode, Intent data)
        {
    
            if (requestCode == 999 && resultCode==RESULT_OK) {
    
               Uri path=data.getParcelableExtra("picture");
                Bitmap bitmap=null;
                try {
                    bitmap= MediaStore.Images.Media.getBitmap(this.getContentResolver(), path);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                Toast.makeText(this,path.toString(),Toast.LENGTH_SHORT).show();
    
                if (bitmap!=null){
    
                    iv_profile_pic.setImageBitmap(bitmap);
    
                }
    }
    

    Maybe my problem statement is wrong, but workaround works. Any edits/suggestions

    are 100% welcome. Just in-case someone like me gets stuck, this might help!