Намерение выбирать между камерой или галереей в Android

Я пытаюсь запустить намерение выбрать изображение с камеры или галереи Android. Я проверил этот пост, и в настоящее время мой код близок к работе:

private Intent getPickIntent() {
    final List<Intent> intents = new ArrayList<Intent>();
    if (allowCamera) {
        setCameraIntents(intents, cameraOutputUri);
    }
    if (allowGallery) {
        intents.add(new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI));
    }

    if (intents.isEmpty()) return null;
    Intent result = Intent.createChooser(intents.remove(0), null);
    if (!intents.isEmpty()) {
        result.putExtra(Intent.EXTRA_INITIAL_INTENTS, intents.toArray(new Parcelable[] {}));
    }
    return result;
}

private void setCameraIntents(List<Intent> cameraIntents, Uri output) {
    final Intent captureIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
    final PackageManager packageManager = context.getPackageManager();
    final List<ResolveInfo> listCam = packageManager.queryIntentActivities(captureIntent, 0);
    for (ResolveInfo res : listCam) {
        final String packageName = res.activityInfo.packageName;
        final Intent intent = new Intent(captureIntent);
        intent.setComponent(new ComponentName(res.activityInfo.packageName, res.activityInfo.name));
        intent.setPackage(packageName);
        intent.putExtra(MediaStore.EXTRA_OUTPUT, output);
        cameraIntents.add(intent);
    }
}

Когда я устанавливаю allowCamera=true он работает правильно.

Когда я устанавливаю allowGallery=true он показывает следующее:

enter image description here

Но если я установлю allowCamera=true и allowGallery =true показан следующий allowGallery =true:

enter image description here

И если вы выберете Android System то будет показан первый выбор.

Я бы хотел, чтобы выбор был примерно таким:

enter image description here

Как я могу "расширить" опцию Android System?

Ответ 1

В вашем связанном сообщении вы можете найти решение. Разница с вашим кодом заключается в том, как создается намерение галереи:

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

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

В комментарии этого ответа вы найдете разницу между ACTION_PICK и ACTION_GET_CONTENT.

Есть несколько доступных решений, которые рекомендуют использовать настраиваемый диалог. Но в этом диалоговом окне не будет значков стандартов (см. Develter docs здесь). Поэтому я рекомендую остановиться на вашем решении и просто исправить проблему с иерархией.

Ответ 2

            Intent galleryintent = new Intent(Intent.ACTION_GET_CONTENT, null);
            galleryintent.setType("image/*");

            Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);

            Intent chooser = new Intent(Intent.ACTION_CHOOSER);
            chooser.putExtra(Intent.EXTRA_INTENT, galleryintent);
            chooser.putExtra(Intent.EXTRA_TITLE, "Select from:");

            Intent[] intentArray = { cameraIntent };
            chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentArray);
            startActivityForResult(chooser, REQUEST_PIC);

Ответ 3

## Intent to choose between Camera and Gallery Heading and can crop image after capturing from camera ##


