android从图库中选择图像


196

我想从图库中创建图片选择器。我使用代码

 intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
 startActivityForResult(intent, TFRequestCodes.GALLERY);

我的问题是在此活动中显示了视频文件。有没有办法过滤显示的文件,以便在此活动中不显示视频文件?


3
本文很好地描述了如何从图库中选取图像:androidbitmaps.blogspot.com/2015/04/…–
Andy Res

像你一样有一个类似的问题。 stackoverflow.com/a/31382240/1835650
TeeTracker

Answers:


343

绝对。试试这个:

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

也不要忘记创建常量PICK_IMAGE,这样您就可以识别用户何时从图库活动回来:

public static final int PICK_IMAGE = 1;

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
    if (requestCode == PICK_IMAGE) {
        //TODO: action
    }
}

这就是我所谓的图片库。放入并查看它是否适合您。

编辑:

这将打开“文档”应用程序。要允许用户还使用他们可能已安装的任何图库应用程序:

    Intent getIntent = new Intent(Intent.ACTION_GET_CONTENT);
    getIntent.setType("image/*");

    Intent pickIntent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    pickIntent.setType("image/*");

    Intent chooserIntent = Intent.createChooser(getIntent, "Select Image");
    chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent[] {pickIntent});

    startActivityForResult(chooserIntent, PICK_IMAGE);

6
我在“ Android系统”,“文档”上有2个选项。如果我选择Android System,那么它将向我显示图库和照片。如何摆脱这个中间选项列表?
Uday

4
@Uday仅仅是因为您没有设置默认值。放开它:)
Tristan Wiley

13
必须将PICK_IMAGE常数设置为什么?它说“无法解析符号“ PICK_IMAGE”
迈克尔

3
@Michael PICK_IMAGE常量保存您在此类上确定的任何静态int值,该值在@Override函数上进一步使用onActivityResult(int requestCode, resultCode, Intent data),建议您requestCode在执行任何操作之前使用此常量检查参数:)
Gabriel Checchia Vitali

您可以使用以下代码(假设为RESULT_OK)从onActivityResult(...)方法中检索位图:位图bitmap = data.getExtras()。getParcelable(“ data”);
Shn_Android_Dev '18

196

有时,您无法从所选图片中获取文件。这是因为选择的一个来自Google+,云端硬盘,Dropbox或任何其他提供商。

最好的解决方案是要求系统通过Intent.ACTION_GET_CONTENT选择内容,并通过内容提供程序获取结果。

您可以按照下面的代码或查看我更新的要点

public void pickImage() {
  Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
  intent.setType("image/*");
  startActivityForResult(intent, PICK_PHOTO_FOR_AVATAR);
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == PICK_PHOTO_FOR_AVATAR && resultCode == Activity.RESULT_OK) {
        if (data == null) {
            //Display an error
            return;
        }
        InputStream inputStream = context.getContentResolver().openInputStream(data.getData());
        //Now you can do whatever you want with your inpustream, save it as file, upload to a server, decode a bitmap...
    }
}

14
if(resultCode == Activity.RESULT_OK) {...}可以用来检测成功/取消
Thamme Gowda 2014年

你怎么走?
2015年

@delive,我想您可以尝试new File(data.getData()).getAbsolutePath()只是一个猜测,我还没有尝试过
某处某人2015年

1
Android Studio中的片段中的FileNotFound异常警告getActivity().getContentResolver().openInputStream(data.getData());
Iqbal

1
这在某些不返回文件路径的设备上有效。但是,一旦有了InputStream,我就无法确定如何确定图像的方向。
Casey Perkins '02

