Програмно отримуйте / вибирайте зображення із вбудованого додатка Галерея Android


271

Я намагаюся відкрити зображення / зображення у вбудованому додатку Галерея зсередини програми.

У мене є URI зображення (зображення розташоване на SD-картці).

Чи є у вас якісь пропозиції?


Я оновив свою відповідь, щоб надати більше тестового коду, щоб гарантувати правильне отримання результатів.
Ентоні Форлоні

Подивіться на мою відповідь, це оновлення коду hcpl, і воно також працює для астро файлового менеджера та oi файлового менеджера.
божевільний

15
Хтось повинен оновити питання "Отримати / вибрати зображення з Android ...". Поточне запитання тлумачить, що у мене є зображення, і я хочу показати його через додаток галереї за замовчуванням.
Вікас

@Vikas, здається, ти маєш рацію. Я не пам’ятаю, що саме я намагався досягти більше року тому і чому всі відповіді (включаючи той, який я вибрав як рішення) насправді відповідають на інше питання ...
Майкл Кесслер

Насправді я не знаю, чи правильно цілком змінити питання. Є 36 людей, які додали питання до своїх улюблених ...
Майкл Кесслер

Відповіді:


351

Це повне рішення. Я щойно оновив цей приклад коду інформацією, наданою у відповіді нижче від @mad. Також перегляньте рішення нижче в @Khobaib, пояснивши, як поводитися із зображеннями Picasa.

Оновлення

Щойно я переглянув свою оригінальну відповідь і створив простий проект Android Studio, на який можна отримати замовлення з github та імпортувати безпосередньо у вашу систему.

https://github.com/hanscappelle/SO-2169649

(зауважте, що багаторазовий вибір файлів все ще потребує роботи)

Вибір єдиного зображення

Завдяки підтримці зображень від файлових дослідників завдяки користувачеві mad.

public class BrowsePictureActivity extends Activity {

    // this is the action code we use in our intent, 
    // this way we know we're looking at the response from our own action
    private static final int SELECT_PICTURE = 1;

    private String selectedImagePath;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

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

    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == RESULT_OK) {
            if (requestCode == SELECT_PICTURE) {
                Uri selectedImageUri = data.getData();
                selectedImagePath = getPath(selectedImageUri);
            }
        }
    }

    /**
     * helper to retrieve the path of an image URI
     */
    public String getPath(Uri uri) {
            // just some safety built in 
            if( uri == null ) {
                // TODO perform some logging or show user feedback
                return null;
            }
            // try to retrieve the image from the media store first
            // 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();
                String path = cursor.getString(column_index);
                cursor.close();
                return path;
            }
            // this is our fallback here
            return uri.getPath();
    }

}

Вибір декількох зображень

Оскільки хтось просив цю інформацію в коментарі, і краще зібрати інформацію.

Встановіть додатковий параметр EXTRA_ALLOW_MULTIPLEу намірі:

intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);

І у перевірці обробки результатів для цього параметра:

if (Intent.ACTION_SEND_MULTIPLE.equals(data.getAction()))
        && Intent.hasExtra(Intent.EXTRA_STREAM)) {
    // retrieve a collection of selected images
    ArrayList<Parcelable> list = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM);
    // iterate over these images
    if( list != null ) {
       for (Parcelable parcel : list) {
         Uri uri = (Uri) parcel;
         // TODO handle the images one by one here
       }
   }
} 

Зауважте, що це підтримується лише API рівня 18+.


Це не працює, коли я використовую Astro файловий менеджер. Будь-які ідеї чому?
Рохіт Нандакумар

@hcpl Дякую за відповідь. Скажіть, будь ласка, як отримати кілька зображень ...?
Noby

28
Створення єдиного зображення, схоже, вже не працює над новітньою версією Android 4.4 (KitKat). Стовпець _data із запиту повертає нульове значення.
Крістофер Массер

1
@hcpl Ви не мали на увазі "Intent.hasExtra", ви мали на увазі "data.hasExtra" - припустимо, що дані є вашим параметром Intent в onActivityResult ().
ІгорГанапольський

2
Цей код прекрасно працює preKitkat, але відтоді з'являються постачальники документів. У своїй відповіді я пишу про те, що робити в киткаті.
абат

135

Ось оновлення до тонкого коду, який розмістив hcpl. але це також працює з OI файловим менеджером, астро-файловим менеджером І медіа-галереєю (протестовано). тож я здогадуюсь, що він буде працювати з кожним файловим менеджером (чи багато інших, ніж згадані?). зробив деякі виправлення написаного ним коду.

public class BrowsePicture extends Activity {

    //YOU CAN EDIT THIS TO WHATEVER YOU WANT
    private static final int SELECT_PICTURE = 1;

    private String selectedImagePath;
    //ADDED
    private String filemanagerstring;

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

