17

I want to display an image taken from the camera in an ImageView using

Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);

This works fine so far but after the user takes the photo using the chosen camera app a dialog (probably from the app) appears asking whether to save or delete the taken picture (at least on Android 2.3 and 4.2 using the default camera app).

I would like to skip this extra dialog and directly display the image in the ImageView (when onActivityResult gets called), because it means an extra interaction step for the user, which is unneccessary because he will have the possibilty to save or delete the photo in my app.

Is this possible using the simple ACTION_IMAGE_CAPTURE Intent or will I need something more complex like Camera Preview and SurfaceView for this purpose ?

Alex Cohn
  • 56,089
  • 9
  • 113
  • 307
fritz
  • 427
  • 1
  • 5
  • 13

6 Answers6

17

You ca use the SurfaceView to capture image

package com.camera;

import java.io.IOException;

import android.app.Activity;
import android.content.Intent;
import android.hardware.Camera;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class Camera_capture extends Activity implements SurfaceHolder.Callback {

private Camera mCamera;
private SurfaceView surfaceView;
private SurfaceHolder surfaceHolder;
private Button capture_image;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.camera_layout);
    capture_image = (Button) findViewById(R.id.capture_image);
    capture_image.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            capture();
        }
    });
    surfaceView = (SurfaceView) findViewById(R.id.surfaceview);
    surfaceHolder = surfaceView.getHolder();
    surfaceHolder.addCallback(Camera_capture.this);
    surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    try {
        mCamera = Camera.open();
        mCamera.setPreviewDisplay(surfaceHolder);
        mCamera.startPreview();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

private void capture() {
    mCamera.takePicture(null, null, null, new Camera.PictureCallback() {

        @Override
        public void onPictureTaken(byte[] data, Camera camera) {
            Toast.makeText(getApplicationContext(), "Picture Taken",
                    Toast.LENGTH_SHORT).show();
            Intent intent = new Intent();
            intent.putExtra("image_arr", data);
            setResult(RESULT_OK, intent);
            camera.stopPreview();
            if (camera != null) {
                camera.release();
                mCamera = null;
            }
            finish();
        }
    });
}

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
        int height) {
    Log.e("Surface Changed", "format   ==   " + format + ",   width  ===  "
            + width + ", height   ===    " + height);
    try {
        mCamera.setPreviewDisplay(holder);
        mCamera.startPreview();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

@Override
public void surfaceCreated(SurfaceHolder holder) {
    Log.e("Surface Created", "");
}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
    Log.e("Surface Destroyed", "");
}

@Override
protected void onPause() {
    super.onPause();
    if (mCamera != null) {
        mCamera.stopPreview();
        mCamera.release();
    }
}
}

And the layout file would be

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >

<SurfaceView
    android:id="@+id/surfaceview"
    android:layout_width="fill_parent"
    android:layout_weight="100"
    android:layout_height="wrap_content" />

<Button
    android:id="@+id/capture_image"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_weight="1"
    android:text="Capture" />

</LinearLayout>

Start this Camera_capture activity with startActivityForResult and onActivityResult you can get the image as byte array as

byte[] image = data.getExtras().getByteArray("image_arr");

where data is the received data.

Decode the byte array to Bitmap using

Bitmap bmp = BitmapFactory.decodeByteArray(image, 0,
                    image.length);

now set this Bitmap


Edit

As there is some problem while returning byte[], the byte[] should be save in a file and the path of the file should be sent to the previous Activity so that file can be read.

In onPictureTaken(), just add

String PATH = "Any path to store a file";
try {
    FileOutputStream fos=new FileOutputStream(PATH);

    fos.write(data);
    fos.close();
  }
  catch (java.io.IOException e) {

  }

and in place of :

intent.putExtra("image_arr", data);

write

intent.putExtra("image_path", PATH);

and receive this path in previous Activity's onActivityResult as :