public void captureImageCameraOrGallery() {

        final CharSequence[] options = { "Take photo", "Choose from library",
                "Cancel" };
        AlertDialog.Builder builder = new AlertDialog.Builder(
                Post_activity.this);

        builder.setTitle("Select");

        builder.setItems(options, new DialogInterface.OnClickListener() {

            @Override
            public void onClick(DialogInterface dialog, int which) {
                // TODO Auto-generated method stub
                if (options[which].equals("Take photo")) {
                    try {
                        Intent cameraIntent = new Intent(
                                android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
                        startActivityForResult(cameraIntent, TAKE_PICTURE);
                    } catch (ActivityNotFoundException ex) {
                        String errorMessage = "Whoops - your device doesn't support capturing images!";

                    }

                } else if (options[which].equals("Choose from library")) {
                    Intent intent = new Intent(
                            Intent.ACTION_PICK,
                            android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
                    startActivityForResult(intent, ACTIVITY_SELECT_IMAGE);
                } else if (options[which].equals("Cancel")) {
                    dialog.dismiss();

                }

            }
        });
        dialog = builder.create();
        dialog.getWindow().getAttributes().windowAnimations = R.style.dialog_animation;

        dialog.show();

    }

public void onActivityResult(int requestcode, int resultcode, Intent intent) {
        super.onActivityResult(requestcode, resultcode, intent);
        if (resultcode == RESULT_OK) {
            if (requestcode == TAKE_PICTURE) {
                picUri = intent.getData();
                startCropImage();
            } else if (requestcode == PIC_CROP) {
                Bitmap photo = (Bitmap) intent.getExtras().get("data");
                Drawable drawable = new BitmapDrawable(photo);
                backGroundImageLinearLayout.setBackgroundDrawable(drawable);
            } else if (requestcode == ACTIVITY_SELECT_IMAGE) {
                Uri selectedImage = intent.getData();
                String[] filePath = { MediaStore.Images.Media.DATA };
                Cursor c = getContentResolver().query(selectedImage, filePath,
                        null, null, null);
                c.moveToFirst();
                int columnIndex = c.getColumnIndex(filePath[0]);
                String picturePath = c.getString(columnIndex);
                c.close();
                Bitmap thumbnail = (BitmapFactory.decodeFile(picturePath));
                Drawable drawable = new BitmapDrawable(thumbnail);
                backGroundImageLinearLayout.setBackgroundDrawable(drawable);

            }
        }
    }

private void startCropImage() {
        try {
            Intent cropIntent = new Intent("com.android.camera.action.CROP");
            cropIntent.setDataAndType(picUri, "image/*");
            cropIntent.putExtra("crop", "true");
            cropIntent.putExtra("aspectX", 1);
            cropIntent.putExtra("aspectY", 1);
            // indicate output X and Y
            cropIntent.putExtra("outputX", 256);
            cropIntent.putExtra("outputY", 256);
            // retrieve data on return
            cropIntent.putExtra("return-data", true);
            // start the activity - we handle returning in onActivityResult
            startActivityForResult(cropIntent, PIC_CROP);
        } catch (ActivityNotFoundException anfe) {
            // display an error message
            String errorMessage = "Whoops - your device doesn't support the crop action!";
            Toast toast = Toast
                    .makeText(this, errorMessage, Toast.LENGTH_SHORT);
            toast.show();
        }
    }

Ответ 4

Вам может потребоваться создать для этого пользовательский диалог:

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

private void ChooseGallerOrCamera() {
    final CharSequence[] items = { "Take Photo", "Choose from Gallery",
            "Cancel" };

    AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
    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);
                File f = new File(android.os.Environment
                        .getExternalStorageDirectory(), "MyImage.jpg");
                intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(f));
                startActivityForResult(intent, REQUEST_CAMERA);
            } else if (items[item].equals("Choose from Gallery")) {
                Intent intent = new Intent(
                        Intent.ACTION_PICK,
                        android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
                intent.setType("image/*");
                startActivityForResult(
                        Intent.createChooser(intent, "Select File"),
                        SELECT_FILE);
            } else if (items[item].equals("Cancel")) {
                dialog.dismiss();
            }
        }
    });
    builder.show();
}

И код для обработки onActivityResult():

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode == RESULT_OK) {
        Bitmap mBitmap;
        if (requestCode == REQUEST_CAMERA) {
            File camFile = new File(Environment.getExternalStorageDirectory()
                    .toString());
            for (File temp : camFile.listFiles()) {
                if (temp.getName().equals("MyImage.jpg")) {
                    camFile = temp;
                    break;
                }
            }
            try {

                BitmapFactory.Options btmapOptions = new BitmapFactory.Options();

                mBitmap = BitmapFactory.decodeFile(camFile.getAbsolutePath(),
                        btmapOptions);
                //Here you have the bitmap of the image from camera

            } catch (Exception e) {
                e.printStackTrace();
            }
        } else if (requestCode == SELECT_FILE) {
            Uri selectedImageUri = data.getData();

            String tempPath = getPath(selectedImageUri, MyActivity.this);
            BitmapFactory.Options btmapOptions = new BitmapFactory.Options();
            mBitmap = BitmapFactory.decodeFile(tempPath, btmapOptions);

            //Here you have the bitmap of the image from gallery
        }
    }
}

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

EDIT: Попробуйте использовать это:

private void letUserTakeUserTakePicture() {

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

    takePhotoIntent.putExtra(MediaStore.EXTRA_OUTPUT,
            Uri.fromFile(getTempFile(getActivity())));

    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, Values.REQ_CODE_TAKEPICTURE);
}

Ответ 5

Намерение показать камеру и видео файлы в окне выбора активности:

    Intent galleryintent = new Intent(Intent.ACTION_GET_CONTENT, null);
    galleryintent.setType("video/*");

    Intent cameraIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);

    Intent chooser = new Intent(Intent.ACTION_CHOOSER);
    chooser.putExtra(Intent.EXTRA_INTENT, galleryintent);
    chooser.putExtra(Intent.EXTRA_TITLE, "Select from:");

    Intent[] intentArray = { cameraIntent };
    chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentArray);
    startActivityForResult(chooser, REQUEST_VIDEO_CAPTURE);

Ответ 6

Ваш код уже очень достигнут цели. Просто поменяйте галерею и добавьте порядок камеры.

if (allowGallery) {
    intents.add(new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI));
}
if (allowCamera) {
    setCameraIntents(intents, cameraOutputUri);
}

Вот мой результат теста. Разница во внешнем виде, так как моя ОС - Android Nougat (7.0)

Первый скриншот в вашем заказе, второй после обмена. Как вы сказали, в первой ситуации нажмите на системный логотип, чтобы увидеть элементы галереи.

enter image description here enter image description here