                // 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
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == RESULT_OK) {
            if (requestCode == SELECT_PICTURE) {
                Uri selectedImageUri = data.getData();

                //OI FILE Manager
                filemanagerstring = selectedImageUri.getPath();

                //MEDIA GALLERY
                selectedImagePath = getPath(selectedImageUri);

                //DEBUG PURPOSE - you can delete this if you want
                if(selectedImagePath!=null)
                    System.out.println(selectedImagePath);
                else System.out.println("selectedImagePath is null");
                if(filemanagerstring!=null)
                    System.out.println(filemanagerstring);
                else System.out.println("filemanagerstring is null");

                //NOW WE HAVE OUR WANTED STRING
                if(selectedImagePath!=null)
                    System.out.println("selectedImagePath is the right one for you!");
                else
                    System.out.println("filemanagerstring is the right one for you!");
            }
        }
    }

    //UPDATED!
    public String getPath(Uri uri) {
        String[] projection = { MediaStore.Images.Media.DATA };
        Cursor cursor = managedQuery(uri, projection, null, null, null);
        if(cursor!=null)
        {
            //HERE YOU WILL GET A NULLPOINTER IF CURSOR IS NULL
            //THIS CAN BE, IF YOU USED OI FILE MANAGER FOR PICKING THE MEDIA
            int column_index = cursor
            .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
            cursor.moveToFirst();
            return cursor.getString(column_index);
        }
        else return null;
    }

1
Як отримати зображення Bitmap із шляху OI?
Вікас

2
подивіться на код. в рядках з коментарем // ЗАРАЗ МИ МАЄМО НАШІЙ ВІДКРИТИЙ СТРІН ... це все, що вам потрібно. потім використовуйте клас BitmapFactory для отримання растрової карти з шляху
божевільний

Дякую! У вас хороший момент, ніколи не пробували інших файлових менеджерів :).
hcpl

2
Я також хотів би закрити курсор :)
pgsandstrom

7
Може також змінити else return null;в getPath(Uri uri)до return uri.getPath();і позбутися від першої filemanagerstring = selectedImageUri.getPath();перевірки. Таким чином, ви просто зробите один дзвінок getPath(Uri)і повертаєте шлях назад (незалежно від того, використовувались Галерея чи файловий менеджер).
ашути

24

Методи hcpl прекрасно працюють перед KitKat, але не працюють з API DocumentsProvider. Для цього просто дотримуйтесь офіційного підручника Android для постачальників документів: https://developer.android.com/guide/topics/providers/document-provider.html -> відкрийте документ, розділ Bitmap.

Просто я використав код hcpl і розширив його: якщо файл із отриманим шляхом до зображення кидає виняток, я викликаю цю функцію:

private Bitmap getBitmapFromUri(Uri uri) throws IOException {
        ParcelFileDescriptor parcelFileDescriptor =
             getContentResolver().openFileDescriptor(uri, "r");
        FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
        Bitmap image = BitmapFactory.decodeFileDescriptor(fileDescriptor);
        parcelFileDescriptor.close();
        return image;
}

Тестовано на Nexus 5.


Дійсно корисна відповідь, слід використовувати для вибору зображень із програми "Фотографії".
Arun Badole

Я спробував це в файлах локального та сервера, працював для обох.
Арун Бадоле

11

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

public String getPath(Uri uri) {
    String selectedImagePath;
    //1:MEDIA GALLERY --- query from MediaStore.Images.Media.DATA
    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();
        selectedImagePath = cursor.getString(column_index);
    }else{
        selectedImagePath = null;
    }

    if(selectedImagePath == null){
        //2:OI FILE Manager --- call method: uri.getPath()
        selectedImagePath = uri.getPath();
    }
    return selectedImagePath;
}

11

Я розглядав рішення від @hcpl & @mad. Рішення hcpl добре підтримує локальне зображення в галереї & mad за умови кращого рішення - це також допомагає завантажити зображення OI / Astro / Dropbox. Але в моєму додатку, працюючи над бібліотекою picasa яка тепер інтегрована в Android Gallery, обидва рішення не виходять із ладу.

Я трохи пошукав і проаналізував і, врешті-решт, прийшов із кращим та елегантним рішенням, яке долає це обмеження. Завдяки Димитру Даражанському за його блог, який мені допоміг у цій справі, я трохи змінив, щоб полегшити розуміння. Ось моє рішення іде -

public class BrowsePicture extends Activity {

//YOU CAN EDIT THIS TO WHATEVER YOU WANT
private static final int SELECT_PICTURE = 1;

private String selectedImagePath;
//ADDED
private String filemanagerstring;

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

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

public void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (resultCode == RESULT_OK) {
        if (requestCode == SELECT_PICTURE) {
            Uri selectedImageUri = data.getData();
            Log.d("URI VAL", "selectedImageUri = " + selectedImageUri.toString());
            selectedImagePath = getPath(selectedImageUri);

            if(selectedImagePath!=null){         
                // IF LOCAL IMAGE, NO MATTER IF ITS DIRECTLY FROM GALLERY (EXCEPT PICASSA ALBUM),
                // OR OI/ASTRO FILE MANAGER. EVEN DROPBOX IS SUPPORTED BY THIS BECAUSE DROPBOX DOWNLOAD THE IMAGE 
                // IN THIS FORM - file:///storage/emulated/0/Android/data/com.dropbox.android/...
                System.out.println("local image"); 
            }
            else{
                System.out.println("picasa image!");
                loadPicasaImageFromGallery(selectedImageUri);
            }
        }
    }
}