30
public void FromCamera() {

    Log.i("camera", "startCameraActivity()");
    File file = new File(path);
    Uri outputFileUri = Uri.fromFile(file);
    Intent intent = new Intent(
            android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
    intent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
    startActivityForResult(intent, 1);

}

public void FromCard() {
    Intent i = new Intent(Intent.ACTION_PICK,
            android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    startActivityForResult(i, 2);
}

 protected void onActivityResult(int requestCode, int resultCode, Intent data) {

    super.onActivityResult(requestCode, resultCode, data);

    if (requestCode == 2 && resultCode == RESULT_OK
            && null != data) {

        Uri selectedImage = data.getData();
        String[] filePathColumn = { MediaStore.Images.Media.DATA };

        Cursor cursor = getContentResolver().query(selectedImage,
                filePathColumn, null, null, null);
        cursor.moveToFirst();

        int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
        String picturePath = cursor.getString(columnIndex);
        cursor.close();

        bitmap = BitmapFactory.decodeFile(picturePath);
        image.setImageBitmap(bitmap);

        if (bitmap != null) {
            ImageView rotate = (ImageView) findViewById(R.id.rotate);

        }

    } else {

        Log.i("SonaSys", "resultCode: " + resultCode);
        switch (resultCode) {
        case 0:
            Log.i("SonaSys", "User cancelled");
            break;
        case -1:
            onPhotoTaken();
            break;

        }

    }

}

protected void onPhotoTaken() {
    // Log message
    Log.i("SonaSys", "onPhotoTaken");
    taken = true;
    imgCapFlag = true;
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inSampleSize = 4;
    bitmap = BitmapFactory.decodeFile(path, options);
    image.setImageBitmap(bitmap);


}

非常感谢你。这个答案让我上传的图片以后
罗萨里奥·佩雷拉·费尔南德斯

我猜你是说情况1:而不是情况-1:在OnActivityResult的开关中。
Mathias

我知道这是一个新问题,但是,为什么我们要做所有这些事情以获得图片路径,那么data.getData返回什么呢?
moumenShobakey

的值是path多少?于File file = new File(path);
拉维·瓦尼亚

23

您可以使用此方法从图库中选择图像。仅显示图像。

public void pickImage() {
    Intent intent = new Intent(Intent.ACTION_PICK,
            MediaStore.Images.Media.INTERNAL_CONTENT_URI);
    intent.setType("image/*");
    intent.putExtra("crop", "true");
    intent.putExtra("scale", true);
    intent.putExtra("outputX", 256);
    intent.putExtra("outputY", 256);
    intent.putExtra("aspectX", 1);
    intent.putExtra("aspectY", 1);
    intent.putExtra("return-data", true);
    startActivityForResult(intent, 1);
}

并将onActivityResult覆盖为

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode != RESULT_OK) {
            return;
        }
        if (requestCode == 1) {
            final Bundle extras = data.getExtras();
            if (extras != null) {
                //Get image
                Bitmap newProfilePic = extras.getParcelable("data");
            }
        }
    }

2
@Abhishek ...您在哪里找到了ACTION_PICK意图允许的其他功能清单?谢谢!
约翰尼·吴

1
请不要忘记为api级别23及更高版本添加READ_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAGE的运行时权限。否则,您可能无法从图库中获得不为null的位图。请参阅stackoverflow.com/a/35285667/3341089
oguzhan,

1
设置URI后调用setType将清除数据。
Taslim Oseni

11

这是请求权限(如果需要)的完整示例,从图库中选择图片,然后将图片转换为bitmapfile

AndroidManifesh.xml

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

