misaka-10032
misaka-10032

Reputation: 179

Camera intent doesn't show in intent chooser

String chooseTitle = activity.getString(R.string.select_or_take_picture);

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

Intent galleryIntent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
galleryIntent.setType("image/*");
PackageManager pm = activity.getApplicationContext().getPackageManager();
for (ResolveInfo ri: pm.queryIntentActivities(galleryIntent, PackageManager.MATCH_DEFAULT_ONLY)) {
  Intent intent = pm.getLaunchIntentForPackage(ri.activityInfo.packageName);
  intent.setAction(Intent.ACTION_PICK);
  intents.add(intent);
}

Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE, photoUri);
for (ResolveInfo ri : pm.queryIntentActivities(cameraIntent, 0)) {
  Intent intent = pm.getLaunchIntentForPackage(ri.activityInfo.packageName);
  intents.add(intent);
}

Intent chooserIntent = Intent.createChooser(getIntent, chooseTitle);
chooserIntent.putExtra(
    Intent.EXTRA_INITIAL_INTENTS,
    intents.toArray(new Parcelable[] {})
);

By doing this way, the chooser shows:

Effect when I passed photoUri

The camera intent doesn't show at all.

But if I change the line

Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE, photoUri);

to

Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

It works just fine:

enter image description here

But the problem is, I really want to pass photoUri. How can I do with it?

I know a possible alternative is to write my own chooser dialog, but I do want to know if it's a bug in intent chooser, or if I don't use it correctly.

p.s. @dkarmazi, Here's how I generate Uri:

public Uri generatePhotoUri() {
  String timeStamp = new SimpleDateFormat("yyyyMMdd-HHmmss").format(new Date());
  String imageFileName = "XXX_" + timeStamp + ".jpg";
  File storageDir = Environment.getExternalStoragePublicDirectory(
      Environment.DIRECTORY_PICTURES);
  File imageFile = new File(storageDir, imageFileName);
  return Uri.fromFile(imageFile);
}

Here's my onActivityResult

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  switch (requestCode) {
    case PICK_PHOTO:
      if (resultCode != Activity.RESULT_OK) {
        break;
      }
      Uri source = data == null ?
          mPhotoUri : // take picture
          data.getData(); // choose from other app
      if (source == null) {
        break;
      }
      // TODO: do with source
      break;
  }
  //....
}

@dkarmazi, I've debugged it, and I make sure resultCode is RESULT_CANCELED.

Upvotes: 2

Views: 1654

Answers (2)

misaka-10032
misaka-10032

Reputation: 179

Thank @dkarmazi very much for helping me debug this issue. It seems we haven't enough reputation to refine the answer together, so I'm posting the solution here. Later in our chat we find a probable cause, and after my experimenting, now it works. It's actually an issue how I gather cameraIntents, so change this part of code

Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE, photoUri);
for (ResolveInfo ri : pm.queryIntentActivities(cameraIntent, 0)) {
  Intent intent = pm.getLaunchIntentForPackage(ri.activityInfo.packageName);
  intents.add(intent);
}

to

final Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
for(ResolveInfo ri : pm.queryIntentActivities(cameraIntent, 0)) {
  final String packageName = ri.activityInfo.packageName;
  final Intent intent = new Intent(cameraIntent);
  intent.setComponent(new ComponentName(ri.activityInfo.packageName, ri.activityInfo.name));
  intent.setPackage(packageName);
  intent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
  intents.add(intent);
}

Also need to change

Intent galleryIntent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
galleryIntent.setType("image/*");
PackageManager pm = activity.getApplicationContext().getPackageManager();
for (ResolveInfo ri: pm.queryIntentActivities(galleryIntent, PackageManager.MATCH_DEFAULT_ONLY)) {
  Intent intent = pm.getLaunchIntentForPackage(ri.activityInfo.packageName);
  intent.setAction(Intent.ACTION_PICK);
  intents.add(intent);
}

to

Intent galleryIntent = new Intent(Intent.ACTION_PICK);
galleryIntent.setType("image/*");
PackageManager pm = activity.getApplicationContext().getPackageManager();
for (ResolveInfo ri: pm.queryIntentActivities(galleryIntent, PackageManager.MATCH_DEFAULT_ONLY)) {
  final String packageName = ri.activityInfo.packageName;
  final Intent intent = new Intent(galleryIntent);
  intent.setComponent(new ComponentName(ri.activityInfo.packageName, ri.activityInfo.name));
  intent.setPackage(packageName);
  intents.add(intent);
}

I hate the boilerplate of it, but finally it works.

Upvotes: 0

dkarmazi
dkarmazi

Reputation: 3259

I recently worked on the same problem and here is my solution:

Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);

Then, once the user takes a picture, you should be able to access it by using the provided photoUri

Here is some documentation on EXTRA_OUTPUT and you can also lookup ACTION_IMAGE_CAPTURE on the same page.

UPDATE on Intent Chooser:

// we create intent chooser by picking one of the intents
Intent chooserIntent = Intent.createChooser(cameraIntent, getResources().getString(R.string.pick_action_string_for_user));
// then we add any additional intents
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent[] { getIntent });
// chooserIntent is ready
startActivityForResult(chooserIntent, requestCode);

Upvotes: 2

Related Questions