// NEW METHOD FOR PICASA IMAGE LOAD
private void loadPicasaImageFromGallery(final Uri uri) {
    String[] projection = {  MediaColumns.DATA, MediaColumns.DISPLAY_NAME };
    Cursor cursor = getContentResolver().query(uri, projection, null, null, null);
    if(cursor != null) {
        cursor.moveToFirst();

        int columnIndex = cursor.getColumnIndex(MediaColumns.DISPLAY_NAME);
        if (columnIndex != -1) {
            new Thread(new Runnable() {
                // NEW THREAD BECAUSE NETWORK REQUEST WILL BE MADE THAT WILL BE A LONG PROCESS & BLOCK UI
                // IF CALLED IN UI THREAD 
                public void run() {
                    try {
                        Bitmap bitmap = android.provider.MediaStore.Images.Media.getBitmap(getContentResolver(), uri);
                        // THIS IS THE BITMAP IMAGE WE ARE LOOKING FOR.
                    } catch (Exception ex) {
                        ex.printStackTrace();
                    }
                }
            }).start();
        }
    }
    cursor.close();
}


public String getPath(Uri uri) {
    String[] projection = {  MediaColumns.DATA};
    Cursor cursor = getContentResolver().query(uri, projection, null, null, null);
    if(cursor != null) {
        //HERE YOU WILL GET A NULLPOINTER IF CURSOR IS NULL
        //THIS CAN BE, IF YOU USED OI FILE MANAGER FOR PICKING THE MEDIA
        cursor.moveToFirst();
        int columnIndex = cursor.getColumnIndexOrThrow(MediaColumns.DATA);
        String filePath = cursor.getString(columnIndex);
        cursor.close();
        return filePath;
    }
    else 
        return uri.getPath();               // FOR OI/ASTRO/Dropbox etc
}

Перевірте це і повідомте мені, чи є з цим проблема. Я перевірив це, і він працює добре у кожному випадку.

Сподіваюся, що це допоможе всім.


10

Якщо припустити , що у вас є зображення папки в каталозі карти SD для всього зображення.

Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
// tells your intent to get the contents
// opens the URI for your image directory on your sdcard
intent.setType("file:///sdcard/image/*"); 
startActivityForResult(intent, 1);

Тоді ви можете вирішити, що б ви хотіли зробити зі вмістом у своїй діяльності.

Це був приклад для отримання назви шляху для зображення, протестуйте це за допомогою коду, щоб переконатися, що ви можете обробляти результати, що повертаються. Ви можете змінити код за потребою, щоб краще відповідати вашим потребам.

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

  // this matches the request code in the above call
  if (requestCode == 1) {
      Uri _uri = i.getData();

    // this will be null if no image was selected...
    if (_uri != null) {
      // now we get the path to the image file
     cursor = getContentResolver().query(_uri, null,
                                      null, null, null);
     cursor.moveToFirst();
     String imageFilePath = cursor.getString(0);
     cursor.close();
     }
   }

Моя порада - спробувати отримати правильні зображення, які працюють правильно, я думаю, що проблема полягає в вмісті доступу до зображень на sdcard. Ознайомтеся з відображенням зображень на sd-картці .

Якщо ви можете це зробити і працювати, ймовірно, на прикладі надання правильного постачальника, ви зможете розібратися у вирішенні коду.

Повідомляйте мене, оновлюючи це питання своїм прогресом. Удачі


@Anthony, дякую за вашу відповідь. На жаль, це не працює для мене. Я отримую наступну помилку: android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.GET_CONTENT typ=file:///sdcard/images/* }
Майкл Кесслер

Вам потрібно зателефонувати startActivityforResultта надати дію. Це те, про що я мав на увазі, вирішуючи, що далі, моє погане.
Ентоні Форлоні

Він все ще не працює ... Я перевіряю, чи існує папка та чи є файл із зображеннями всередині папки. Я дзвоню startActivityForResult(intent, 1);і все ще отримую цю помилку ... Цей код розташований поза "Діяльністю", але я маю посилання на активність і називаю startActivityForResultметод у цій посиланні - можливо, це причина?
Майкл Кесслер

Ні, не повинно бути причиною, що це за 1ваш проїзд? СпробуйтеIMAGE_PICK
Ентоні Форлоні,

1
Другий парам - це щось для мене, чи не так? Це лише інта, яка буде передана мені разом з результатом. Спробував також Intent.ACTION_PICKзамість Intent.ACTION_GET_CONTENT. Що ви маєте на увазі під IMAGE_PICK? Такої постійної немає. Я також спробував intent.setData(Uri.fromFile(new File("/sdcard/image/")));. Я спробував усі можливі комбінації з них, і нічого, здається, не спрацювало ...
Майкл Кесслер

10

це мій перегляд цієї теми, збираючи всю інформацію тут, а також інші відповідні запитання щодо переповнення стека. Він повертає зображення від певного постачальника, обробляючи умови поза пам'яттю та обертання зображення. Він підтримує галереї, пікасу та файлові менеджери, як, наприклад, дроп-бокс. Використання просте: конструктор отримує роздільну здатність вмісту та uri. Вихід - кінцева растрова карта.

