Android: How to differentiate between multiple intents when using ActivityResultLauncher
Asked Answered
M

6

3

I am creating a Intent chooser to choose between a the phone camera app and the gallery/file manager.

Intent chooserIntent = Intent.createChooser(clickPhoto(),"Set Image Using");
                        chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS,openGallery());
                        startActivityForResult.launch(chooserIntent);

Click Photo method:

private Intent clickPhoto() {
        Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        ComponentName componentName = takePictureIntent.resolveActivity(requireActivity().getPackageManager());
        if (componentName != null) {
            try {
                createImageFile();
                mimeType = "image/*";
                ContentValues values = new ContentValues();
                values.put(MediaStore.Images.Media.DISPLAY_NAME, getNewFileName());
                values.put(MediaStore.Images.Media.MIME_TYPE, mimeType);
                values.put(MediaStore.Images.Media.RELATIVE_PATH, getImageDirectoryPath());

                Uri imageUri = requireActivity().getContentResolver().insert(MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL), values);
                if (imageUri != null) {
                    currentPhotoPath = imageUri.toString();
                    shareUri = imageUri;
                }
                takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);

               // initRequestCode(takePictureIntent, requestCode);
            } catch (IOException ioException) {
                Toast.makeText(requireContext(), ioException.getMessage().toString(), Toast.LENGTH_LONG).show();

            }

        }
        return takePictureIntent;
    }

Open gallery method:

private Intent openGallery(){
    mimeType = "image/*";
    Intent intent = new Intent();
    Uri collection = MediaStore.Video.Media.getContentUri(
            MediaStore.VOLUME_EXTERNAL);

    try {
         intent =
                new Intent(Intent.ACTION_PICK, collection).setType(mimeType);
        intent.resolveActivity(requireActivity().getPackageManager());

       // initRequestCode(intent, requestCode);
    } catch (ActivityNotFoundException e) {
        Toast.makeText(requireContext(), e.getLocalizedMessage(), Toast.LENGTH_LONG).show();
    }
    return intent;
}

The ActivityResultLauncher:

ActivityResultLauncher<Intent> startActivityForResult = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(),
            result -> {
                if (result.getResultCode() == Activity.RESULT_OK) {
                   //how to tell which intent the user selected ?
                }
            });

how do I know if the user took a piture using the camera or picked an image with the file picker ?

Mayberry answered 23/6, 2022 at 11:6 Comment(0)
B
2

You can put an extra integer to each intent before returning them which you can access in result, say:

Global variables

   final String SOURCE = "source";
    final int SOURCE_CAMERA = 0;
    final int SOURCE_GALLERY = 1;
   final int SOURCE_UNKNOWN = 2;

For camera

...
takePictureIntent.putExtra(SOURCE, SOURCE_CAMERA);
return takePictureIntent;

For gallery

..
intent.putExtra(SOURCE, SOURCE_GALLERY);
return intent;

ActivityResultLauncher

if (result.getResultCode() == Activity.RESULT_OK) {
        //Identify source
       int mySource = result.getData().getIntExtra(SOURCE, SOURCE_UNKNOWN )         
}
Barbaric answered 6/7, 2022 at 18:56 Comment(0)
E
0

You can differentiate like this,

If one method is for camera intent,

  private fun openCamera() {
        val takePictureIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
        if (takePictureIntent.resolveActivity(packageManager) != null) {
            cameraImageFile = getTempFile()
            cameraImageFile?.let {
                val imageUri = FileProvider.getUriForFile(
                    this,
                    "${BuildConfig.APPLICATION_ID}.fileprovider",
                    it
                )
                cameraLauncher.launch(imageUri)
            }
        }
    }

and another method is for gallery intent

    private fun openGallery() {
        galleryLauncher.launch("image/*")
    }

Then you can define them like below in activity,

//Todo for gallery
    private val galleryLauncher = registerForActivityResult(ActivityResultContracts.GetContent()) {
        //code here for gallery
    }

//Todo for camera
private val cameraLauncher = registerForActivityResult(ActivityResultContracts.TakePicture()) {
        //code here for camera
    }

That's it!

Editheditha answered 24/6, 2022 at 10:6 Comment(1)
Hi, I wanted to use the Intent chooser with both the intents merged and use a single ActivityResultContract. I don't have the option to use two buttons or a dialog and need to get a equivalent of getPickImageChooserIntent() working in android 10 and belowMayberry
J
0

Declare some variables

companion object{
    private const val CAMERA_ACTION =1
    private const val GALLERY_ACTION =2
    private const val CHOOSER_INTENT_ACTION =3
}
private var mActionTriggered =0

