Android ACTION_IMAGE_CAPTURE Intent

Drew picture Drew · Dec 15, 2009 · Viewed 180.1k times · Source

We are trying to use the native camera app to let the user take a new picture. It works just fine if we leave out the EXTRA_OUTPUT extra and returns the small Bitmap image. However, if we putExtra(EXTRA_OUTPUT,...) on the intent before starting it, everything works until you try to hit the "Ok" button in the camera app. The "Ok" button just does nothing. The camera app stays open and nothing locks up. We can cancel out of it, but the file never gets written. What exactly do we have to do to get ACTION_IMAGE_CAPTURE to write the picture taken to a file?

Edit: This is done via the MediaStore.ACTION_IMAGE_CAPTURE intent, just to be clear

Answer

yanokwa picture yanokwa · Dec 19, 2009

this is a well documented bug in some versions of android. that is, on google experience builds of android, image capture doesn't work as documented. what i've generally used is something like this in a utilities class.

public boolean hasImageCaptureBug() {

    // list of known devices that have the bug
    ArrayList<String> devices = new ArrayList<String>();
    devices.add("android-devphone1/dream_devphone/dream");
    devices.add("generic/sdk/generic");
    devices.add("vodafone/vfpioneer/sapphire");
    devices.add("tmobile/kila/dream");
    devices.add("verizon/voles/sholes");
    devices.add("google_ion/google_ion/sapphire");

    return devices.contains(android.os.Build.BRAND + "/" + android.os.Build.PRODUCT + "/"
            + android.os.Build.DEVICE);

}

then when i launch image capture, i create an intent that checks for the bug.

Intent i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
if (hasImageCaptureBug()) {
    i.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File("/sdcard/tmp")));
} else {
    i.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
}
startActivityForResult(i, mRequestCode);

then in activity that i return to, i do different things based on the device.

protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
     switch (requestCode) {
         case GlobalConstants.IMAGE_CAPTURE:
             Uri u;
             if (hasImageCaptureBug()) {
                 File fi = new File("/sdcard/tmp");
                 try {
                     u = Uri.parse(android.provider.MediaStore.Images.Media.insertImage(getContentResolver(), fi.getAbsolutePath(), null, null));
                     if (!fi.delete()) {
                         Log.i("logMarker", "Failed to delete " + fi);
                     }
                 } catch (FileNotFoundException e) {
                     e.printStackTrace();
                 }
             } else {
                u = intent.getData();
            }
    }

this saves you having to write a new camera app, but this code isn't great either. the big problems are

  1. you never get full sized images from the devices with the bug. you get pictures that are 512px wide that are inserted into the image content provider. on devices without the bug, everything works as document, you get a big normal picture.

  2. you have to maintain the list. as written, it is possible for devices to be flashed with a version of android (say cyanogenmod's builds) that has the bug fixed. if that happens, your code will crash. the fix is to use the entire device fingerprint.