The ACTION_IMAGE_CAPTURE Fallacy
The documentation for
the new permission system in the M Developer Preview
has:
In many cases, you can choose between two ways for your app to perform a task. You can have your app ask for permission to perform the operation itself. Alternatively, you can have the app use an intent to have another app perform the task.
For example, suppose your app needs to be able to take pictures with the device camera. Your app can request the android.permission.CAMERA permission, which allows your app to access the camera directly. Your app would then use the camera APIs to control the camera and take a picture. This approach gives your app full control over the photography process, and lets you incorporate the camera UI into your app.
However, if you don���t need such control, you can just use an ACTION_IMAGE_CAPTURE intent to request an image. When you start the intent, the user is prompted to choose a camera app (if there isn���t already a default camera app), and that app takes the picture. The camera app returns the picture to your app���s onActivityResult() method.
Oh, if it were only this easy.
The theory is sound, but the practice is unrealistic. The problem is
three-fold:
The rules for what ACTION_IMAGE_CAPTURE is supposed to do are
fairly limited, at least in terms of what is documented
I am not aware that the CTS actually tests ACTION_IMAGE_CAPTURE
There is no test suite that I am aware of to test arbitrary
camera apps��� implementation of ACTION_IMAGE_CAPTURE, let alone anyone
actually using it to test their camera apps
As a result, ACTION_IMAGE_CAPTURE is not reliable or consistent.
For example:
Some cameras will store photos taken in portrait mode as portrait
images. Some cameras will store photos taken in portrait mode as
landscape, setting an EXIF header to say ���hey, image viewer, could you
rotate this for me please, kthxbye���. Since BitmapFactory ignores
this header, Android apps frequently load these images as landscape,
ignoring the header. And either behavior is perfectly legitimate, because
ACTION_IMAGE_CAPTURE does not specify one way or another.
Some cameras will record images taken with the front-facing camera
as-is. Some will mirror the images, to make them appear more like what
the user saw in the camera preview. And either behavior is perfectly legitimate, because
ACTION_IMAGE_CAPTURE does not specify one way or another.
The documentation says that by default the camera should return
���a small sized image��� in an unfortunately undocumented Intent
extra (hint: the key is data). But there are no standards as to what
���a small sized image��� means. It has to be less than 1MB due to IPC
constraints, but whether it is a 120x80 thumbnail or a 512x512 image
is up to the camera app.
The documentation says that you can use EXTRA_OUTPUT to indicate
where the image should be written as a full-size image. But the documentation
does not state what valid values for EXTRA_OUTPUT are. Is that limited
only to file:// Uri values? Will a content:// Uri work, if the
provider supports write access? Again, any behavior of the camera is
perfectly fine, insofar as there is no right or wrong answer, even if
the behavior difference is important to developers.
Stack Overflow is littered with people trying to use ACTION_IMAGE_CAPTURE
and having difficulty dealing with the wide range of results from
camera apps. It���s the primary reason I wrote a library
to try to make it easier for apps to have consistent behavior, and why
I am rewriting that library (since my first attempt
gots issues, yo).
I sincerely wish I didn���t feel the need to write these things, as there
are lots of other things that I would like to do with my time.
Google, in the interests of granting implementors flexibility, has
constrained the practicality of using stuff like ACTION_IMAGE_CAPTURE.
Lots of implicit Intent actions tend to work OK, because they
do not return any results, and so are simply one-way communications
channels, like Web page links. But any implicit Intent that is
supposed to return results ��� basically, anything using
startActivityForResult() ��� has the potential to be unreliable,
if there are many implementations that offer to handle that Intent.
ACTION_IMAGE_CAPTURE is one of the worst in that regard.
Google���s recommendation of relying on third-party apps for things like
basic picture-taking still hold true, but only in cases where the app
needing the picture does not really care about the picture, and so whatever
the other app happens to hand back will be just fine, thanks. If Google
wants developers to rely on third-party apps for more than really
trivial stuff, Google needs to tighten up the contract between
both sides, so everybody knows what everybody is expecting.


