Як вибрати зображення з галереї (SD Card) для свого додатка?


343

Це питання спочатку задавали для Android 1.6.

Я працюю над параметрами фотографій у своєму додатку.

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


1
подивіться на цю відповідь, я розмістив там вдосконалений код для обробки вибору файлових менеджерів також stackoverflow.com/questions/2169649/…
божевільний

Відповіді:


418

Оновлена ​​відповідь, майже через 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код. Це просто отримує номер стовпця на основі його імені, того самого, який використовується у процесі фільтрації. Як тільки ви це отримаєте, ви, нарешті, зможете розшифрувати зображення в растровій карті з останнім рядком коду, який я дав.


4
cursor.moveToFirst () слід перевірити на наявність: якщо (cursor.moveToFirst ()) {зробіть щось із даними курсора}
mishkin

14
Замість курсору слід отримати зображення таким чином: Bitmap b = MediaStore.Images.Media.getBitmap (this.getContentResolver (), selectedImage);
Луїджі Агості

4
Луїджі, якщо Bitmap великий MediaStore.Images.Media.getBitmap () може спричинити винятки OutOfMemory. Метод Стіва дозволяє зменшити масштаб зображення перед завантаженням його в пам'ять.
Френк Харпер

9
це не працює для мене, я отримую нуль від cursor.getString (columnIndex);
Alexis Pautrot

9
Обережно з цим методом: ім'я файлу буде "нульовим", коли користувач вибере фотографію з альбому Picasa або з програми Google+ Фото.
Ciske Boekelo

315
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
поміщення jpeg 1,5 Мб у мій невеликий перегляд зображень у 100 пікселів на 100 пікселів призвело до помилки пам'яті в VM. Даунсимплінг вирішив цю проблему :-)
Хтось десь

1
Привіт. Чи не повинні обидва потоки закриватися?
Денис Княжев

Привіт @ siamii..Я пішов за вашим кодом ... але це частково працює для мене .. :( коли зображення вибирається з галереї під розділом захоплених зображень, то воно дає помилку json, але коли зображення вибрано з галереї під розділом Bluetooth образ доступний і відправлений server..could ласка , перевірте це посилання і запропонувати мені яке - або рішення , будь ласка ... stackoverflow.com/questions/29234409/image-is-not-uploaded
Prabs

Розділ про пошук шкали можна записати так:int scale = 1; for ( ; bfOptions.outWidth / scale > TARGET_SIZE && bfOptions.outWidth > TARGET_SIZE; scale*=2);
The_Rafi

@siamii Де і як називати цей метод -------- decodeUri
Акшай Кумар,

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.


Чим ACTION_PICK відрізняється від ACTION_GET_CONTENT, що використовується у двох інших відповідях?
penguin359

4
За допомогою ACTION_PICK ви вказуєте конкретний URI, а за допомогою ACTION_GET_CONTENT ви вказуєте тип mime_type. Я використовував ACTION_PICK, оскільки питання стосувалося конкретно зображень із SDCARD, а не всіх зображень.
Robby Pond

2
Класно. Це саме те, що мені було потрібно і працював як шарм :) Цікаво, звідки ви, хлопці, знайдете цей матеріал :)
Jayshil Dave

@WilliamKinaan ACTIVITY_SELECT_IMAGE - це будь-яке значення int, яке ви вказуєте, щоб визначити, який результат ви очікуєте отримати. Потім він надсилається назад у onActivityResult (int requestCode, int resultCode, Intent data) як "codeCode".
Фідо

@Fydo Я зрозумів, що пізніше, Спасибі
Вільям Кінаан

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

14

Зробіть це, щоб запустити галерею та дозволити користувачеві вибрати зображення:

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

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


3
Це не працює для пристроїв Android 4.4. Він запустить екран останніх документів.
Noundla Sandeep

2
Ось виправлення для KitKat: stackoverflow.com/a/26690628/860488
Morten Holmgaard

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

}

Ось виправлення для KitKat: stackoverflow.com/a/26690628/860488
Morten Holmgaard

4

З певних причин усі відповіді в цій темі onActivityResult()намагаються переробити отримане Uri, як-от отримати реальний шлях зображення, а потім використати, 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:
Введення Bitmapв окрему змінну має сенс у випадках, коли завантажуване зображення є занадто великим, щоб вміститись у пам'яті, і для запобігання необхідна операція зменшення масштабу OurOfMemoryError, як показано у відповіді @siamii.


3

виклик методу selectImage типу

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

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


}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.