Android 如何从gallery(SD卡)中为我的应用选择图像?

Android 如何从gallery(SD卡)中为我的应用选择图像?,android,android-image,android-gallery,Android,Android Image,Android Gallery,这个问题最初是针对Android 1.6提出的 我正在使用我的应用程序中的照片选项 我的活动中有一个按钮和一个ImageView。当我点击按钮,它将重定向到画廊,我将能够选择一个图像。所选图像将显示在my ImageView中 您必须启动gallery intent以获得结果 Intent i = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONT

这个问题最初是针对Android 1.6提出的

我正在使用我的应用程序中的照片选项


我的活动中有一个按钮和一个ImageView。当我点击按钮,它将重定向到画廊,我将能够选择一个图像。所选图像将显示在my ImageView中

您必须启动gallery intent以获得结果

Intent i = new Intent(Intent.ACTION_PICK,
               android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(i, ACTIVITY_SELECT_IMAGE); 

然后在onActivityForResult中调用
intent.getData()
获取图像的Uri。然后您需要从ContentProvider获取图像。

执行此操作以启动gallery并允许用户选择图像:

Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
startActivityForResult(intent, IMAGE_PICK);

然后在您的
onActivityResult()
中,使用返回的图像的URI在ImageView上设置图像。

近5年后更新了答案:

原始答案中的代码不再可靠,因为来自不同来源的图像有时返回不同的内容URI,即
content://
而不是
file://
。更好的解决方案是简单地使用
context.getContentResolver().openInputStream(intent.getData())
,因为这将返回一个您可以选择处理的InputStream

例如,
BitmapFactory.decodeStream()
在这种情况下工作得非常好,因为您还可以使用Options和inSampleSize字段来减少对大型图像的采样并避免内存问题

然而,像GoogleDrive这样的东西会将URI返回到实际上尚未下载的图像中。因此,需要在后台线程上执行getContentResolver()代码


原始答复:

其他答案解释了如何发送意图,但没有很好地解释如何处理响应。下面是一些关于如何做到这一点的示例代码:

protected void onActivityResult(int requestCode, int resultCode, 
       Intent imageReturnedIntent) {
    super.onActivityResult(requestCode, resultCode, imageReturnedIntent); 

    switch(requestCode) { 
    case REQ_CODE_PICK_IMAGE:
        if(resultCode == RESULT_OK){  
            Uri selectedImage = imageReturnedIntent.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 filePath = cursor.getString(columnIndex);
            cursor.close();


            Bitmap yourSelectedImage = BitmapFactory.decodeFile(filePath);
        }
    }
}
在此之后,您已将所选图像存储在“yourSelectedImage”中,以便对其执行任何操作。这段代码通过获取ContentResolver数据库中图像的位置来工作,但仅凭此还不够。每幅图像都有大约18列信息,从文件路径到“上次修改日期”,再到照片拍摄地点的GPS坐标,尽管许多字段实际上没有被使用

为了节省时间,因为您实际上不需要其他字段,光标搜索是通过过滤器完成的。过滤器的工作方式是指定所需列的名称MediaStore.Images.Media.DATA(即路径),然后将该字符串[]指定给游标查询。游标查询返回路径,但在使用
columnIndex
代码之前,您不知道它位于哪个列中。它只是根据列的名称获取列的编号,与过滤过程中使用的名称相同。一旦你得到了,你最终能够用我给出的最后一行代码将图像解码成位图

private static final int SELECT_PHOTO = 100;
启动意图

Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
photoPickerIntent.setType("image/*");
startActivityForResult(photoPickerIntent, SELECT_PHOTO);    
过程结果

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent imageReturnedIntent) { 
    super.onActivityResult(requestCode, resultCode, imageReturnedIntent); 

    switch(requestCode) { 
    case SELECT_PHOTO:
        if(resultCode == RESULT_OK){  
            Uri selectedImage = imageReturnedIntent.getData();
            InputStream imageStream = getContentResolver().openInputStream(selectedImage);
            Bitmap yourSelectedImage = BitmapFactory.decodeStream(imageStream);
        }
    }
}
或者,您也可以对图像进行下采样,以避免OutOfMemory错误