/**
 * Creates resized images without exploding memory. Uses the method described in android
 * documentation concerning bitmap allocation, which is to subsample the image to a smaller size,
 * close to some expected size. This is required because the android standard library is unable to
 * create a reduced size image from an image file using memory comparable to the final size (and
 * loading a full sized multi-megapixel picture for processing may exceed application memory budget).
 */

public class UserPicture {
    static int MAX_WIDTH = 600;
    static int MAX_HEIGHT = 800;
    Uri uri;
    ContentResolver resolver;
    String path;
    Matrix orientation;
    int storedHeight;
    int storedWidth;

    public UserPicture(Uri uri, ContentResolver resolver) {
        this.uri = uri;
        this.resolver = resolver;
    }

    private boolean getInformation() throws IOException {
        if (getInformationFromMediaDatabase())
            return true;

        if (getInformationFromFileSystem())
            return true;

        return false;
    }

    /* Support for gallery apps and remote ("picasa") images */
    private boolean getInformationFromMediaDatabase() {
        String[] fields = { Media.DATA, ImageColumns.ORIENTATION };
        Cursor cursor = resolver.query(uri, fields, null, null, null);

        if (cursor == null)
            return false;

        cursor.moveToFirst();
        path = cursor.getString(cursor.getColumnIndex(Media.DATA));
        int orientation = cursor.getInt(cursor.getColumnIndex(ImageColumns.ORIENTATION));
        this.orientation = new Matrix();
        this.orientation.setRotate(orientation);
        cursor.close();

        return true;
    }

    /* Support for file managers and dropbox */
    private boolean getInformationFromFileSystem() throws IOException {
        path = uri.getPath();

        if (path == null)
            return false;

        ExifInterface exif = new ExifInterface(path);
        int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,
                                               ExifInterface.ORIENTATION_NORMAL);

        this.orientation = new Matrix();
        switch(orientation) {
            case ExifInterface.ORIENTATION_NORMAL:
                /* Identity matrix */
                break;
            case ExifInterface.ORIENTATION_FLIP_HORIZONTAL:
                this.orientation.setScale(-1, 1);
                break;
            case ExifInterface.ORIENTATION_ROTATE_180:
                this.orientation.setRotate(180);
                break;
            case ExifInterface.ORIENTATION_FLIP_VERTICAL:
                this.orientation.setScale(1, -1);
                break;
            case ExifInterface.ORIENTATION_TRANSPOSE:
                this.orientation.setRotate(90);
                this.orientation.postScale(-1, 1);
                break;
            case ExifInterface.ORIENTATION_ROTATE_90:
                this.orientation.setRotate(90);
                break;
            case ExifInterface.ORIENTATION_TRANSVERSE:
                this.orientation.setRotate(-90);
                this.orientation.postScale(-1, 1);
                break;
            case ExifInterface.ORIENTATION_ROTATE_270:
                this.orientation.setRotate(-90);
                break;
        }

        return true;
    }

    private boolean getStoredDimensions() throws IOException {
        InputStream input = resolver.openInputStream(uri);
        Options options = new Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(resolver.openInputStream(uri), null, options);

        /* The input stream could be reset instead of closed and reopened if it were possible
           to reliably wrap the input stream on a buffered stream, but it's not possible because
           decodeStream() places an upper read limit of 1024 bytes for a reset to be made (it calls
           mark(1024) on the stream). */
        input.close();

        if (options.outHeight <= 0 || options.outWidth <= 0)
            return false;

        storedHeight = options.outHeight;
        storedWidth = options.outWidth;

        return true;
    }

    public Bitmap getBitmap() throws IOException {
        if (!getInformation())
            throw new FileNotFoundException();

        if (!getStoredDimensions())
            throw new InvalidObjectException(null);

        RectF rect = new RectF(0, 0, storedWidth, storedHeight);
        orientation.mapRect(rect);
        int width = (int)rect.width();
        int height = (int)rect.height();
        int subSample = 1;

        while (width > MAX_WIDTH || height > MAX_HEIGHT) {
            width /= 2;
            height /= 2;
            subSample *= 2;
        }

        if (width == 0 || height == 0)
            throw new InvalidObjectException(null);

        Options options = new Options();
        options.inSampleSize = subSample;
        Bitmap subSampled = BitmapFactory.decodeStream(resolver.openInputStream(uri), null, options);

        Bitmap picture;
        if (!orientation.isIdentity()) {
            picture = Bitmap.createBitmap(subSampled, 0, 0, options.outWidth, options.outHeight,
                                          orientation, false);
            subSampled.recycle();
        } else
            picture = subSampled;

        return picture;
    }
}

Список літератури:


9

Тут є два корисні підручники щодо вибору зображень із завантажуваним вихідним кодом:

Як створити Android Picker Image Picker

Як вибрати та обрізати зображення на Android

Однак додаток буде змушено коли-небудь закрити, ви можете виправити це, додавши атрибут android: configChanges в основну діяльність у файлі Manifest, як:

<activity android:name=".MainActivity"
                  android:label="@string/app_name" android:configChanges="keyboardHidden|orientation" >

Здається, API камери втратив управління з орієнтацією, тому це допоможе. :)


7

Нижче розроблені рішення для 2.3 (пряників) -4,4 (Kitkat), 5,0 (Lollipop) і 6,0 (Marshmallow) також: -

