OnActivityResult sometimes not called after ACTION_GET_CONTENT intent
Asked Answered
X

5

39

I'm working on an image editing Android application. In one of my activities I call an intent to pick an image from the gallery in onCreate() like this:

Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Select Picture"), PICK_IMAGE);

Then I receive data like this:

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    Crashlytics.log("onActivityResult called");
    super.onActivityResult(requestCode, resultCode, data);

    if (requestCode == PICK_IMAGE && resultCode == Activity.RESULT_OK && data != null) {
        Crashlytics.log("Data received from image pick intent");
        imageUri = data.getData();
        loadImage();
    } else {
        //if we do not select a picture, go back to the dashboard
        Crashlytics.log("Data not received");
        onBackPressed();
        Log.d(TAG, "no picture selected");
    }
}

The loadImage method:

private void loadImage() {
    try {
        photoBitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), imageUri);
    } catch (IOException e) {
        Crashlytics.log("IOException from getBitmap");
        Log.d(TAG, e.getMessage());
        showToastAndPressBack();
        return;
    }

    if (photoBitmap == null) {
        Crashlytics.log("photoBitmap is null in onActivityResult");
        showToastAndPressBack();
        return;
    }

    Display display = getWindowManager().getDefaultDisplay();
    Point size = new Point();
    display.getSize(size);
    imgVWidth = size.x;
    int height = size.y;
    imgVHeight = (int) (((float) imgVWidth / photoBitmap.getWidth()) * photoBitmap.getHeight());
    photoInImgViewBitmap = Bitmap.createScaledBitmap(photoBitmap, imgVWidth, imgVHeight, true);
    imageAlreadyPicked = true;
}

Now my problem is that sometimes I see NPE-s in Crashlytics claiming that photoBitmap is null when the user presses the next button.

@OnClick(R.id.toolbar_next)
void onToolbarNextClick() {
    float originalScale = (float) (previewImageView.getHeight()) / (float) (photoBitmap.getHeight());
    ...
}

The only Crashlytics log I see is that the user leaves for the intent (I placed a Crashlytics log inside onPause). No log for onActivityResult, so my best guess is that onActivityResult is not called, thus my bitmap is not loaded, thus it will be null when the user presses next.

Question: why is onActivityResult called sometimes, and sometimes not? Are there any other possible causes of photoBitmap being null?

Xanthein answered 5/12, 2017 at 9:37 Comment(8)
The exception occures when the user navigates away from this screen to the next one. If it was due to the bitmap loading, we would detect that in onActivityResult as you can see in the code sample.Xanthein
Yes I am overriding it-Xanthein
If it was due to onBackPressed not working, I would see crashlytics log that onActivityResult was calledXanthein
photoBitmap.getHeight());. Do not use this code if photoBitmap==null. Thats all! Check for null before use.Thoron
That's really it? That sounds like a quick fix without knowing the root cause. There must be a reason it's null. I could detect it through crashyltics logs that onActivityResult is not called. Why is that?Xanthein
The root cause is the life cycle of your activity. Its partly recreated and hence your variable is not initialised.Thoron
I think it may due to the image size. Please check with small images and larger images(say > 8MB) and check whether you are getting the results. Also, check if any OOM is happening.Pseudohermaphroditism
You are getting the imageUri in onActivityResult, but you don't pass it into loadImage(). Could it be, that this causes the NPE?Perseus
C
1

You must add following code for taking images from devices

choosebtn.setOnClickListener(new View.OnClickListener() {
     @Override
     public void onClick(View v) {
         Intent i1=new Intent();
         i1.setType("image/*");
         i1.setAction(Intent.ACTION_GET_CONTENT);
         startActivityForResult(i1,1);
      }
});


@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if(requestCode == 1 && resultCode == RESULT_OK && data != null && data.getData() != null)
    {
        imguri=data.getData();
        mainpreview.setImageURI(data.getData());
    } else {
        Toast.makeText(getApplicationContext(),"please choose image",Toast.LENGTH_SHORT).show();
    }
}
Colorimeter answered 12/2, 2021 at 10:12 Comment(1)
Very strange question thread, This should be an accepted answer, but it doesn't have even one voteElery
B
-1

To start camera activity use this code

Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, CAMERA_REQUEST);

To get bitmap

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  super.onActivityResult(requestCode, resultCode, data);

  if(resultCode == Activity.RESULT_OK){
    if(requestCode==CAMERA_REQUEST) {
      Bitmap photo = (Bitmap) data.getExtras().get("data"); }
    }else{
      //Camera request cancelled
  }
}
Blindfish answered 3/1, 2018 at 10:17 Comment(0)
S
-1

Try this it worked perfect

     Intent i = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
            startActivityForResult(i, LOAD_IMAGE_RESULTS);

  @SuppressLint("Recycle")
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

           if (requestCode == LOAD_IMAGE_RESULTS && resultCode == RESULT_OK && data != null) {
                    // Let's read picked image data - its URI
                    Uri pickedImage = data.getData();

                    // Let's read picked image path using content resolver
                    String[] filePath = {MediaStore.Images.Media.DATA};
                    @SuppressLint("Recycle") Cursor cursor = null;
                    if (pickedImage != null) {
                        cursor = getContentResolver().query(pickedImage, filePath, null, null, null);
                    }
                    if (cursor != null) {
                        cursor.moveToFirst();

                        String imagePath = cursor.getString(cursor.getColumnIndex(filePath[0]));
      }
    }
}

now you can convert imagepath to bitmap

Strange answered 4/1, 2018 at 7:3 Comment(1)
What's the purpose of @SupressLint("Recycle")?Xanthein
C
-1

Call super.onActivityResult after your code last line of method. You've told android your done when you call the super.

Also I noticed your logging a char sequence. Don't do that Your not going to fix anything with this.

 Crashlytics.log("Data not received");

You need to save some data. Considered the user canceled because your code doesn't capture this.

/* assume log method has an int input */

Crashlytics.log("Data not received");
Crashlytics.log(requestCode);
Crashlytics.log(resultCode);
Century answered 4/1, 2018 at 17:41 Comment(4)
I don't want to fix anyhing with that log. Just wanted to find out which code pathes execute. If you read the question you see that I wrote: "The only Crashlytics log I see is that the user leaves for the intent (I placed a Crashlytics log inside onPause). No log for onActivityResult" You see? There is not a single log that would imply that onActivityResult was called.Xanthein
Yes I did read the question. You didn't show you logged when you started the intent. How can I believe a char sequence is enough to know the intent was finished.Century
I put a log in onPause. Couldn't find any other way to know if the intent was called. So fabric only reported one log: "User left screen" (which I print out in onpause). And after that the user presses next with a null photobitmap and the app crashes. No onActivityResult log.Xanthein
Why a null comes in. the user swipped away the photo chooser. The user was distracted by a notification or text message and left your app in the background. Or my favorite over two months later user has switched back to your app and here I. Seeing if you've got any further on this. Did you get the NPE figured out You could use kotlin its supposed to mask out the NPE. Consider moving the call to the super to the last line of code in the method.Century
Q
-1

Use this to select from gallery:

Intent i = new Intent(Intent.ACTION_PICK);
i.setType("image/*");
startActivityForResult(i, REQUEST_CODE);

Now u will get a callback in onActivityResult:

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch (requestCode) {
        case REQUEST_CODE:
            if (resultCode != RESULT_CANCELED) {
//use data to get the selected image
            }
            break;
    }
}
Quicken answered 7/1, 2018 at 18:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.