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


Я разрабатываю приложение для Android 2.1 вверх. Я хочу, чтобы мои пользователи могли выбрать изображение профиля в моем приложении (я не использую структуру контактов).

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

Я могу сделать один или другой, но не оба.

Если я перейду непосредственно в режим камеры с помощью MediaStore.ACTION_IMAGE_CAPTURE тогда нет возможности упасть в галерею.

Если я иду прямо в галерею, используя намерение.ACTION_PICK тогда я могу выбрать изображение, но если я нажму кнопку камеры (в правом верхнем углу галереи), то будет запущен новый намерение камеры. Таким образом, любой снимок, который сделан, не возвращается непосредственно к моему заявлению. (Конечно, вы можете нажать кнопку назад, чтобы вернуться в галерею и выбирать оттуда, но это лишний ненужный шаг и вообще не понятный).

Так есть ли способ объединить оба или я собираюсь предложить меню, чтобы сделать один или другой из моего приложения? Похоже, это будет общий случай использования...неужели я чего-то не понимаю?

4 65

4 ответа:

обновление: другой ответ, используя EXTRA_INITIAL_INTENTS, является лучшим на данный момент. В то время я написал свой ответ, EXTRA_INITIAL_INTENTS еще не существует, так как он был добавлен в API уровня 5.

Так есть ли способ объединить оба или я собираюсь предложить меню сделайте одно или другое изнутри моего заявление?

написать свою собственную галерею, которая имеет функции, которые вы желаете.

Я бы подумал, что меню будет упроститься.

Кажется, что это было бы общее использование случай...неужели я чего-то не понимаю?

разработчик рядом с вами будет думать, что галерея должна позволить вам выбрать из местной галереи или же выскочить на Flickr, чтобы сделать выбор оттуда. Другой разработчик будет думать, что камера должна не только позволить "сделать снимок" с помощью камеры, но и "сделать снимок", выбрав что-то из галереи, перевернув вещи так, как Вы себе представляете оно. Еще один разработчик будет думать, что галерея должна позволить выбирать из локальной галереи, или Flickr, или камеры, или сетевой веб-камеры. Еще один разработчик подумает, что галерея глупа, и пользователи должны просто выбирать файлы через проводник. И так далее.

все это в среде (мобильные телефоны), где flash для ОС находится на высоком уровне.

следовательно, ИМХО, это не совсем шокирует, что основная команда Android решила предоставить строительные блоки для вас, чтобы собрать, как вы считаете нужным, а не пытаться вместить все возможные модели.

вы можете попробовать сделать что-то вроде этого:

// ...
// Within your enclosing Class
// ...
private static final int SELECT_PICTURE = 1;

// ... 

Intent pickIntent = new Intent();
pickIntent.setType("image/*");
pickIntent.setAction(Intent.ACTION_GET_CONTENT);

Intent takePhotoIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

String pickTitle = "Select or take a new Picture"; // Or get from strings.xml
Intent chooserIntent = Intent.createChooser(pickIntent, pickTitle);
chooserIntent.putExtra
(
  Intent.EXTRA_INITIAL_INTENTS, 
  new Intent[] { takePhotoIntent }
);

startActivityForResult(chooserIntent, SELECT_PICTURE);

чтобы узнать, как обрабатывать результат activitiy, пожалуйста, обратитесь к этот вопрос


Примечание: критическая точка заключается в том, как определить, была ли использована камера или галерея. Это показано в следующем примере кода: https://stackoverflow.com/a/12347567/294884

в своей деятельности вы можете действовать следующим образом:

private static final int REQUEST_CODE_PICTURE= 1;

    /**
     * Click on View to change photo. Sets into View of your layout, android:onClick="clickOnPhoto"
     * @param view View
     */
    public void clickOnPhoto(View view) {
        Intent pickIntent = new Intent();
        pickIntent.setType("image/*");
        pickIntent.setAction(Intent.ACTION_GET_CONTENT);
        Intent takePhotoIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        String pickTitle = "Take or select a photo";
        Intent chooserIntent = Intent.createChooser(pickIntent, pickTitle);
        chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent[] { takePhotoIntent });
        startActivityForResult(chooserIntent, REQUEST_CODE_PICTURE);
    }

затем всегда добавляйте в свою активность метод onActivityResult:

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == REQUEST_CODE_PICTURE && resultCode == Activity.RESULT_OK) {
            if (data == null) {
                return;
            }
            try {
                InputStream inputStream = getContentResolver().openInputStream(data.getData());
                Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
                imgPhoto.setImageBitmap(bitmap);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }
    }

мой ответ почти идентичен решению @Macarse, но я также добавляю дополнительное намерение показать приложения галереи (например, Google Photos) и написан в Kotlin:

val REQUEST_CODE_GET_IMAGE = 101

private fun addProfileImage() {
    val pickImageFileIntent = Intent()
    pickImageFileIntent.type = "image/*"
    pickImageFileIntent.action = Intent.ACTION_GET_CONTENT

    val pickGalleryImageIntent = Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI)

    val captureCameraImageIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)

    val pickTitle = "Capture from camera or Select from gallery the Profile photo"
    val chooserIntent = Intent.createChooser(pickImageFileIntent, pickTitle)
    chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, arrayOf(captureCameraImageIntent, pickGalleryImageIntent))
    startActivityForResult(chooserIntent, REQUEST_CODE_GET_IMAGE)
}

бонус пример:

private var imageTempFile: File? = null
private var imageMimeType: String? = null

private fun extractImage(intent: Intent?) {
    val imageUri = intent?.data
    imageUri?.let {
        Glide.with(this)
                .load(imageUri)
                .into(profileImageCiv)
        imageTempFile = MediaUtils.copyContentFromUriToCacheFile(this, imageUri, Settings.DIRECTORY_CACHE_TEMP_PROFILE_IMAGE)
        imageMimeType = MediaUtils.getMimeType(this, imageUri)
    } ?: run {
        intent?.extras?.get("data")?.let { bitmap ->    // Bitmap was returned as raw bitmap
            Glide.with(this)
                    .load(bitmap)
                    .into(profileImageCiv)
            imageTempFile = MediaUtils.writeBitmapToCacheFile(this, bitmap as Bitmap, Settings.DIRECTORY_CACHE_TEMP_PROFILE_IMAGE)
            imageMimeType = "image/jpeg"    // The bitmap was compressed as JPEG format. The bitmap itself doesn't have any format associated to it
        } ?: run {
            imageTempFile = null
            imageMimeType = null
            Log.e("Intent data is null.")
            Log.d("Error during photo selection")
        }
    }
}