Крок 1 Код для відкриття галереї для вибору фотографій:

public static final int PICK_IMAGE = 1;
private void takePictureFromGalleryOrAnyOtherFolder() 
{
    Intent intent = new Intent();
    intent.setType("image/*");
    intent.setAction(Intent.ACTION_GET_CONTENT);
    startActivityForResult(Intent.createChooser(intent, "Select Picture"), PICK_IMAGE);
}

Крок 2 Код для отримання даних у onActivityResult:

 @Override
 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
            if (resultCode == Activity.RESULT_OK) {
               if (requestCode == PICK_IMAGE) {
                    Uri selectedImageUri = data.getData();
                    String imagePath = getRealPathFromURI(selectedImageUri);
                   //Now you have imagePath do whatever you want to do now
                 }//end of inner if
             }//end of outer if
      }

 public String getRealPathFromURI(Uri contentUri) {
        //Uri contentUri = Uri.parse(contentURI);

        String[] projection = { MediaStore.Images.Media.DATA };
        Cursor cursor = null;
        try {
            if (Build.VERSION.SDK_INT > 19) {
                // Will return "image:x*"
                String wholeID = DocumentsContract.getDocumentId(contentUri);
                // Split at colon, use second item in the array
                String id = wholeID.split(":")[1];
                // where id is equal to
                String sel = MediaStore.Images.Media._ID + "=?";

                cursor = context.getContentResolver().query(
                        MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                        projection, sel, new String[] { id }, null);
            } else {
                cursor = context.getContentResolver().query(contentUri,
                        projection, null, null, null);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        String path = null;
        try {
            int column_index = cursor
                    .getColumnIndex(MediaStore.Images.Media.DATA);
            cursor.moveToFirst();
            path = cursor.getString(column_index).toString();
            cursor.close();
        } catch (NullPointerException e) {
            e.printStackTrace();
        }
        return path;
    }

Для мене це працює, я використовую Nexus 5 з Marshmallow. Який телефон ви використовуєте.
Панкай

я також usng google nexus, але не вдалося отримати ім’я зображення або шлях моєї галереї, вибране зображення ім стає нульовим
Erum

java.lang.SecurityException: Заборона дозволу: читання com.android.providers.media.MediaProvider вмісту uri: // медіа / зовнішнє / зображення / медіа з pid = 31332, uid = 11859 вимагає android.permission.READ_EXTERNAL_STORAGE або grantUriPermission () отримати цю помилку
Ерум

Ви маєте додати дозвіл, який показує йогоREAD_EXTERNAL_STORAGE
Панкай

так, я вже додав дозвіл у маніфест, але я не додав жодного дозволу у файли Java під час виконання
Erum,

6

Щоб відобразити зображення та відео, спробуйте:

    Intent intent = new Intent();
    intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    startActivityForResult(intent, 1);
    startActivityForResult(Intent.createChooser(intent,"Wybierz plik"), SELECT_FILE);

5

Про всяк випадок, коли це допомагає; Я роблю це, щоб отримати Bitmap:

InputStream is = context.getContentResolver().openInputStream(imageUri);
Bitmap bitmap = BitmapFactory.decodeStream(is);

Це найпростіша відповідь (і єдина, яка працювала на мене). Так гарно зроблено!
Дерлін

5

Вище відповіді правильні. Я зіткнувся з іншою проблемою, коли в HTC M8 моя програма виходить з ладу під час вибору зображення з галереї. Я отримую нульове значення для шляху зображення. Я зафіксував та оптимізував наступне рішення. у методі onActivityResult

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if ((requestCode == RESULT_LOAD_IMAGE) && (resultCode == RESULT_OK)) {
     if (data != null) {

            Uri selectedImageUri = null;
            selectedImageUri = data.getData();
            String[] filePathColumn = { MediaStore.Images.Media.DATA };

            Cursor imageCursor = mainActivity.getContentResolver().query(
                    selectedImageUri, filePathColumn, null, null, null);

            if (imageCursor == null) {
                return;
            }

            imageCursor.moveToFirst();
            int columnIndex = imageCursor.getColumnIndex(filePathColumn[0]);
            picturePath = imageCursor.getString(columnIndex);
            if (picturePath == null) {
                picturePath = selectedImageUri.getPath();
                String wholeID = DocumentsContract
                        .getDocumentId(selectedImage);

                // Split at colon, use second item in the array
                String id = wholeID.split(":")[1];

                String[] column = { MediaStore.Images.Media.DATA };

                // where id is equal to
                String sel = MediaStore.Images.Media._ID + "=?";

                Cursor cursor = mainActivity.getContentResolver().query(
                        MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                        column, sel, new String[] { id }, null);

                columnIndex = cursor.getColumnIndex(column[0]);

                if (cursor.moveToFirst()) {
                    picturePath = cursor.getString(columnIndex);
                }

                cursor.close();
            }
            picturePathAbs = new File(picturePath).getAbsolutePath();
            imageCursor.close();
        }

}


Я стикаюся з подібною проблемою, і picturePath завжди є недійсним. Я пробую вам рішення, але не працює, плюс що getDocumentId вимагає> API 19
Stoycho Andreev

3
package com.ImageConvertingDemo;

import java.io.BufferedInputStream;
import java.io.FileInputStream;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.util.Log;
import android.widget.EditText;
import android.widget.ImageView;

public class MyActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        EditText tv = (EditText)findViewById(R.id.EditText01);
        ImageView iv = (ImageView)findViewById(R.id.ImageView01);
        FileInputStream in;
        BufferedInputStream buf;
            try 
            {
                in = new FileInputStream("/sdcard/smooth.png");
                buf = new BufferedInputStream(in,1070);
                System.out.println("1.................."+buf);
                byte[] bMapArray= new byte[buf.available()];
                tv.setText(bMapArray.toString());
                buf.read(bMapArray);
                Bitmap bMap = BitmapFactory.decodeByteArray(bMapArray, 0, bMapArray.length);

                /*for (int i = 0; i < bMapArray.length; i++) 
                {
                System.out.print("bytearray"+bMapArray[i]);
                }*/
                iv.setImageBitmap(bMap);
                //tv.setText(bMapArray.toString());
                //tv.setText(buf.toString());
                if (in != null) 
                {
                    in.close();
                }
                if (buf != null) 
                {
                    buf.close();
                }

            } 
            catch (Exception e) 
            {
                Log.e("Error reading file", e.toString());
            }
    }
}

