Как выбрать изображение из галереи (SD Card) для моего приложения?

Этот вопрос изначально задавался для Android 1.6.

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

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

10 ответов

Решение

Обновленный ответ, почти через 5 лет:

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

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

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

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

    }

You have to start the gallery intent for a result.

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

Затем в onActivityForResult, вызов intent.getData() to get the Uri of the Image. Затем вам нужно получить изображение от ContentProvider.

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

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

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, как получить реальный путь изображения, а затем использовать 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.

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


}

Увидев все ответы. Я предлагаю использовать Android Logger.

Вы можете просто установить логическое значение, что приложение регистрируется или нет. Из документации

Адаптер журнала проверяет, следует ли печатать журнал, проверяя эту функцию. Если вы хотите отключить / скрыть логи для вывода, переопределите метод isLoggable. true напечатает сообщение журнала, false проигнорирует его.

Logger.addLogAdapter(new AndroidLogAdapter() {
  @Override public boolean isLoggable(int priority, String tag) {
    return BuildConfig.DEBUG;
  }
});

Есть много возможностей этой библиотеки, вы можете найти их в документации.

Бонус: логи этой библиотеки выглядят так. Разве это не круто!

образ

Другие вопросы по тегам