在使用ACTION_GET_CONTENT意图后,OnActivityResult有时不会被调用

39

我正在开发一款图片编辑的Android应用程序。在我的一个活动中,我会在 onCreate() 方法中调用一个意图来从相册中选择一张图片,就像这样:

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

然后我收到了这样的数据:

@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");
    }
}
< p > loadImage 方法:

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;
}

现在我的问题是,有时我在Crashlytics中看到NPE-s,提示当用户按下下一个按钮时photoBitmap为 null。

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

我只看到一个Crashlytics日志,即用户离开意图(我在onPause中放置了一个Crashlytics日志)。没有onActivityResult的日志,因此我的最佳猜测是onActivityResult未被调用,因此我的位图未加载,因此当用户按下下一步时,它将为null。

问题:为什么有时会调用onActivityResult,有时不会?photoBitmap为空的其他可能原因有哪些?


当用户从此屏幕导航到下一个屏幕时,异常会发生。如果是由于位图加载引起的,我们将在代码示例中的onActivityResult中检测到它。 - WPMed
是的,我正在覆盖它。 - WPMed
如果是由于onBackPressed无法工作,我会看到Crashlytics日志记录了调用了onActivityResult。 - WPMed
请在使用前检查是否为null,不要使用此代码如果 photoBitmap==null。只有这些了! - greenapps
那真的是这样吗?在不知道根本原因的情况下,这听起来像是一个快速修复。一定有一个原因导致它为空。我可以通过 Crashyltics 日志检测到 onActivityResult 没有被调用。为什么会这样? - WPMed
显示剩余3条评论
5个回答

1
您需要添加以下代码来从设备中获取图像。
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();
    }
}

非常奇怪的问题线程,这应该是一个被接受的答案,但它甚至没有一个投票。 - Samuel Owino

-1

在方法的最后一行调用super.onActivityResult。当你调用super时,你告诉Android你已经完成了。

另外我注意到你正在记录字符序列。不要这样做,这并不能解决任何问题。

 Crashlytics.log("Data not received");

你需要保存一些数据。要考虑到用户取消操作,因为你的代码没有捕获这种情况。

/* 假设日志方法有一个整数输入 */

Crashlytics.log("Data not received");
Crashlytics.log(requestCode);
Crashlytics.log(resultCode);

我不想通过那个日志来修复任何东西。我只是想找出哪些代码路径被执行了。如果你读了问题,你会发现我写道:“我看到的唯一的Crashlytics日志是用户离开意图(我在onPause中放置了一个Crashlytics日志)。没有关于onActivityResult的日志。” 你看到了吗?没有一个日志表明已调用onActivityResult。 - WPMed
是的,我确实看了这个问题。您没有展示您在启动意图时所记录的内容。 我怎么能相信一个字符序列足以知道意图是否已完成呢? - danny117
我在onPause中放置了一个日志。找不到其他方法来知道是否调用了意图。因此,fabric仅报告了一个日志:“用户离开屏幕”(我在onpause中打印出来)。之后,用户使用空的photobitmap按下下一步按钮,应用程序崩溃了。没有onActivityResult日志。 - WPMed
为什么会出现 null 呢?用户划掉了照片选择器。用户被通知或短信分心,离开了你的应用程序。或者两个月后,用户重新回到你的应用程序,我在这里看看你是否有进一步的进展。你解决了 NPE 吗?你可以使用 Kotlin 来屏蔽 NPE。考虑将调用超类的代码移动到方法的最后一行。 - danny117

-1

使用此功能从图库中选择:

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

现在你将在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;
    }
}

-1

使用以下代码启动相机活动

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

获取位图
@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
  }
}

-1

试试这个,它完美地工作了。

     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]));
      }
    }
}

现在你可以将imagepath转换为位图


"@SupressLint("Recycle")" 的目的是什么? - WPMed

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接