Chooser with camera intent and image picker intent

2019-02-17 04:15发布

问题:

I have created a chooser for either picking an image from file or for making a picture.

The code I use works fine on a Nexus 5, however when I try it on a Samsung S5, the chooser does not display the camera icons.

public Intent makePhotoIntent(String title, Context ctx, String uniqueImageId){

        //Build galleryIntent
        Intent galleryIntent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
        galleryIntent.setType("image/*");

        //Create chooser
        Intent chooser = Intent.createChooser(galleryIntent,title);

        if (checkexCameraHardware()){
            Intent  cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
            mTempImage = null;
            try {
                mTempImage = createImageFile(uniqueImageId);
            } catch (IOException e) {
                e.printStackTrace();
            }

            if (mTempImage != null){
                cameraIntent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, Uri.fromFile(mTempImage)); //add file ure (photo is saved here)
                Intent[] extraIntents = {cameraIntent};
                chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, extraIntents);
            }
        }
        return chooser;
    }

When I change the order in which the intents are added to the chooser the Samsung device does show the camera but only shows android-system as the file option.

public Intent makePhotoIntent(String title, Context ctx, String uniqueImageId){

        //Build galleryIntent
        Intent galleryIntent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
        galleryIntent.setType("image/*");

        //Create chooser
        Intent chooser = Intent.createChooser(galleryIntent,title);

        if (checkexCameraHardware()){
            Intent  cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
            mTempImage = null;
            try {
                mTempImage = createImageFile(uniqueImageId);
            } catch (IOException e) {
                e.printStackTrace();
            }

            if (mTempImage != null){
                cameraIntent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, Uri.fromFile(mTempImage)); //add file ure (photo is saved here)

                //I have to re-create the chooser here or the Samsung will not show the 'camera' icons.
                //I have to add the cameraIntent first.
                chooser = Intent.createChooser(cameraIntent,title);
                Intent[] extraIntents = {galleryIntent};

                //Intent[] extraIntents = {cameraIntent};
                chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, extraIntents);
            }
        }
        return chooser;
    }

Ideally I would like the Samsung device to show the same as the Nexus one when I add the gallery intent first. I can however not get this to work.

回答1:

  • If there are multiple intent matches for the extra intent (Intent.EXTRA_INITIAL_INTENTS) , it will show all of them combined under "Android System". When you click on "Android System", it will open another chooser with all those intent matches.

  • So, in your first screenshot for samsung device, the camera is indeed showing up - its just under "Android Systeem" (clicking this will show all camera intent matches).

  • If you make galleryIntent the extra instead of camera intent, it will combine all gallery related intents under "Android Systeem" (as seen in your 2nd screenshot for samsung device)

I guess the user can be confused if he does not know what this "Android Systeem" is !

  • With below solution you can directly add each one to your chooser

    In your 2nd code snippet, replace

    Intent[] extraIntents = {galleryIntent};
    chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, extraIntents);
    

    with :

    List<Intent> galleryIntents = new ArrayList<Intent>();
    PackageManager pm = getApplicationContext().getPackageManager();
    for (ResolveInfo ri: pm.queryIntentActivities(galleryIntent, PackageManager.MATCH_DEFAULT_ONLY)) {
        Intent intent = pm.getLaunchIntentForPackage(ri.activityInfo.packageName);
        intent.setAction(Intent.ACTION_PICK);
        galleryIntents.add(intent); 
    }
    chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, galleryIntents.toArray(new Parcelable[] {}));
    

This will manually add each matching intent directly to your chooser



回答2:

Try this way,hope this will help you to solve your problem

Please follow these steps and this is the best and simple way to pick image from gallery and from camera,

Step 1. declare globally variables

public static final int rcCC = 33;
boolean isCC = false;

Step 2 . Copy these methods and paste your code

void picPhoto() {
    String str[] = new String[] { "Camera", "Gallery" };
    new AlertDialog.Builder(getActivity()).setItems(str,
            new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    performImgPicAction(which);
                }
            }).show();
}

void performImgPicAction(int which) {
    Intent in;
    if (which == 1) {
        in = new Intent(
                Intent.ACTION_PICK,
                android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    } else {
        in = new Intent();
        in.setAction(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
    }
    startActivityForResult(
            Intent.createChooser(in, "Select profile picture"), which);
}

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


        try {
            if (rcCC == requestCode) {
                getActivity();
                if (resultCode == Activity.RESULT_OK) {
                    isCC = true;

                }
            } else {
                getActivity();
                if (resultCode == Activity.RESULT_OK) {
                    BitmapFactory.Options option = new BitmapFactory.Options();
                    option.inDither = false;
                    option.inPurgeable = true;
                    option.inInputShareable = true;
                    option.inTempStorage = new byte[32 * 1024];
                    option.inPreferredConfig = Bitmap.Config.RGB_565;
                    if (Build.VERSION.SDK_INT < 19) {
                        Uri selectedImageURI = data.getData();
                        uImage = BitmapFactory.decodeFile(Common.getPath(
                                selectedImageURI, getActivity()), option);
                    } else {

                        ParcelFileDescriptor pfd;
                        try {
                            pfd = context
                                    .getContentResolver()
                                    .openFileDescriptor(data.getData(), "r");
                            FileDescriptor fileDescriptor = pfd
                                    .getFileDescriptor();

                            uImage = BitmapFactory.decodeFileDescriptor(
                                    fileDescriptor, null, option);
                            pfd.close();

                        } catch (FileNotFoundException e) {
                            e.printStackTrace();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                    try {
                        ivProfile_image.setImageBitmap(uImage);

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

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

}

Step 3. call the method, where you want to pick pic and show dialog

  picPhoto();

Step 4.

Make user permission in manifest file,

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

Thanks



回答3:

Try in this way, i hope its works for you, i check in samsung galaxy tab 2 it show camera option

Declare your intent like this

  Intent galleryIntent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    galleryIntent.setType("image/*");

    //Create chooser
    Intent chooser = Intent.createChooser(galleryIntent,title);

        Intent  cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
        fileUri = getOutputMediaFileUri(uniqueImageId);
            cameraIntent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, fileUri); //add file ure (photo is saved here)
            Intent[] extraIntents = {cameraIntent};
            chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, extraIntents);

            startActivityForResult(chooser, Constants.SEND_IMAGE_FROM_CEMERA); 

and getOutputMediaFileUri(uniqueImageId) method this return you Uri of image

getOutputMediaFileUri(String uniqueImageId){

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


        File mediaFile;
            mediaFile = new File(mediaStorageDir.getPath() + File.separator
                    + "IMG_" + uniqueImageId + ".jpg");

        return Uri.fromFile(mediaFile);
}