2010-03-24 4 views
327

Этот вопрос изначально был задан для Android 1.6.Как выбрать изображение из галереи (SD-карта) для моего приложения?

Я работаю над параметрами фотографий в своем приложении.

У меня есть кнопка и ImageView в моей деятельности. Когда я нажимаю кнопку, она будет перенаправляться в галерею, и я смогу выбрать изображение. Выбранное изображение появится в моем ImageView.

+1

посмотреть на этот ответ, я разместил улучшенный код там обрабатывать медиаторы из файловых менеджеров также http://stackoverflow.com/questions/2169649/open-an-image-in-androids-built-in- gallery-app-programatically/4470069 # 4470069 – mad

ответ

411

Обновленный ответ, почти 5 лет спустя:

код в оригинальный ответ больше не работает надежно, как и образы из различных источников, иногда возвращаются с различным содержанием URI, т.е. content://, а не file://. Лучшее решение - просто использовать context.getContentResolver().openInputStream(intent.getData()), так как это вернет InputStream, который вы сможете обрабатывать по своему усмотрению.

Например, BitmapFactory.decodeStream() отлично справляется с этой ситуацией, так как вы также можете использовать поля «Параметры» и «Иссечение размера» для уменьшения размера больших изображений и устранения проблем с памятью.

Однако такие вещи, как Google Drive, возвращают 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. Это просто получает номер столбца на основе его имени, тот же самый, который используется в процессе фильтрации. Как только вы получите это, вы, наконец, сможете декодировать изображение в растровое изображение с последней строкой кода, которую я дал.

+4

cursor.moveToFirst() необходимо проверить на наличие: if (cursor.moveToFirst()) {сделать что-то с данными курсора} – mishkin

+0

columnIndex всегда 0, потому что ваш запрос запрашивает только один столбец, который, конечно, имеет индекс 0. Или я что-то упускаю, и это не всегда так? –

+1

Это не то, что я специально экспериментировал, поэтому я не мог сказать точно. Было бы разумно, что если вы только попросите один столбец, вы можете предположить, что он всегда будет в индексе 0. Однако я думаю, что для повышения безопасности на случай, если вы что-то изменили, эта строка стоит того. –

87

Чтобы получить результат, вы должны приступить к созданию галереи.

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.

+0

Как ACTION_PICK отличается от ACTION_GET_CONTENT, используемого в двух других ответах? – penguin359

+4

С ACTION_PICK вы указываете конкретный URI, и с ACTION_GET_CONTENT вы указываете mime_type. Я использовал ACTION_PICK, потому что речь шла именно о изображениях из SDCARD, а не обо всех изображениях. –

+2

Прохладный. Это именно то, что мне нужно и работало как шарм :) Интересно, откуда вы, ребята, находите этот материал :) –

14

Сделайте это, чтобы запустить галерею и позволить пользователю выбрать изображение:

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

Тогда в вашем onActivityResult() использовать URI изображения, который возвращается, чтобы установить изображение на ImageView. не

+3

Это не будет работать для устройств Android 4.4. Он запустит экран последних документов. – Noundla

+2

Вот исправление для KitKat: stackoverflow.com/a/26690628/860488 –

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

    } 
+8

, помещая 1,5 МБ jpeg в мой маленький 100px на 100px изображение, привел к ошибке VM из памяти. Downsampling исправил эту проблему :-) –

+1

Привет. Не следует ли закрывать оба потока? –

+0

Здравствуйте @ siamii..I следил за вашим кодом ... но он частично работает для меня .. :(Когда изображение выбрано из галереи под заголовком снятых изображений, тогда это дает json-ошибку, но когда изображение выбрано из галереи под bluetooth изображение раздела доступно и отправлено на сервер. Не могли бы вы проверить эту ссылку и предложить мне какое-либо решение, пожалуйста ... http://stackoverflow.com/questions/29234409/image-is-not-uploaded – Prabs

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

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

} 
+1

Не работает на Android 4.4 –

+0

Вот исправление для KitKat: stackoverflow.com/a/26690628/860488 –

1
#initialize in main activity 
    path = Environment.getExternalStorageDirectory() 
      + "/images/make_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); 


} 
2

вызов метода 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(); 
    } 
} 
3

По некоторым причинам, все ответы в этой теме, в onActivityResult() пытаются пост-обработки принятого Uri , например, получить реальный путь изображения, а затем использовать BitmapFactory.decodeFile(path), чтобы получить Bitmap ,

Этот шаг не требуется. Класс ImageView имеет метод, называемый setImageURI(uri). Передайте свой uri, и вы должны сделать это.

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

Для полного рабочего примера можно взглянуть здесь: http://androidbitmaps.blogspot.com/2015/04/loading-images-in-android-part-iii-pick.html

PS:
Получение Bitmap в отдельной переменной будет иметь смысл в тех случаях, когда изображение будет загружено слишком большой, чтобы поместится в память, а операция уменьшения масштаба необходима для предотвращения OurOfMemoryError, как показано в ответе @siamii.

22

Вот протестированный код для изображения и видео. Он будет работать для всех API менее 19 и более 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); 
        } 

Видео:

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

 Смежные вопросы

  • Нет связанных вопросов^_^