1
Ви не зрозуміли питання, перш ніж відповісти. Також ви не включили жодного опису про те, що намагаєтесь зробити. Також ваш код порушує деякі усталені стандарти програмування Java.
Торбен

3
public class BrowsePictureActivity extends Activity {

    // this is the action code we use in our intent, 
    // this way we know we're looking at the response from our own action
    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) {

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

    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == RESULT_OK) {
            if (requestCode == SELECT_PICTURE) {
                Uri selectedImageUri = data.getData();
                selectedImagePath = getPath(selectedImageUri);
            }
        }
    }

    /**
     * helper to retrieve the path of an image URI
     */
    public String getPath(Uri uri) {
            // just some safety built in 
            if( uri == null ) {
                // TODO perform some logging or show user feedback
                return null;
            }
            // try to retrieve the image from the media store first
            // 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);
            }
            // this is our fallback here
            return uri.getPath();
    }

}

3

Отримайте певний тип файлу

Цей приклад отримає копію зображення.

static final int REQUEST_IMAGE_GET = 1;

public void selectImage() {
    Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
    intent.setType("image/*");
    if (intent.resolveActivity(getPackageManager()) != null) {
        startActivityForResult(intent, REQUEST_IMAGE_GET);
    }
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == REQUEST_IMAGE_GET && resultCode == RESULT_OK) {
        Bitmap thumbnail = data.getParcelable("data");
        Uri fullPhotoUri = data.getData();
        // Do work with photo saved at fullPhotoUri
        ...
    }
}

Відкрийте певний тип файлу

Запускаючи версію 4.4 або вище, ви вимагаєте відкрити файл, яким керує інша програма

static final int REQUEST_IMAGE_OPEN = 1;

public void selectImage() {
    Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
    intent.setType("image/*");
    intent.addCategory(Intent.CATEGORY_OPENABLE);
    // Only the system receives the ACTION_OPEN_DOCUMENT, so no need to test.
    startActivityForResult(intent, REQUEST_IMAGE_OPEN);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == REQUEST_IMAGE_OPEN && resultCode == RESULT_OK) {
        Uri fullPhotoUri = data.getData();
        // Do work with full size photo saved at fullPhotoUri
        ...
    }
}

Першоджерело


2

На додаток до попередніх відповідей, якщо у вас виникають проблеми з правильним шляхом (наприклад, AndroZip), ви можете скористатися цим:

  public String getPath(Uri uri ,ContentResolver contentResolver) {
        String[] projection = {  MediaStore.MediaColumns.DATA};
        Cursor cursor;
        try{
            cursor = contentResolver.query(uri, projection, null, null, null);
        } catch (SecurityException e){
            String path = uri.getPath();
            String result = tryToGetStoragePath(path);
            return  result;
        }
        if(cursor != null) {
            //HERE YOU WILL GET A NULLPOINTER IF CURSOR IS NULL
            //THIS CAN BE, IF YOU USED OI FILE MANAGER FOR PICKING THE MEDIA
            cursor.moveToFirst();
            int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA);
            String filePath = cursor.getString(columnIndex);
            cursor.close();
            return filePath;
        }
        else
            return uri.getPath();               // FOR OI/ASTRO/Dropbox etc
    }

    private String tryToGetStoragePath(String path) {
        int actualPathStart = path.indexOf("//storage");
        String result = path;

        if(actualPathStart!= -1 && actualPathStart< path.length())
            result = path.substring(actualPathStart+1 , path.length());

        return result;
    }

Чи потрібно знати тут ури зображення? Що робити, якщо я просто хочу вибрати довільне зображення з галереї?
ІгорГанапольський

Намір, який ви отримаєте від галереї, надасть вам URL
буграораль

1

Будь ласка, знайдіть відповідь для вибору одного зображення з галереї

import android.app.Activity;
import android.net.Uri;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;

public class PickImage extends Activity {

    Button btnOpen, btnGet, btnPick;
    TextView textInfo1, textInfo2;
    ImageView imageView;