private Bitmap decodeUri(Uri selectedImage) throws FileNotFoundException {

        // Decode image size
        BitmapFactory.Options o = new BitmapFactory.Options();
        o.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(getContentResolver().openInputStream(selectedImage), null, o);

        // The new size we want to scale to
        final int REQUIRED_SIZE = 140;

        // Find the correct scale value. It should be the power of 2.
        int width_tmp = o.outWidth, height_tmp = o.outHeight;
        int scale = 1;
        while (true) {
            if (width_tmp / 2 < REQUIRED_SIZE
               || height_tmp / 2 < REQUIRED_SIZE) {
                break;
            }
            width_tmp /= 2;
            height_tmp /= 2;
            scale *= 2;
        }

        // Decode with inSampleSize
        BitmapFactory.Options o2 = new BitmapFactory.Options();
        o2.inSampleSize = scale;
        return BitmapFactory.decodeStream(getContentResolver().openInputStream(selectedImage), null, o2);

    }
私有位图解码Uri(Uri selectedImage)引发FileNotFoundException{
//解码图像大小
BitmapFactory.Options o=新的BitmapFactory.Options();
o、 inJustDecodeBounds=true;
BitmapFactory.decodeStream(getContentResolver().openInputStream(SelecteImage),null,o;
//我们要扩展到的新尺寸
所需最终整型尺寸=140;
//找到正确的刻度值。它应该是2的幂。
内部宽度=o.向外宽度,高度=o.向外高度;
int标度=1;
while(true){
如果(宽度\u tmp/2<要求的\u尺寸
||高度(tmp/2<所需尺寸){
打破
}
宽度_tmp/=2;
高度_tmp/=2;
比例*=2;
}
//用inSampleSize解码
BitmapFactory.Options o2=新的BitmapFactory.Options();
o2.inSampleSize=刻度;
返回BitmapFactory.decodeStream(getContentResolver().openInputStream(SelecteImage),null,o2;
}

调用chooseImage方法,如-

public void chooseImage(ImageView v)
{
    Intent intent = new Intent(Intent.ACTION_PICK);
    intent.setType("image/*");
    startActivityForResult(intent, SELECT_PHOTO);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent imageReturnedIntent) {
    // TODO Auto-generated method stub
    super.onActivityResult(requestCode, resultCode, imageReturnedIntent);

    if(imageReturnedIntent != null)
    {
        Uri selectedImage = imageReturnedIntent.getData();
    switch(requestCode) { 
    case SELECT_PHOTO:
        if(resultCode == RESULT_OK)
        {
            Bitmap datifoto = null;
            temp.setImageBitmap(null);
            Uri picUri = null;
            picUri = imageReturnedIntent.getData();//<- get Uri here from data intent
             if(picUri !=null){
               try {
                   datifoto = android.provider.MediaStore.Images.Media.getBitmap(this.getContentResolver(),                                 picUri);
                   temp.setImageBitmap(datifoto);
               } catch (FileNotFoundException e) {
                  throw new RuntimeException(e);
               } catch (IOException e) {
                  throw new RuntimeException(e);
               } catch (OutOfMemoryError e) {
                Toast.makeText(getBaseContext(), "Image is too large. choose other", Toast.LENGTH_LONG).show();
            }

        }
        }
        break;

}
    }
    else
    {
        //Toast.makeText(getBaseContext(), "data null", Toast.LENGTH_SHORT).show();
    }
}
public void选择图像(图像视图v)
{
意向意向=新意向(意向、行动和选择);
intent.setType(“image/*”);
startActivityForResult(意图,选择照片);
}
@凌驾
ActivityResult上受保护的void(int-requestCode、int-resultCode、Intent-ImageReturnedContent){
//TODO自动生成的方法存根
super.onActivityResult(请求代码、结果代码、图像返回内容);
if(imageReturnedIntent!=null)
{
Uri selectedImage=imageReturnedIntent.getData();
开关(请求代码){
案例选择图片:
if(resultCode==RESULT\u OK)
{
位图datifoto=null;
临时设置图像位图(空);
Uri picUri=null;

picUri=imageReturnedIntent.getData();//由于某些原因,此线程中的所有答案,在
onActivityResult()
中,尝试对接收到的
Uri
进行后期处理,比如获取图像的真实路径,然后使用
位图工厂.decodeFile(path)

此步骤是不必要的。
ImageView
类有一个名为
setImageURI(uri)
的方法。将您的uri传递给它,您就应该完成了

Uri imageUri = data.getData();
imageView.setImageURI(imageUri);
有关完整的工作示例,您可以在此处查看:

附言:

如果要加载的图像太大而无法装入内存,则在单独变量中获取
位图将有意义,并且需要进行缩小操作以防止
OurOfMemoryError
,如@siamii答案所示。

这是一个经过测试的图像和视频代码。它适用于所有小于19和g的API也超过19岁

图片:

if (Build.VERSION.SDK_INT <= 19) {
                        Intent i = new Intent();
                        i.setType("image/*");
                        i.setAction(Intent.ACTION_GET_CONTENT);
                        i.addCategory(Intent.CATEGORY_OPENABLE);
                        startActivityForResult(i, 10);
                    } else if (Build.VERSION.SDK_INT > 19) {
                        Intent intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
                        startActivityForResult(intent, 10);
                    }

应检查cursor.moveToFirst()是否存在:如果(cursor.moveToFirst()){使用光标数据执行某些操作}而不是使用光标,则应以以下方式获取图像:位图b=MediaStore.Images.Media.getBitmap(this.getContentResolver(),selectedImage);Luigi,
public void chooseImage(ImageView v)
{
    Intent intent = new Intent(Intent.ACTION_PICK);
    intent.setType("image/*");
    startActivityForResult(intent, SELECT_PHOTO);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent imageReturnedIntent) {
    // TODO Auto-generated method stub
    super.onActivityResult(requestCode, resultCode, imageReturnedIntent);

    if(imageReturnedIntent != null)
    {
        Uri selectedImage = imageReturnedIntent.getData();
    switch(requestCode) { 
    case SELECT_PHOTO:
        if(resultCode == RESULT_OK)
        {
            Bitmap datifoto = null;
            temp.setImageBitmap(null);
            Uri picUri = null;
            picUri = imageReturnedIntent.getData();//<- get Uri here from data intent
             if(picUri !=null){
               try {
                   datifoto = android.provider.MediaStore.Images.Media.getBitmap(this.getContentResolver(),                                 picUri);
                   temp.setImageBitmap(datifoto);
               } catch (FileNotFoundException e) {
                  throw new RuntimeException(e);
               } catch (IOException e) {
                  throw new RuntimeException(e);
               } catch (OutOfMemoryError e) {
                Toast.makeText(getBaseContext(), "Image is too large. choose other", Toast.LENGTH_LONG).show();
            }

        }
        }
        break;

}
    }
    else
    {
        //Toast.makeText(getBaseContext(), "data null", Toast.LENGTH_SHORT).show();
    }
}
Uri imageUri = data.getData();
imageView.setImageURI(imageUri);
if (Build.VERSION.SDK_INT <= 19) {
                        Intent i = new Intent();
                        i.setType("image/*");
                        i.setAction(Intent.ACTION_GET_CONTENT);
                        i.addCategory(Intent.CATEGORY_OPENABLE);
                        startActivityForResult(i, 10);
                    } else if (Build.VERSION.SDK_INT > 19) {
                        Intent intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
                        startActivityForResult(intent, 10);
                    }
if (Build.VERSION.SDK_INT <= 19) {
                        Intent i = new Intent();
                        i.setType("video/*");
                        i.setAction(Intent.ACTION_GET_CONTENT);
                        i.addCategory(Intent.CATEGORY_OPENABLE);
                        startActivityForResult(i, 20);
                    } else if (Build.VERSION.SDK_INT > 19) {
                        Intent intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Video.Media.EXTERNAL_CONTENT_URI);
                        startActivityForResult(intent, 20);
                    }    
     @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == Activity.RESULT_OK) {               
            if (requestCode == 10) {
                Uri selectedImageUri = data.getData();
                String selectedImagePath = getRealPathFromURI(selectedImageUri);
            } else if (requestCode == 20) {
                Uri selectedVideoUri = data.getData();
                String selectedVideoPath = getRealPathFromURI(selectedVideoUri);
            }
        }
     }

     public String getRealPathFromURI(Uri uri) {
            if (uri == null) {
                return null;
            }
            String[] projection = {MediaStore.Images.Media.DATA};
            Cursor cursor = getActivity().getContentResolver().query(uri, projection, null, null, null);
            if (cursor != null) {
                int column_index = cursor
                        .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
                cursor.moveToFirst();
                return cursor.getString(column_index);
            }
            return uri.getPath();
        }