如何从图库(SD卡)为我的应用程序select一个图像?

这个问题最初是要求为Android 1.6。

我正在处理我的应用程序中的照片选项。

我在我的活动中有一个button和一个ImageView。 当我点击button时,它会redirect到画廊,我将能够select一个图像。 所选图像将出现在我的ImageView中。

近5年后更新了答案:

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

例如, BitmapFactory.decodeStream()在这种情况下可以很好地工作,因为您也可以使用Options和inSampleSize字段来下采样大图像并避免内存问题。

但是,Google云端硬盘会将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列的信息,从文件path到'最后修改date'到拍摄照片的GPS坐标,尽pipe很多字段没有被实际使用。

为了节省时间,因为您实际上不需要其他字段,光标search使用filter完成。 该filter通过指定所需列的名称MediaStore.Images.Media.DATA(这是path),然后将该string[]指定给游标查询来工作。 游标查询返回的path,但你不知道它是哪个列,直到你使用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); } 

你必须开始画廊意图的结果。

 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获取图像。

这是一个经过testing的图像和video代码。它将适用于所有19以下和19以上的API。

图片:

 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); } 

video:

 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(); } 

这样做启animation廊,并允许用户select一个图像:

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

然后在你的onActivityResult()使用返回的图像的URI来设置ImageView上的图像。

 public class EMView extends Activity { ImageView img,img1; int column_index; Intent intent=null; // Declare our Views, so we can access them later String logo,imagePath,Logo; Cursor cursor; //YOU CAN EDIT THIS TO WHATEVER YOU WANT private static final int SELECT_PICTURE = 1; String selectedImagePath; //ADDED String filemanagerstring; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); img= (ImageView)findViewById(R.id.gimg1); ((Button) findViewById(R.id.Button01)) .setOnClickListener(new OnClickListener() { public void onClick(View arg0) { // in onCreate or any event where your want the user to // select a file Intent intent = new Intent(); intent.setType("image/*"); intent.setAction(Intent.ACTION_GET_CONTENT); startActivityForResult(Intent.createChooser(intent, "Select Picture"), SELECT_PICTURE); } }); } //UPDATED @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { if (resultCode == Activity.RESULT_OK) { if (requestCode == SELECT_PICTURE) { Uri selectedImageUri = data.getData(); //OI FILE Manager filemanagerstring = selectedImageUri.getPath(); //MEDIA GALLERY selectedImagePath = getPath(selectedImageUri); img.setImageURI(selectedImageUri); imagePath.getBytes(); TextView txt = (TextView)findViewById(R.id.title); txt.setText(imagePath.toString()); Bitmap bm = BitmapFactory.decodeFile(imagePath); // img1.setImageBitmap(bm); } } } //UPDATED! public String getPath(Uri uri) { String[] projection = { MediaColumns.DATA }; Cursor cursor = managedQuery(uri, projection, null, null, null); column_index = cursor .getColumnIndexOrThrow(MediaColumns.DATA); cursor.moveToFirst(); imagePath = cursor.getString(column_index); return cursor.getString(column_index); } } 
 public class BrowsePictureActivity extends Activity { private static final int SELECT_PICTURE = 1; private String selectedImagePath; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); ((Button) findViewById(R.id.Button01)) .setOnClickListener(new OnClickListener() { public void onClick(View arg0) { Intent intent = new Intent(); intent.setType("image/*"); intent.setAction(Intent.ACTION_GET_CONTENT); startActivityForResult(Intent.createChooser(intent, "Select Picture"), SELECT_PICTURE); } }); } public void onActivityResult(int requestCode, int resultCode, Intent data) { if (resultCode == RESULT_OK) { if (requestCode == SELECT_PICTURE) { Uri selectedImageUri = data.getData(); selectedImagePath = getPath(selectedImageUri); } } } public String getPath(Uri uri) { if( uri == null ) { return null; } // this will only work for images selected from gallery String[] projection = { MediaStore.Images.Media.DATA }; Cursor cursor = managedQuery(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(); } } 

由于某些原因, onActivityResult()所有答案都会尝试对接收到的Uri进行后期处理,例如获取图像的实际path,然后使用BitmapFactory.decodeFile(path)获取Bitmap

这一步是不必要的。 ImageView类有一个名为setImageURI(uri) 。 把你的尿通过它,你应该完成。

 Uri imageUri = data.getData(); imageView.setImageURI(imageUri); 

对于一个完整的工作例子,你可以看看这里: http : //androidbitmaps.blogspot.com/2015/04/loading-images-in-android-part-iii-pick.html

PS:
在一个单独的variables中获取Bitmap是有意义的,因为要加载的图像太大而不能放入内存,并且缩小操作对于防止OurOfMemoryError是必要的,就像@siamii答案中所示。

调用chooseImage方法like-

 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(); } } 
 #initialize in main activity path = Environment.getExternalStorageDirectory() + "http://img.dovov.commake_machine_example.jpg"; # ImageView image=(ImageView)findViewById(R.id.image); //--------------------------------------------------|| public void FromCamera(View) { 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); }