Діалогове вікно, щоб вибрати зображення з галереї чи з камери


122

Чи є стандартний спосіб зателефонувати у діалогове вікно, вибравши або вибрати зображення з камери, або отримати з галереї (наприклад, у вбудованій телефонній книзі чи Skype)?

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

Пристрій: Samsung Galaxy Tab
Android: 2.3.3


Подивіться на цю відповідь з наміром, який об’єднує обидва запити (Камера та Галерея) в унікальному намірі: stackoverflow.com/a/32475805/2232889
Маріо Веласко,

Відповіді:


192

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

Щоб зробити знімок з камери:

Intent takePicture = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(takePicture, 0);//zero can be replaced with any action code (called requestCode)

Щоб вибрати фото з галереї:

Intent pickPhoto = new Intent(Intent.ACTION_PICK,
           android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(pickPhoto , 1);//one can be replaced with any action code

onActivityResult код:

protected void onActivityResult(int requestCode, int resultCode, Intent imageReturnedIntent) { 
    super.onActivityResult(requestCode, resultCode, imageReturnedIntent); 
    switch(requestCode) {
    case 0:
        if(resultCode == RESULT_OK){  
            Uri selectedImage = imageReturnedIntent.getData();
            imageview.setImageURI(selectedImage);
        }

    break; 
    case 1:
        if(resultCode == RESULT_OK){  
            Uri selectedImage = imageReturnedIntent.getData();
            imageview.setImageURI(selectedImage);
        }
    break;
    }
}

Нарешті додайте цей дозвіл у файл маніфесту:

 <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

20
Дозвіл для камери не потрібно, оскільки він відкриває програму за замовчуванням.
tasomaniac

2
@Jeremy Ні, це не так. Якщо у вас взагалі немає дозволу, ви можете просто ним скористатися. Тому що не ваш додаток відкриває камеру. Нюанс полягає в тому, що якщо у вас є дозвіл і якщо користувач відхилив дозвіл, то використання цього Intentв якості резервного копіювання кидає SecurityException. Більше інформації: plus.google.com/+AndroidDevelopers/posts/e9kyM7VXajz
tasomaniac

2
Тепер потрібен дозвіл камери, щоб відкрити намір камери @tasomaniac
Саад Білал

26
з ACTION_IMAGE_CAPTURE я отримую imageReturnedIntent.getData () == null чому?
Xan

3
Згідно з офіційною документацією developer.android.com/training/camera/photobasics фотографування не зберігає зображення в Uri, поверненому з намірів getData (). Ви можете отримати ескіз лише з наміру результату (intent.getBundle (). Get ("data)). Повнорозмірне зображення можна записати у файл, підготовлений для цього, перш ніж викликати startActivityForResult.
marioc64

56

Я об'єднав кілька рішень, щоб зробити повну програму для вибору зображення з Галереї чи Камери. Це особливості утиліти ImagePicker (також у ліфті Github ):

  • Об'єднані наміри для запитів на Галерею та Камери.
  • Розмір розмірів вибраних великих зображень (наприклад: 2500 x 1600)
  • Оберніть зображення, якщо це необхідно

Знімок екрана:

Початковий намір ImagePicker

Редагувати : Ось фрагмент коду для об'єднання об'єднаних намірів для додатків Галерея та Камера разом. Повний код ви можете побачити на утиліті ImagePicker (також у вкладиші Github ):

public static Intent getPickImageIntent(Context context) {
    Intent chooserIntent = null;

    List<Intent> intentList = new ArrayList<>();

    Intent pickIntent = new Intent(Intent.ACTION_PICK,
            android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    Intent takePhotoIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    takePhotoIntent.putExtra("return-data", true);
    takePhotoIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(getTempFile(context)));
    intentList = addIntentsToList(context, intentList, pickIntent);
    intentList = addIntentsToList(context, intentList, takePhotoIntent);

    if (intentList.size() > 0) {
        chooserIntent = Intent.createChooser(intentList.remove(intentList.size() - 1),
                context.getString(R.string.pick_image_intent_text));
        chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentList.toArray(new Parcelable[]{}));
    }

    return chooserIntent;
}

private static List<Intent> addIntentsToList(Context context, List<Intent> list, Intent intent) {
    List<ResolveInfo> resInfo = context.getPackageManager().queryIntentActivities(intent, 0);
    for (ResolveInfo resolveInfo : resInfo) {
        String packageName = resolveInfo.activityInfo.packageName;
        Intent targetedIntent = new Intent(intent);
        targetedIntent.setPackage(packageName);
        list.add(targetedIntent);
    }
    return list;
}

4
Це прекрасно працює, Маріо. Дуже дякую! Я перевірив його на Samsung GT-I9100, LG L7, але він не вдається, коли ми намагаємось поставити зображення з камери в Nexus 6 з Android 6. Рішення додасть це до 58-ти рядків у ImagePicker.java:boolean isCamera = (imageReturnedIntent == null || imageReturnedIntent.getData() == null);
Габі Морено

1
Дякую @GabrielMorenoIbarra. Ви виправили це, тепер він є і в моєму коді.
Маріо Веласко

що таке getTempFileі як користуватися цією функцією? будь ласка, оновіть відповідь
Basheer AL-MOMANI

1
Це функція отримати тимчасовий файл. Перейдіть за посиланням і ви знайдете більш детальний сценарій
Mario Velasco

1
@Brainware, так, це залежить від версії Android. Подумайте про використання FileProviderдля API> = 23 і Uriменше.
CoolMind

19

Ця бібліотека робить її простою.

Просто зателефонуйте:

PickImageDialog.on(MainActivity.this, new PickSetup(BuildConfig.APPLICATION_ID));

Потім змусьте свою активність впровадити IPickResult і замініть цей спосіб нижче.

@Override
public void onPickResult(PickResult r) {
    if (r.getError() == null) {
        imageView.setImageBitmap(r.getBitmap());

        //or

        imageView.setImageURI(r.getUri());
    } else {
        //Handle possible errors
        //TODO: do what you have to do with r.getError();
    }
}

У мене є фотографії амазонки в моєму телефоні s7 edge коли колись я вибираю варіант галереї, це перенаправлення на сторінку входу в Amazon та на інші телефони, її добре .. але я тестую в s7 edge
nafees ahmed

Це дуже безладний підхід, може вплинути на весь код. Не знаю, чому хлопець створив окремий mvn repo.
Радість

Чи це дозволяє зображення з декількома виборами або зйомки з кількома заходами?
Аднан

12

Ви можете реалізувати цей код, щоб вибрати зображення з галереї чи камери: -

private ImageView imageview;
private Button btnSelectImage;
private Bitmap bitmap;
private File destination = null;
private InputStream inputStreamImg;
private String imgPath = null;
private final int PICK_IMAGE_CAMERA = 1, PICK_IMAGE_GALLERY = 2;

Тепер при події натискання кнопки ви можете викликати ваш метод вибору Зображення. Це всередині діяльності onCreate.

imageview = (ImageView) findViewById(R.id.imageview);
btnSelectImage = (Button) findViewById(R.id.btnSelectImage);

//OnbtnSelectImage click event...
btnSelectImage.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            selectImage();
        }
    });

