如何从图库(SD 卡)中为我的应用程序选择图像?
这个问题最初是针对 Android 1.6 提出的。
我正在研究我的应用程序中的照片选项。
我的 Activity 中有一个按钮和一个 ImageView。当我单击该按钮时,它将重定向到图库,我将能够选择图像。所选图像将出现在我的 ImageView 中。
This question was originally asked for Android 1.6.
I am working on photos options in my app.
I have a button and an ImageView in my Activity. When I click the button it would redirect to the gallery and I would be able to select an image. The selected image would appear in my ImageView.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
更新答案,近 5 年后:
原始答案中的代码不再可靠地工作,因为来自不同来源的图像有时会返回不同的内容 URI,即
content://
而不是file ://。更好的解决方案是简单地使用 context.getContentResolver().openInputStream(intent.getData())
,因为它将返回一个您可以根据需要进行处理的 InputStream。例如,
BitmapFactory.decodeStream()
在这种情况下可以完美工作,因为您还可以使用 Options 和 inSampleSize 字段对大图像进行下采样并避免内存问题。然而,像 Google Drive 这样的东西会返回尚未实际下载的图像的 URI。因此,您需要在后台线程上执行 getContentResolver() 代码。
原始答案:
其他答案解释了如何发送意图,但没有很好地解释如何处理响应。以下是有关如何执行此操作的一些示例代码:
在此之后,您已将选定的图像存储在“yourSelectedImage”中以执行您想要的任何操作。此代码的工作原理是获取 ContentResolver 数据库中图像的位置,但这本身还不够。每张图像都有大约 18 列信息,从文件路径到“上次修改日期”再到拍摄照片的 GPS 坐标,尽管许多字段实际上并未使用。
为了节省时间,因为您实际上不需要其他字段,光标搜索是通过过滤器完成的。该过滤器的工作原理是指定所需列的名称 MediaStore.Images.Media.DATA(即路径),然后将该 string[] 提供给游标查询。游标查询会返回路径,但在使用
columnIndex
代码之前您不知道它位于哪一列。这只是根据列名获取列号,与过滤过程中使用的列号相同。完成后,您终于可以使用我给出的最后一行代码将图像解码为位图。Updated answer, nearly 5 years later:
The code in the original answer no longer works reliably, as images from various sources sometimes return with a different content URI, i.e.
content://
rather thanfile://
. A better solution is to simply usecontext.getContentResolver().openInputStream(intent.getData())
, as that will return an InputStream that you can handle as you choose.For example,
BitmapFactory.decodeStream()
works perfectly in this situation, as you can also then use the Options and inSampleSize field to downsample large images and avoid memory problems.However, things like Google Drive return URIs to images which have not actually been downloaded yet. Therefore you need to perform the getContentResolver() code on a background thread.
Original answer:
The other answers explained how to send the intent, but they didn't explain well how to handle the response. Here's some sample code on how to do that:
After this, you've got the selected image stored in "yourSelectedImage" to do whatever you want with. This code works by getting the location of the image in the ContentResolver database, but that on its own isn't enough. Each image has about 18 columns of information, ranging from its filepath to 'date last modified' to the GPS coordinates of where the photo was taken, though many of the fields aren't actually used.
To save time as you don't actually need the other fields, cursor search is done with a filter. The filter works by specifying the name of the column you want, MediaStore.Images.Media.DATA, which is the path, and then giving that string[] to the cursor query. The cursor query returns with the path, but you don't know which column it's in until you use the
columnIndex
code. That simply gets the number of the column based on its name, the same one used in the filtering process. Once you've got that, you're finally able to decode the image into a bitmap with the last line of code I gave.启动意图
处理结果
或者,您也可以对图像进行缩减采样以避免内存不足错误。
Start intent
Process result
Alternatively, you can also downsample your image to avoid OutOfMemory errors.
您必须启动画廊意图才能获得结果。
然后在
onActivityForResult
中,调用intent.getData()
获取Image的Uri。然后您需要从ContentProvider获取图像。You have to start the gallery intent for a result.
Then in
onActivityForResult
, callintent.getData()
to get the Uri of the Image. Then you need to get the Image from the ContentProvider.这是经过测试的图像和视频代码。它也适用于小于 19 和大于 19 的所有 API。
图片:
视频:
.
Here is a tested code for image and video.It will work for all APIs less than 19 and greater than 19 as well.
Image:
Video:
.
执行此操作可启动图库并允许用户选择图像:
然后在
onActivityResult()
中使用返回的图像的 URI 在 ImageView 上设置图像。Do this to launch the gallery and allow the user to pick an image:
Then in your
onActivityResult()
use the URI of the image that is returned to set the image on your ImageView.由于某些原因,此线程中的所有答案,在
onActivityResult()
中尝试对收到的Uri
进行后处理,例如获取图像的真实路径,然后使用BitmapFactory.decodeFile(path)
获取Bitmap
。这一步是不必要的。
ImageView
类有一个名为setImageURI(uri)
的方法。将您的 uri 传递给它,您就应该完成了。对于完整的工作示例,您可以在这里查看: http://androidbitmaps.blogspot.com/2015/04/loading-images-in-android-part-iii-pick.html
PS:
在要加载的图像太大而无法放入内存的情况下,将位图放在单独的变量中是有意义的,并且需要进行缩小操作来防止
OurOfMemoryError
,如 @siamii 答案所示。For some reasons, all of the answers in this thread, in
onActivityResult()
try to post-process the receivedUri
, like getting the real path of the image and then useBitmapFactory.decodeFile(path)
to get theBitmap
.This step is unnecessary. The
ImageView
class has a method calledsetImageURI(uri)
. Pass your uri to it and you should be done.For a complete working example you could take a look here: http://androidbitmaps.blogspot.com/2015/04/loading-images-in-android-part-iii-pick.html
PS:
Getting the
Bitmap
in a separate variable would make sense in cases where the image to be loaded is too large to fit in memory, and a scale down operation is necessary to preventOurOfMemoryError
, like shown in the @siamii answer.调用 ChooseImage 方法,例如 -
call chooseImage method like-