then follow

private fun openCamera() {
    mActionTriggered = CAMERA_ACTION
}

private fun openGallery() {
    mActionTriggered =GALLERY_ACTION
}

private fun openChooser() {
    mActionTriggered =CHOOSER_INTENT_ACTION
}

onResult

private val startActivityForResult = registerForActivityResult(
    StartActivityForResult()
) { result: ActivityResult ->
    if (result.resultCode == RESULT_OK) {
        when (mActionTriggered) {
            CAMERA_ACTION -> {
                mActionTriggered =  0
                //TODO your logics
            }
            GALLERY_ACTION -> {
                mActionTriggered =   0
                //TODO your logics
            }
            else -> {
                mActionTriggered =   0
                //TODO your logics
            }
        }
    }else{
        mActionTriggered =  0
    }
}
Jerkwater answered 30/6, 2022 at 11:53 Comment(0)
H
0

It feels a little overkill, but you can use the refinement mechanism of the chooser activity.

You need to implement the refinement activity yourself, but you can use the EXTRA_RESULT_RECEIVER that the chooser passes along to send back the result.

Intent refinementIntent = new Intent(this, RefinementActivity.class);
PendingIntent refinementPendingIntent = PendingIntent.getActivity(this, 0, refinementIntent, 0);
Intent clickPhotoIntent = clickPhoto();
Intent chooserIntent = Intent.createChooser(clickPhoto(),"Set Image Using");
chooserIntent.putExtra(
    Intent.EXTRA_CHOOSER_REFINEMENT_INTENT_SENDER, refinementPendingIntent.getIntentSender());
chooserIntent.putExtra(Intent.EXTRA_RESULT_RECEIVER, new ResultReceiver() {
  @Override
  public void onReceive(int resultCode, Bundle resultData) {
    Intent startedIntent = resultData.getParcelable("extra_selected_intent");
    // Check which intent was selected.
    // Note that this is called when the selection happened, before the
    // started activity returned. Probably what you want to do here is
    // cache the value in a field and then check it when you get
    // the activity result.
  }
});
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, openGallery());
startActivityForResult.launch(chooserIntent);

And then in RefinementActivity.java, you will need to send the selected intent back to the sender

@Override
public void onCreate(Bundle savedInstanceState) { 
  Intent selectedIntent = getIntent().getParcelableExtra(Intent.EXTRA_INTENT);
  ResultReceiver receiver = getIntent().getParcelableExtra(Intent.EXTRA_RESULT_RECEIVER);
  Bundle resultData = new Bundle();
  resultData.putParcelable("extra_selected_intent", selectedIntent);
  receiver.send(RESULT_OK, resultData);

  startActivity(selectedIntent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT));
  finish();
}
Hallett answered 1/7, 2022 at 19:34 Comment(0)
F
0

You can initialize Global Boolean value name isGallery and set it true in openGallery() and false in clickPhoto()

Like the code below:

private  boolean isGallery ;

private Intent clickPhoto() {
    isGallery = false;
}

private Intent openGallery() {
    isGallery = true;
}

Now your ActivityResultLauncher will be like this:

ActivityResultLauncher<Intent> startActivityForResult =
 registerForActivityResult(new ActivityResultContracts.StartActivityForResult(),
            result -> {
                if (result.getResultCode() == Activity.RESULT_OK) {
                    if (isGallery) {
                        // user picked an image with the file picker
                    } else {
                        // user took a picture using the camera
                    }

                }
            });
Forward answered 7/7, 2022 at 9:3 Comment(0)
B
0

Since you're using ActivityResultContracts.StartActivityForResult, the callback receives an instance of ActivityResult. So, you can get the intent by calling result.getData(), as below:

ActivityResultLauncher<Intent> startActivityForResult = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(),
            result -> {
                if (result.getResultCode() == Activity.RESULT_OK) {
                   Intent intent = result.getData();
                }
            });

However, if you have to create some conditions to decide what should be done according to the intent, I'd suggest create two different ActivityResultLauncher<Intent> and then launch them separately, so you will have two different callbacks, like:

ActivityResultLauncher<Intent> galleryLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(),
            result -> {
                if (result.getResultCode() == Activity.RESULT_OK) {
                   // what you have to do for gallery
                }
            });

ActivityResultLauncher<Intent> cameraLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(),
            result -> {
                if (result.getResultCode() == Activity.RESULT_OK) {
                   // what you have to do for camera
                }
            });

Bicentenary answered 1/8, 2023 at 19:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.