    private static final int RQS_OPEN_IMAGE = 1;
    private static final int RQS_GET_IMAGE = 2;
    private static final int RQS_PICK_IMAGE = 3;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.image_pick);
        btnOpen = (Button)findViewById(R.id.open);
        btnGet = (Button)findViewById(R.id.get);
        btnPick = (Button)findViewById(R.id.pick);
        textInfo1 = (TextView)findViewById(R.id.info1);
        textInfo2 = (TextView)findViewById(R.id.info2);
        imageView = (ImageView) findViewById(R.id.image);

        btnOpen.setOnClickListener(btnOpenOnClickListener);
        btnGet.setOnClickListener(btnGetOnClickListener);
        btnPick.setOnClickListener(btnPickOnClickListener);
    }

    View.OnClickListener btnOpenOnClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent intent = new Intent();
            intent.setAction(Intent.ACTION_OPEN_DOCUMENT);
            intent.addCategory(Intent.CATEGORY_OPENABLE);
            intent.setType("image/*");

            startActivityForResult(intent, RQS_OPEN_IMAGE);
        }
    };

    View.OnClickListener btnGetOnClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent intent = new Intent();
            intent.setAction(Intent.ACTION_GET_CONTENT);
            intent.addCategory(Intent.CATEGORY_OPENABLE);
            intent.setType("image/*");

            startActivityForResult(intent, RQS_OPEN_IMAGE);
        }
    };

    View.OnClickListener btnPickOnClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent intent = new Intent(Intent.ACTION_PICK,
                    android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
            startActivityForResult(intent, RQS_PICK_IMAGE);
        }
    };

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == Activity.RESULT_OK) {


            if (requestCode == RQS_OPEN_IMAGE ||
                    requestCode == RQS_GET_IMAGE ||
                    requestCode == RQS_PICK_IMAGE) {

                imageView.setImageBitmap(null);
                textInfo1.setText("");
                textInfo2.setText("");

                Uri mediaUri = data.getData();
                textInfo1.setText(mediaUri.toString());
                String mediaPath = mediaUri.getPath();
                textInfo2.setText(mediaPath);

                //display the image
                try {
                    InputStream inputStream = getBaseContext().getContentResolver().openInputStream(mediaUri);
                    Bitmap bm = BitmapFactory.decodeStream(inputStream);

                   ByteArrayOutputStream stream = new ByteArrayOutputStream();
                    byte[] byteArray = stream.toByteArray();

                    imageView.setImageBitmap(bm);

                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

0

Найшвидший спосіб відкрити зображення з галереї чи камери.

Оригінальна довідка: отримати зображення з галереї в Android програмно

Наступний метод отримає зображення з галереї чи камери та покаже його у ImageView. Вибране зображення буде зберігатися всередині.

код для XML

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.exampledemo.parsaniahardik.uploadgalleryimage.MainActivity">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/btn"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="20dp"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text="Capture Image and upload to server" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Below image is fetched from server"
        android:layout_marginTop="5dp"
        android:textSize="23sp"
        android:gravity="center"
        android:textColor="#000"/>

    <ImageView
        android:layout_width="300dp"
        android:layout_height="300dp"
        android:layout_gravity="center"
        android:layout_marginTop="10dp"
        android:scaleType="fitXY"
        android:src="@mipmap/ic_launcher"
        android:id="@+id/iv"/>

</LinearLayout>

Клас JAVA

import android.content.Intent;
import android.graphics.Bitmap;
import android.media.MediaScannerConnection;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;
import com.androidquery.AQuery;
import org.json.JSONException;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Calendar;
import java.util.HashMap;

public class MainActivity extends AppCompatActivity implements AsyncTaskCompleteListener{

    private ParseContent parseContent;
    private Button btn;
    private ImageView imageview;
    private static final String IMAGE_DIRECTORY = "/demonuts_upload_camera";
    private final int CAMERA = 1;
    private AQuery aQuery;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        parseContent = new ParseContent(this);
        aQuery = new AQuery(this);

        btn = (Button) findViewById(R.id.btn);
        imageview = (ImageView) findViewById(R.id.iv);

        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
                startActivityForResult(intent, CAMERA);
            }
        });

    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {

        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == this.RESULT_CANCELED) {
            return;
        }
        if (requestCode == CAMERA) {
            Bitmap thumbnail = (Bitmap) data.getExtras().get("data");
            String path = saveImage(thumbnail);
            try {
                uploadImageToServer(path);
            } catch (IOException e) {
                e.printStackTrace();
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
    }

    private void uploadImageToServer(final String path) throws IOException, JSONException {

        if (!AndyUtils.isNetworkAvailable(MainActivity.this)) {
            Toast.makeText(MainActivity.this, "Internet is required!", Toast.LENGTH_SHORT).show();
            return;
        }

        HashMap<String, String> map = new HashMap<String, String>();
        map.put("url", "https://demonuts.com/Demonuts/JsonTest/Tennis/uploadfile.php");
        map.put("filename", path);
        new MultiPartRequester(this, map, CAMERA, this);
        AndyUtils.showSimpleProgressDialog(this);
    }

    @Override
    public void onTaskCompleted(String response, int serviceCode) {
        AndyUtils.removeSimpleProgressDialog();
        Log.d("res", response.toString());
        switch (serviceCode) {

            case CAMERA:
                if (parseContent.isSuccess(response)) {
                    String url = parseContent.getURL(response);
                    aQuery.id(imageview).image(url);
                }
        }
    }

    public String saveImage(Bitmap myBitmap) {
        ByteArrayOutputStream bytes = new ByteArrayOutputStream();
        myBitmap.compress(Bitmap.CompressFormat.JPEG, 90, bytes);
        File wallpaperDirectory = new File(
                Environment.getExternalStorageDirectory() + IMAGE_DIRECTORY);
        // have the object build the directory structure, if needed.
        if (!wallpaperDirectory.exists()) {
            wallpaperDirectory.mkdirs();
        }

        try {
            File f = new File(wallpaperDirectory, Calendar.getInstance()
                    .getTimeInMillis() + ".jpg");
            f.createNewFile();
            FileOutputStream fo = new FileOutputStream(f);
            fo.write(bytes.toByteArray());
            MediaScannerConnection.scanFile(this,
                    new String[]{f.getPath()},
                    new String[]{"image/jpeg"}, null);
            fo.close();
            Log.d("TAG", "File Saved::--->" + f.getAbsolutePath());

            return f.getAbsolutePath();
        } catch (IOException e1) {
            e1.printStackTrace();
        }
        return "";
    }
}

0

ось мій приклад, може бути не так, як ваш випадок.


припускаючи, що ви отримуєте формат base64 від свого постачальника API, дайте йому ім’я та розширення файлу, збережіть його до певного місця у файловій системі.

public static void shownInBuiltInGallery(final Context ctx, String strBase64Image, final String strFileName, final String strFileExtension){

new AsyncTask<String, String, File>() {
    @Override
    protected File doInBackground(String... strBase64Image) {

        Bitmap bmpImage = convertBase64StringToBitmap(strBase64Image[0], Base64.NO_WRAP);

        if(bmpImage == null) {
            cancel(true);
            return null;
        }

        byte[] byImage = null;

        if(strFileExtension.compareToIgnoreCase(FILE_EXTENSION_JPG) == 0) {
            byImage = convertToJpgByte(bmpImage); // convert bitmap to binary for latter use
        } else if(strFileExtension.compareToIgnoreCase(FILE_EXTENSION_PNG) == 0){
            byImage = convertToPngByte(bmpImage); // convert bitmap to binary for latter use
        } else if(strFileExtension.compareToIgnoreCase(FILE_EXTENSION_BMP) == 0){
            byImage = convertToBmpByte(bmpImage); // convert bitmap to binary for latter use
        } else {
            cancel(true);
            return null;
        }

        if(byImage == null) {
            cancel(true);
            return null;
        }

        File imageFolder = ctx.getExternalCacheDir();

        if(imageFolder.exists() == false){
            if(imageFolder.mkdirs() == false){
                cancel(true);
                return null;
            }
        }

        File imageFile = null;

        try {
            imageFile = File.createTempFile(strFileName, strFileExtension, imageFolder);
        } catch (IOException e){
            e.printStackTrace();
        }

        if(imageFile == null){
            cancel(true);
            return null;
        }

        if (imageFile.exists() == true) {
            if(imageFile.delete() == false){
                cancel(true);
                return null;
            }
        }

        FileOutputStream fos = null;

        try {
            fos = new FileOutputStream(imageFile.getPath());
            fos.write(byImage);
            fos.flush();
            fos.close();
        } catch (java.io.IOException e) {
            e.printStackTrace();
        } finally {
            fos = null;
        }

        return imageFile;
    }

    @Override
    protected void onPostExecute(File file) {
        super.onPostExecute(file);

            String strAuthority = ctx.getPackageName() + ".provider";
            Uri uriImage = FileProvider.getUriForFile(ctx, strAuthority, file);

            Intent intent = new Intent(Intent.ACTION_VIEW);
            intent.setDataAndType(uriImage, "image/*");
            intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            ctx.startActivity(intent);

    }
}.execute(strBase64Image);}

Не забудьте створити належного постачальника файлів на першому місці в AndroidManifest.xml

        <provider
        android:name="android.support.v4.content.FileProvider"
        android:authorities="${applicationId}.provider"
        android:exported="false"
        android:grantUriPermissions="true">

        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_paths"/>
    </provider>

де шлях до файлу - xml у ... / res / xml / file_path.xml

<?xml version="1.0" encoding="utf-8"?>

<external-files-path name="external_files" path="Accessory"/>

<external-path name="ex_Download" path="Download/" />
<external-path name="ex_Pictures" path="Pictures/" />

<external-files-path name="my_Download" path="Download/" />
<external-files-path name="my_Pictures" path="Pictures/" />
<external-cache-path name="my_cache" path="." />

<files-path name="private_Download" path="Download/" />
<files-path name="private_Pictures" path="Pictures/" />
<cache-path name="private_cache" path="." />


Якщо коротко розповісти, спершу готовий постачальник файлів, передайте Uri інтенту для відомого та доступного джерела зображення, інакше збережіть картинку в потрібному місці, а потім передайте розташування (як Uri) в Intent.

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