String imagePath = data.getExtras().getString("image_path");
AnujMathur_07
  • 2,586
  • 2
  • 18
  • 25
  • 1
    Thanks! This gave me a good idea how it will work. I noticed that using the above code the image is rotated by 90 degrees and also after calling finish() the acitivity does not close , so it never gets back to the main activity - the app hangs... – fritz Apr 30 '13 at 12:47
  • will check for your issues. – AnujMathur_07 Apr 30 '13 at 13:04
  • 1
    for the rotated image u can try `Camera.Parameters p = mCamera.getParameters(); p.setRotation(90); mCamera.setParameters(p);` or `Camera.Parameters p = mCamera.getParameters(); p.set("rotation", 90); mCamera.setParameters(p);` – AnujMathur_07 Apr 30 '13 at 13:11
  • and for the app hanging issue, sorry but I did't find it. – AnujMathur_07 Apr 30 '13 at 13:13
  • It may be the same problem as described here: http://stackoverflow.com/questions/2264980/failed-binder-transaction-when-returning-camera-image – fritz Apr 30 '13 at 13:14
  • I think its a random issue. In that question `Colin O'Dell`'s answer looks good. You should do it like that. – AnujMathur_07 Apr 30 '13 at 13:19
  • Yes, it may also depend on the current image resolution ie. how much data will be passed as result argument, 5 MB may be too much...I'm now saving the image inside the capture activity, which takes a few seconds, and then call "finish()" while just passing the filename – fritz Apr 30 '13 at 13:35
  • I never found that issue, but know I'll take care of this in future.. thanks. :) – AnujMathur_07 Apr 30 '13 at 13:46
  • After I take the picture, the back button doesn't work anymore. I have tried overriding the back button to just call `finish()` but it doesn't allow anything to go through. – Ryan Newman Sep 15 '15 at 17:13
8

Use "android.intent.extra.quickCapture"

Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra("android.intent.extra.quickCapture",true);
if (intent.resolveActivity(getPackageManager()) != null) {
    startActivityForResult(intent, REQUEST_IMAGE_CAPTURE);
}
2

If your image is rotated, you can use this:

mCamera.setDisplayOrientation(90);

after

mCamera.startPreview();
Energy Dome
  • 153
  • 3
  • 8
1

You can not do it using the default intent. You will have to write a customer camera capture functionality where you can skip the preview with Ok and Cancel buttons.

Pleas see http://developer.android.com/guide/topics/media/camera.html#custom-camera

1

You can use the solution of AnujMathur_07, but if you do not want work with paths and files, in the method onPictureTaken, you can return the bitmap:

 @Override
            public void onPictureTaken(byte[] data, Camera camera) {
                Toast.makeText(getApplicationContext(), "Picture Taken",
                        Toast.LENGTH_SHORT).show();
                Intent intent = new Intent();

            Bitmap bmp = BitmapFactory.decodeByteArray(data, 0,
                    data.length);

            intent.putExtra("image", bmp);
            setResult(RESULT_OK, intent);
            camera.stopPreview();
            if (camera != null) {
                camera.release();
                mCamera = null;
            }
            finish();
        }

And in the method onActivityResult you can get bitmap:

 Bundle extras = data.getExtras();
 Bitmap imageBitmap = (Bitmap) extras.get("image");
Kampai
  • 22,848
  • 21
  • 95
  • 95
alexcornejo
  • 163
  • 1
  • 12
-3

Use MediaStore.EXTRA_OUTPUT param for you camera application running intent

intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
Eugene Popovich
  • 3,343
  • 2
  • 30
  • 33
  • Are you sure this fulfils the OPs desire to bypass the save/delete confirmation. It doesn't for me. – paulkayuk Apr 30 '13 at 10:36
  • This does not help, the dialog appears although I'm adding intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(Environment.getExternalStorageDirectory()+"/image11.jpg"))); – fritz Apr 30 '13 at 10:44
  • Here is the link to official documentation http://developer.android.com/guide/topics/media/camera.html#intent-image – Eugene Popovich Apr 30 '13 at 10:55
  • The documentation in the link posted by user527759 doesn't mention the extra "save / delete dialog". However, the dialog showed up using their demo code. – OneWorld Oct 09 '14 at 14:08