onActivityResult 返回 Intent data.getData();仅在棉花糖和棒棒糖中始终为空
Posted
技术标签:
【中文标题】onActivityResult 返回 Intent data.getData();仅在棉花糖和棒棒糖中始终为空【英文标题】:onActivityResult returning Intent data.getData(); always Null Only in Marshmallow and Lollipop 【发布时间】:2017-01-28 11:39:29 【问题描述】:阅读我的完整代码。它在除Marshmallow
和Lollipop
之外的所有电话上都能完美运行。在Marshmallow
和Lollipop
电话中,只有在图片已捕获 的情况下data.getData()
返回null
才会出现问题。如果我捕获 视频 就可以正常工作。我有 4 个案例 -
从图库中选择图片并在 Imageview
中显示其缩略图 - 工作正常。
从相机捕获图片并在Imageview
中显示其缩略图 - 在Marshmallow
和Lollipop
中不工作。
从图库中选择视频并在 Imageview
中显示其缩略图 - 工作正常。
3.Capturing Video from Camera and show its thumbnail in Imageview
- 工作正常。
现在有很多解决方案,但看起来都不令人满意,如果代码在视频捕获的情况下工作正常,那么为什么它不能用于图像捕获?是错误还是我在某个地方做错了?
这是我的代码。我已经评论了发生崩溃的一行-
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
super.onActivityResult(requestCode, resultCode, data);
int THUMBSIZE = 120;
switch (requestCode)
case RESULT_LOAD_IMAGE:
if (resultCode==RESULT_OK)
String column_Name= MediaStore.Images.Media.DATA;
String picturePath=getPath(column_Name,data.getData());
Bitmap orientedBitmap = ExifUtil.rotateBitmap(picturePath, BitmapFactory.decodeFile(picturePath));
Drawable fullpic=new BitmapDrawable(getResources(),ThumbnailUtils.extractThumbnail(orientedBitmap, THUMBSIZE, THUMBSIZE));
thumbnailview.setBackground(fullpic);
editText.setText(picturePath);
picker.setVisibility(View.VISIBLE);
thumbnailview.setClickable(false);
break;
case REQUEST_IMAGE_CAPTURE:
if (resultCode==RESULT_OK)
String picturePath="";
String column_Name=MediaStore.Images.Media.DATA;
picturePath=getPath(column_Name,data.getData());
//My app Crashes here because in Marshmallow data.getData() is always null.
Bitmap orientedBitmap = ExifUtil.rotateBitmap(picturePath, BitmapFactory.decodeFile(picturePath));
Drawable fullpic=new BitmapDrawable(getResources(),ThumbnailUtils.extractThumbnail(orientedBitmap, THUMBSIZE, THUMBSIZE));
thumbnailview.setBackground(fullpic);
editText.setText(picturePath);
picker.setVisibility(View.VISIBLE);
thumbnailview.setClickable(false);
break;
case RESULT_LOAD_VIDEO:
if (resultCode==RESULT_OK)
String column_Name=MediaStore.Video.Media.DATA;
String videoPath=getPath(column_Name,data.getData());
Drawable fullpic=new BitmapDrawable(getResources(),ThumbnailUtils.createVideoThumbnail(videoPath,MediaStore.Video.Thumbnails.MINI_KIND));
thumbnailview.setBackground(fullpic);
editText.setText(videoPath);
picker.setVisibility(View.VISIBLE);
thumbnailview.setClickable(false);
break;
case REQUEST_VIDEO_CAPTURE:
if (resultCode==RESULT_OK)
String column_Name=MediaStore.Video.Media.DATA;
String videoPath=getPath(column_Name,data.getData());
Drawable fullpic=new BitmapDrawable(getResources(),ThumbnailUtils.createVideoThumbnail(videoPath,MediaStore.Video.Thumbnails.MINI_KIND));
thumbnailview.setBackground(fullpic);
editText.setText(videoPath);
picker.setVisibility(View.VISIBLE);
thumbnailview.setClickable(false);
break;
if (picker != null)
picker.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
OpenDialog();
);
private String getPath(String column_Name,Uri uri)
String[] projection = column_Name;
String path = "";
Cursor cursor = getContentResolver().query(uri, projection, null, null, null);
int column_index_data ;
if (cursor != null)
column_index_data = cursor.getColumnIndexOrThrow(column_Name);
cursor.moveToFirst();
path = cursor.getString(column_index_data);
cursor.close();
return path;
private void OpenDialog()
dialogBox.setTitle("Select an Action");
dialogBox.setMessage("Choose Picture or Video");
dialogBox.setPositiveButton("Picture", new DialogInterface.OnClickListener()
@Override
public void onClick(DialogInterface dialog, int which)
if (check_Permissions())
OpenCameraDialog();
else
request_Permissions();
CAMERA_DIALOG_PERMISSION=1;
);
dialogBox.setNegativeButton("Video", new DialogInterface.OnClickListener()
@Override
public void onClick(DialogInterface dialog, int which)
if (check_Permissions())
OpenVideoDialog();
else
request_Permissions();
VIDEO_DIALOG_PERMISSION=1;
);
dialogBox.show();
private void OpenCameraDialog()
dialogBox.setTitle("Select an Action");
dialogBox.setMessage("Choose Picture From");
dialogBox.setPositiveButton("Gallery", new DialogInterface.OnClickListener()
@Override
public void onClick(DialogInterface dialog, int which)
final Intent galleryintent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(galleryintent, RESULT_LOAD_IMAGE);
);
dialogBox.setNegativeButton("Camera", new DialogInterface.OnClickListener()
@Override
public void onClick(DialogInterface dialog, int which)
final Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
);
dialogBox.show();
private void OpenVideoDialog()
dialogBox.setTitle("Select an Action");
dialogBox.setMessage("Choose Video From");
dialogBox.setPositiveButton("Gallery", new DialogInterface.OnClickListener()
@Override
public void onClick(DialogInterface dialog, int which)
final Intent galleryintent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Video.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(galleryintent, RESULT_LOAD_VIDEO);
);
dialogBox.setNegativeButton("Camera", new DialogInterface.OnClickListener()
@Override
public void onClick(DialogInterface dialog, int which)
final Intent takeVideoIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
if (takeVideoIntent.resolveActivity(getPackageManager()) != null)
startActivityForResult(takeVideoIntent, REQUEST_VIDEO_CAPTURE);
);
dialogBox.show();
private boolean check_Permissions()
boolean GRANTED;
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) +
ContextCompat.checkSelfPermission(this,Manifest.permission.READ_EXTERNAL_STORAGE) +
ContextCompat.checkSelfPermission(this,Manifest.permission.RECORD_AUDIO) +
ContextCompat.checkSelfPermission(this,Manifest.permission.CAMERA)!= PackageManager.PERMISSION_GRANTED)
GRANTED=false;
else
GRANTED=true;
return GRANTED;
private void request_Permissions()
ActivityCompat.requestPermissions(this,
new String[]Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.CAMERA,Manifest.permission.RECORD_AUDIO,
REQUEST_FOR_PERMISSION);
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode)
case REQUEST_FOR_PERMISSION:
if ((grantResults.length>0)&& (grantResults[0] +grantResults[1]+grantResults[2]+grantResults[3]== PackageManager.PERMISSION_GRANTED))
if (CAMERA_DIALOG_PERMISSION==1)
OpenCameraDialog();
CAMERA_DIALOG_PERMISSION=0;
else if (VIDEO_DIALOG_PERMISSION==1)
OpenVideoDialog();
VIDEO_DIALOG_PERMISSION=0;
else
Toast.makeText(this, "Please GRANT Permissions", Toast.LENGTH_SHORT).show();
【问题讨论】:
【参考方案1】:当我们将在 android 中从相机捕获图像时,Uri
或 data.getdata()
为空。我们有两种解决方案来解决这个问题。
-
我们可以从Bitmap Image中获取Uri路径
我们可以从光标处获取 Uri 路径。
我将在这里实现所有方法,请仔细阅读:-
首先我将讲述如何从位图图像中获取 Uri: 完整代码为:
首先,我们将通过 Intent 捕获图像,这两种方法都相同,所以这段代码我只在这里写一次:
// Capture Image
captureImg.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View view)
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (intent.resolveActivity(getPackageManager()) != null)
startActivityForResult(intent, reqcode);
);
现在我们将实现 OnActivityResult :-(这对于上述两种方法都是一样的):-
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
super.onActivityResult(requestCode, resultCode, data);
if(requestCode==reqcode && resultCode==RESULT_OK)
Bitmap photo = (Bitmap) data.getExtras().get("data");
ImageView.setImageBitmap(photo);
// CALL THIS METHOD TO GET THE URI FROM THE BITMAP
Uri tempUri = getImageUri(getApplicationContext(), photo);
\\ Show Uri path based on Image
Toast.makeText(LiveImage.this,"Here "+ tempUri, Toast.LENGTH_LONG).show();
\\ Show Uri path based on Cursor Content Resolver
Toast.makeText(this, "Real path for URI : "+getRealPathFromURI(tempUri), Toast.LENGTH_SHORT).show();
else
Toast.makeText(this, "Failed To Capture Image", Toast.LENGTH_SHORT).show();
\现在我们将创建上述所有方法,通过类从 Image 和 Cursor 方法创建 Uri:
现在位图图像的 URI 路径
private Uri getImageUri(Context applicationContext, Bitmap photo)
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
photo.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
String path = MediaStore.Images.Media.insertImage(LiveImage.this.getContentResolver(), photo, "Title", null);
return Uri.parse(path);
\Uri from Real path of saved image
public String getRealPathFromURI(Uri uri)
Cursor cursor = getContentResolver().query(uri, null, null, null, null);
cursor.moveToFirst();
int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
return cursor.getString(idx);
亲爱的朋友复制并粘贴此代码,然后尝试理解。 如果您正在制作企业应用程序,我 100% 肯定这对您来说会更好。 如果你喜欢我的代码,那就投票给我吧......
【讨论】:
【参考方案2】:它在除棉花糖和棒棒糖之外的所有手机上都能完美运行
不,不是。当用户选择一个编写良好的相机应用程序来处理您的ACTION_IMAGE_CAPTURE
请求时,它会在许多 Android 版本上失败。
你的问题在这里:
if (data.getData()!=null)
picturePath=getPath(column_Name,data.getData());
else
//My app Crashes here because in Marshmallow data.getData() is always null.
这里至少有两个缺陷。
最重要的是假设您从ACTION_IMAGE_CAPTURE
收到Uri
。 That is not documented,相机应用不需要返回Uri
。特别是,在您的结构中,您只能通过getExtra("data")
获得缩略图。如果您想要全尺寸图像,请在您的Intent
上使用EXTRA_OUTPUT
,在这种情况下,您知道图像的存储位置——它就是您在EXTRA_OUTPUT
中指示的位置。
另一个是您假设您返回的Uri
来自MediaStore
或者具有MediaStore.Video.Media.DATA
列。不仅相机应用不必返回Uri
,而且不要求Uri
来自MediaStore
或有这样的列。
【讨论】:
现在看到我已经更新了我的代码我没有使用 if else .. 我发错了对不起 我应该在 putExtra 和 EXTRA OUTPUT 中传递什么? @CommonsWare @KarandeepAtwal:理想情况下,使用由ContentProvider
支持的Uri
。您可以使用 file:
Uri
,但这不适用于具有 24+ 的 targetSdkVersion
的 Android 7.0+。有关示例,请参见 this sample project。
你能解释一下吗?只是我想获取我捕获的图像的路径。如果路径已知,我知道如何获取缩略图。
@KarandeepAtwal:“我只想获取我捕获的图像的路径”——然后您必须通过EXTRA_OUTPUT
提供您希望相机应用程序使用的Uri
。这在the documentation、books 等中都有介绍。但是,请记住ACTION_IMAGE_CAPTURE
is not reliable,因为相机应用程序开发人员似乎没有对它进行太多测试。【参考方案3】:
正如@CommonsWare 建议的那样 -
相机应用不需要返回uri。
还有,
您需要告诉相机应用在哪里写入图像。
所以,我用-替换了我的代码
final Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
pictureUri=getOutputMediaFileUri(MEDIA_TYPE_IMAGE);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,pictureUri);
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
在onActivityResult
-
case REQUEST_IMAGE_CAPTURE:
if (resultCode==RESULT_OK)
String picturePath="";
String column_Name= MediaStore.Images.Media.DATA;
if (data!=null)
if (data.getData()!=null)
picturePath=getPathfromUri(column_Name,data.getData());
else
picturePath= pictureUri.getPath();
else
picturePath= pictureUri.getPath();
【讨论】:
【参考方案4】:你可以从 Bitmap 中获取 Uri
private Uri getImageUri(Context applicationContext, Bitmap bitmapImage)
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
photo.compress(Bitmap.CompressFormat.PNG, 100, bytes);
String path = MediaStore.Images.Media.insertImage(MainActivity.this.getContentResolver(), bitmapImage, "Some Title", null);
return Uri.parse(path);
protected void onActivityResult(int requestCode, int resultCode, Intent data)
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK)
if (requestCode==CAPTURE_IMAGE_CODE)
Bitmap bitmapImage = (Bitmap) data.getExtras().get("data");
//ImageView.setImageBitmap(photo);
Uri inputImageUri = getImageUri(getApplicationContext(),bitmapImage);
并添加调用这个 onClick
private void takeImage()
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (intent.resolveActivity(getPackageManager()) != null)
startActivityForResult(intent, CAPTURE_IMAGE_CODE);
【讨论】:
以上是关于onActivityResult 返回 Intent data.getData();仅在棉花糖和棒棒糖中始终为空的主要内容,如果未能解决你的问题,请参考以下文章
onActivityResult 从相机返回,Intent null