活动

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        button_pick_image.setOnClickListener {
            pickImage()
        }
    }

    private fun pickImage() {
        if (ActivityCompat.checkSelfPermission(this, READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
            val intent = Intent(
                Intent.ACTION_PICK,
                MediaStore.Images.Media.INTERNAL_CONTENT_URI
            )
            intent.type = "image/*"
            intent.putExtra("crop", "true")
            intent.putExtra("scale", true)
            intent.putExtra("aspectX", 16)
            intent.putExtra("aspectY", 9)
            startActivityForResult(intent, PICK_IMAGE_REQUEST_CODE)
        } else {
            ActivityCompat.requestPermissions(
                this,
                arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE),
                READ_EXTERNAL_STORAGE_REQUEST_CODE
            )
        }
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (requestCode == PICK_IMAGE_REQUEST_CODE) {
            if (resultCode != Activity.RESULT_OK) {
                return
            }
            val uri = data?.data
            if (uri != null) {
                val imageFile = uriToImageFile(uri)
                // todo do something with file
            }
            if (uri != null) {
                val imageBitmap = uriToBitmap(uri)
                // todo do something with bitmap
            }
        }
    }

    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        when (requestCode) {
            READ_EXTERNAL_STORAGE_REQUEST_CODE -> {
                if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    // pick image after request permission success
                    pickImage()
                }
            }
        }
    }

    private fun uriToImageFile(uri: Uri): File? {
        val filePathColumn = arrayOf(MediaStore.Images.Media.DATA)
        val cursor = contentResolver.query(uri, filePathColumn, null, null, null)
        if (cursor != null) {
            if (cursor.moveToFirst()) {
                val columnIndex = cursor.getColumnIndex(filePathColumn[0])
                val filePath = cursor.getString(columnIndex)
                cursor.close()
                return File(filePath)
            }
            cursor.close()
        }
        return null
    }

    private fun uriToBitmap(uri: Uri): Bitmap {
        return MediaStore.Images.Media.getBitmap(this.contentResolver, uri)
    }

    companion object {
        const val PICK_IMAGE_REQUEST_CODE = 1000
        const val READ_EXTERNAL_STORAGE_REQUEST_CODE = 1001
    }
}

演示
https://github.com/PhanVanLinh/AndroidPickImage


这无非是一个库,尤其是具有裁剪和宽高比功能的库。我从来不知道这样的事情存在。先生非常感谢您。
Lalit Fauzdar

1
回到这里,还不如我希望看到的第一印象。使用snapseed编辑时不会选择图像,没有崩溃但没有图像,在编辑后单击“下一步”时,华为的默认图库应用程序不执行任何操作,从Google照片中选择图像时,它不会编辑图像,将其带回没有它直接。仅当我选择huawei的默认图库和google照片进行编辑时,它才有效。
Lalit Fauzdar


1

根据文档,仅向API最低19岁的用户提供答案的更新:

在Android 4.4(API级别19)及更高版本上,您还可以使用ACTION_OPEN_DOCUMENT意向,该附加意向显示系统控制的选择器UI,该用户界面受控制,允许用户浏览其他应用程序提供的所有文件。用户可以通过单个UI从任何受支持的应用中选择文件。

在Android 5.0(API级别21)及更高版本上,您还可以使用ACTION_OPEN_DOCUMENT_TREE意图,该意图允许用户选择客户端应用程序可以访问的目录。

使用存储访问框架打开文件-Android文档

     val intent = Intent(Intent.ACTION_OPEN_DOCUMENT)
     intent.type = "image/*"
     startActivityForResult(intent, PICK_IMAGE_REQUEST_CODE)

0

对于仅从本地选择,请添加以下内容:

        i.putExtra(Intent.EXTRA_LOCAL_ONLY,true)

这工作很好:

    val i = Intent(Intent.ACTION_GET_CONTENT,MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
    i.type = "image/*"
    i.putExtra(Intent.EXTRA_LOCAL_ONLY,true)
    startActivityForResult(Intent.createChooser(i,"Select Photo"),pickImageRequestCode)

-7

你可以比这个答案更容易做到:

Uri Selected_Image_Uri = data.getData();
ImageView imageView = (ImageView) findViewById(R.id.loadedimg);
imageView.setImageURI(Selected_Image_Uri);

我做到了,它奏效了。如果您需要将文件发送到服务器(例如,发送到服务器),则必须使用其他方式,但是仅要将图像加载到imageview,您可以执行此简单的解决方案。
Alireza Taghizadeh 2015年

5
欢迎来到SO!除了评论自己的帖子,您还可以编辑自己的帖子。如果您的评论应该解释答案,那么为什么不将其放入答案本身呢?就我个人而言,我看不出您对这个旧问题的(最新)答案与该问题有何关系。我是否可以建议首先专注于回答尚未被接受的问题?
cfi

1
我找不到android问题。我怎样才能看到Android问题?
Alireza Taghizadeh,2015年

3
请阅读帮助页面。另外,评论不用于讨论该站点的工作方式,您可以使用聊天室与其他用户进行实时讨论,还可以在Meta(help-> Meta)
cfi上
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.