在 ACTION_GET_CONTENT 意图之后有时不会调用 OnActivityResult
Posted
技术标签:
【中文标题】在 ACTION_GET_CONTENT 意图之后有时不会调用 OnActivityResult【英文标题】:OnActivityResult sometimes not called after ACTION_GET_CONTENT intent 【发布时间】:2018-05-18 22:01:17 【问题描述】:我正在开发一个图像编辑 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");
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 为空。
@OnClick(R.id.toolbar_next)
void onToolbarNextClick()
float originalScale = (float) (previewImageView.getHeight()) / (float) (photoBitmap.getHeight());
...
我看到的唯一 Crashlytics 日志是用户离开的意图(我在 onPause
中放置了一个 Crashlytics 日志)。 onActivityResult
没有日志,所以我最好的猜测是 onActivityResult
没有被调用,因此我的位图没有加载,因此当用户按下下一步时它将为空。
问题:为什么有时会调用onActivityResult
,有时不调用? photoBitmap
为空还有其他可能的原因吗?
【问题讨论】:
当用户从这个屏幕导航到下一个屏幕时会发生异常。如果是由于位图加载,我们会在 onActivityResult 中检测到,正如您在代码示例中看到的那样。 是的,我正在覆盖它- 如果是由于 onBackPressed 不起作用,我会看到调用 onActivityResult 的 crashlytics 日志photoBitmap.getHeight());
。如果photoBitmap==null
,请勿使用此代码。就这样!使用前检查是否为空。
真的是这样吗?这听起来像是在不知道根本原因的情况下快速解决问题。一定有它为空的原因。我可以通过没有调用 onActivityResult 的 crashyltics 日志检测到它。这是为什么呢?
【参考方案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();
【讨论】:
很奇怪的问题线程,这应该是一个可以接受的答案,但它甚至没有一票【参考方案2】:试试这个,效果很好
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") 的目的是什么?【参考方案3】:在您的代码最后一行方法之后调用super.onActivityResult
。当你调用 super 时,你已经告诉 android 你已经完成了。
我还注意到您记录了一个字符序列。不要那样做你不会用这个来解决任何问题。
Crashlytics.log("Data not received");
您需要保存一些数据。考虑到用户取消了,因为您的代码没有捕捉到这一点。
/* 假设 log 方法有一个 int 输入 */
Crashlytics.log("Data not received");
Crashlytics.log(requestCode);
Crashlytics.log(resultCode);
【讨论】:
我不想用那个日志来修复任何东西。只是想找出执行哪些代码路径。如果您阅读问题,您会看到我写道:“我看到的唯一 Crashlytics 日志是用户离开的意图(我在 onPause 中放置了 Crashlytics 日志)。没有 onActivityResult 的日志”你看到了吗?没有一条日志暗示 onActivityResult 已被调用。 是的,我确实阅读了这个问题。当您开始意图时,您没有显示您已登录。我怎么能相信一个字符序列就足以知道意图已经完成了。 我在 onPause 中输入了一个日志。找不到任何其他方法来知道是否调用了意图。所以织物只报告了一个日志:“用户左屏”(我在暂停时打印出来)。之后,用户使用空照片位图按下下一步,应用程序崩溃。没有 onActivityResult 日志。 为什么会出现空值。用户刷掉了照片选择器。用户被通知或短信分散了注意力,并将您的应用程序留在了后台。或者两个多月后我最喜欢的用户切换回你的应用程序,我在这里。看看你是否对此有进一步的了解。您是否弄清楚了 NPE 您可以使用 kotlin 来掩盖 NPE。考虑将对 super 的调用移至方法中的最后一行代码。【参考方案4】:使用它从图库中选择:
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;
【讨论】:
【参考方案5】:要启动相机活动,请使用此代码
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
【讨论】:
以上是关于在 ACTION_GET_CONTENT 意图之后有时不会调用 OnActivityResult的主要内容,如果未能解决你的问题,请参考以下文章
获取图像的 ACTION_GET_CONTENT 返回空 URI