Поза твоєю діяльністю.

// Select image from camera and gallery
private void selectImage() {
    try {
        PackageManager pm = getPackageManager();
        int hasPerm = pm.checkPermission(Manifest.permission.CAMERA, getPackageName());
        if (hasPerm == PackageManager.PERMISSION_GRANTED) {
            final CharSequence[] options = {"Take Photo", "Choose From Gallery","Cancel"};
            android.support.v7.app.AlertDialog.Builder builder = new android.support.v7.app.AlertDialog.Builder(activity);
            builder.setTitle("Select Option");
            builder.setItems(options, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int item) {
                    if (options[item].equals("Take Photo")) {
                        dialog.dismiss();
                        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                        startActivityForResult(intent, PICK_IMAGE_CAMERA);
                    } else if (options[item].equals("Choose From Gallery")) {
                        dialog.dismiss();
                        Intent pickPhoto = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
                        startActivityForResult(pickPhoto, PICK_IMAGE_GALLERY);
                    } else if (options[item].equals("Cancel")) {
                        dialog.dismiss();
                    }
                }
            });
            builder.show();
        } else
            Toast.makeText(this, "Camera Permission error", Toast.LENGTH_SHORT).show();
    } catch (Exception e) {
        Toast.makeText(this, "Camera Permission error", Toast.LENGTH_SHORT).show();
        e.printStackTrace();
    }
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    inputStreamImg = null;
    if (requestCode == PICK_IMAGE_CAMERA) {
        try {
            Uri selectedImage = data.getData();
            bitmap = (Bitmap) data.getExtras().get("data");
            ByteArrayOutputStream bytes = new ByteArrayOutputStream();
            bitmap.compress(Bitmap.CompressFormat.JPEG, 50, bytes);

            Log.e("Activity", "Pick from Camera::>>> ");

            String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date());
            destination = new File(Environment.getExternalStorageDirectory() + "/" +
                    getString(R.string.app_name), "IMG_" + timeStamp + ".jpg");
            FileOutputStream fo;
            try {
                destination.createNewFile();
                fo = new FileOutputStream(destination);
                fo.write(bytes.toByteArray());
                fo.close();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }

            imgPath = destination.getAbsolutePath();
            imageview.setImageBitmap(bitmap);

        } catch (Exception e) {
            e.printStackTrace();
        }
    } else if (requestCode == PICK_IMAGE_GALLERY) {
        Uri selectedImage = data.getData();
        try {
            bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), selectedImage);
            ByteArrayOutputStream bytes = new ByteArrayOutputStream();
            bitmap.compress(Bitmap.CompressFormat.JPEG, 50, bytes);
            Log.e("Activity", "Pick from Gallery::>>> ");

            imgPath = getRealPathFromURI(selectedImage);
            destination = new File(imgPath.toString());
            imageview.setImageBitmap(bitmap);

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

public String getRealPathFromURI(Uri contentUri) {
    String[] proj = {MediaStore.Audio.Media.DATA};
    Cursor cursor = managedQuery(contentUri, proj, null, null, null);
    int column_index = cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA);
    cursor.moveToFirst();
    return cursor.getString(column_index);
}

Нарешті, додайте камеру та напишіть зовнішній дозвіл на зберігання в AndroidManifest.xml

Це чудово працює для мене, сподіваюсь, що він буде працювати і для вас.


1
Я додаю дозвіл на камеру, але отримую помилку та показую "помилку дозволу камери"
roghayeh hosseini

7

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


1
Але зображення в цьому зразку перевернуто догори ногами
Сонячний

3

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

In onCreate ()

imageViewRound.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            selectImage();
        }
    });




    private void selectImage() {
    Constants.iscamera = true;
    final CharSequence[] items = { "Take Photo", "Choose from Library",
            "Cancel" };

     TextView title = new TextView(context);
     title.setText("Add Photo!");
        title.setBackgroundColor(Color.BLACK);
        title.setPadding(10, 15, 15, 10);
        title.setGravity(Gravity.CENTER);
        title.setTextColor(Color.WHITE);
        title.setTextSize(22);


    AlertDialog.Builder builder = new AlertDialog.Builder(
            AddContactActivity.this);



    builder.setCustomTitle(title);

    // builder.setTitle("Add Photo!");
    builder.setItems(items, new DialogInterface.OnClickListener() {

        @Override
        public void onClick(DialogInterface dialog, int item) {
            if (items[item].equals("Take Photo")) {
                // Intent intent = new
                // Intent(MediaStore.ACTION_IMAGE_CAPTURE);

                Intent intent = new Intent(
                        android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
                /*
                 * File photo = new
                 * File(Environment.getExternalStorageDirectory(),
                 * "Pic.jpg"); intent.putExtra(MediaStore.EXTRA_OUTPUT,
                 * Uri.fromFile(photo)); imageUri = Uri.fromFile(photo);
                 */
                // startActivityForResult(intent,TAKE_PICTURE);

                Intent intents = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

                fileUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE);

                intents.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);

                // start the image capture Intent
                startActivityForResult(intents, TAKE_PICTURE);

            } else if (items[item].equals("Choose from Library")) {
                Intent intent = new Intent(
                        Intent.ACTION_PICK,
                        android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
                intent.setType("image/*");
                startActivityForResult(
                        Intent.createChooser(intent, "Select Picture"),
                        SELECT_PICTURE);
            } else if (items[item].equals("Cancel")) {
                dialog.dismiss();
            }
        }
    });
    builder.show();
}




    @SuppressLint("NewApi")
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    switch (requestCode) {
    case SELECT_PICTURE:
        Bitmap bitmap = null;
        if (resultCode == RESULT_OK) {
            if (data != null) {


                try {
                    Uri selectedImage = data.getData();
                    String[] filePath = { MediaStore.Images.Media.DATA };
                    Cursor c = context.getContentResolver().query(
                            selectedImage, filePath, null, null, null);
                    c.moveToFirst();
                    int columnIndex = c.getColumnIndex(filePath[0]);
                    String picturePath = c.getString(columnIndex);
                    c.close();
                    imageViewRound.setVisibility(View.VISIBLE);
                    // Bitmap thumbnail =
                    // (BitmapFactory.decodeFile(picturePath));
                    Bitmap thumbnail = decodeSampledBitmapFromResource(
                            picturePath, 500, 500);

                    // rotated
                    Bitmap thumbnail_r = imageOreintationValidator(
                            thumbnail, picturePath);
                    imageViewRound.setBackground(null);
                    imageViewRound.setImageBitmap(thumbnail_r);
                    IsImageSet = true;
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }

        break;
    case TAKE_PICTURE:
        if (resultCode == RESULT_OK) {

            previewCapturedImage();

        }

        break;
    }

}



 @SuppressLint("NewApi")
private void previewCapturedImage() {
    try {
        // hide video preview

        imageViewRound.setVisibility(View.VISIBLE);

        // bimatp factory
        BitmapFactory.Options options = new BitmapFactory.Options();

        // downsizing image as it throws OutOfMemory Exception for larger
        // images
        options.inSampleSize = 8;

        final Bitmap bitmap = BitmapFactory.decodeFile(fileUri.getPath(),
                options);

        Bitmap resizedBitmap = Bitmap.createScaledBitmap(bitmap, 500, 500,
                false);

        // rotated
        Bitmap thumbnail_r = imageOreintationValidator(resizedBitmap,
                fileUri.getPath());

        imageViewRound.setBackground(null);
        imageViewRound.setImageBitmap(thumbnail_r);
        IsImageSet = true;
        Toast.makeText(getApplicationContext(), "done", Toast.LENGTH_LONG)
                .show();
    } catch (NullPointerException e) {
        e.printStackTrace();
    }
}






    // for roted image......
private Bitmap imageOreintationValidator(Bitmap bitmap, String path) {

    ExifInterface ei;
    try {
        ei = new ExifInterface(path);
        int orientation = ei.getAttributeInt(ExifInterface.TAG_ORIENTATION,
                ExifInterface.ORIENTATION_NORMAL);
        switch (orientation) {
        case ExifInterface.ORIENTATION_ROTATE_90:
            bitmap = rotateImage(bitmap, 90);
            break;
        case ExifInterface.ORIENTATION_ROTATE_180:
            bitmap = rotateImage(bitmap, 180);
            break;
        case ExifInterface.ORIENTATION_ROTATE_270:
            bitmap = rotateImage(bitmap, 270);
            break;
        }
    } catch (IOException e) {
        e.printStackTrace();
    }

    return bitmap;
}



private Bitmap rotateImage(Bitmap source, float angle) {

    Bitmap bitmap = null;
    Matrix matrix = new Matrix();
    matrix.postRotate(angle);
    try {
        bitmap = Bitmap.createBitmap(source, 0, 0, source.getWidth(),
                source.getHeight(), matrix, true);
    } catch (OutOfMemoryError err) {
        source.recycle();
        Date d = new Date();
        CharSequence s = DateFormat
                .format("MM-dd-yy-hh-mm-ss", d.getTime());
        String fullPath = Environment.getExternalStorageDirectory()
                + "/RYB_pic/" + s.toString() + ".jpg";
        if ((fullPath != null) && (new File(fullPath).exists())) {
            new File(fullPath).delete();
        }
        bitmap = null;
        err.printStackTrace();
    }
    return bitmap;
}




public static Bitmap decodeSampledBitmapFromResource(String pathToFile,
        int reqWidth, int reqHeight) {

    // First decode with inJustDecodeBounds=true to check dimensions
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeFile(pathToFile, options);

    // Calculate inSampleSize
    options.inSampleSize = calculateInSampleSize(options, reqWidth,
            reqHeight);

    Log.e("inSampleSize", "inSampleSize______________in storage"
            + options.inSampleSize);
    // Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false;
    return BitmapFactory.decodeFile(pathToFile, options);
}




public static int calculateInSampleSize(BitmapFactory.Options options,
        int reqWidth, int reqHeight) {
    // Raw height and width of image
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;

    if (height > reqHeight || width > reqWidth) {

        // Calculate ratios of height and width to requested height and
        // width
        final int heightRatio = Math.round((float) height
                / (float) reqHeight);
        final int widthRatio = Math.round((float) width / (float) reqWidth);

        // Choose the smallest ratio as inSampleSize value, this will
        // guarantee
        // a final image with both dimensions larger than or equal to the
        // requested height and width.
        inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;

    }

    return inSampleSize;
}




public String getPath(Uri uri) {
    String[] projection = { MediaStore.Images.Media.DATA };
    Cursor cursor = managedQuery(uri, projection, null, null, null);
    int column_index = cursor
            .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
    cursor.moveToFirst();
    return cursor.getString(column_index);
}






private static File getOutputMediaFile(int type) {

    // External sdcard location
    File mediaStorageDir = new File(
            Environment
                    .getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
            IMAGE_DIRECTORY_NAME);

    // Create the storage directory if it does not exist
    if (!mediaStorageDir.exists()) {
        if (!mediaStorageDir.mkdirs()) {
            Log.d(IMAGE_DIRECTORY_NAME, "Oops! Failed create "
                    + IMAGE_DIRECTORY_NAME + " directory");
            return null;
        }
    }

    // Create a media file name
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss",
            Locale.getDefault()).format(new Date());
    File mediaFile;
    if (type == MEDIA_TYPE_IMAGE) {
        mediaFile = new File(mediaStorageDir.getPath() + File.separator
                + "IMG_" + timeStamp + ".jpg");
    } else {
        return null;
    }

    return mediaFile;
}






public Uri getOutputMediaFileUri(int type) {
    return Uri.fromFile(getOutputMediaFile(type));
}

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

Якщо targetSdkVersion вище 24, то FileProvider використовується для надання доступу.

Створіть XML-файл (Шлях: res \ xml) provider_paths.xml

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="external_files" path="."/>
</paths>

Додайте постачальника в 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/provider_paths"/>
</provider>

і замінити

return Uri.fromFile(getOutputMediaFile(type));

До

               return FileProvider.getUriForFile(this,  BuildConfig.APPLICATION_ID + ".provider", getOutputMediaFile(type));
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.