android: Take camera picture without "save" / "delete" confirmation
Asked Answered
T

6

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 ?

Triolein answered 30/4, 2013 at 10:24 Comment(0)
S
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");
Stodgy answered 30/4, 2013 at 10:54 Comment(9)
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...Triolein
will check for your issues.Stodgy
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);Stodgy
and for the app hanging issue, sorry but I did't find it.Stodgy
It may be the same problem as described here: #2265480Triolein
I think its a random issue. In that question Colin O'Dell's answer looks good. You should do it like that.Stodgy
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 filenameTriolein
I never found that issue, but know I'll take care of this in future.. thanks. :)Stodgy
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.Anthozoan
A
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);
}
Adornment answered 14/7, 2016 at 10:7 Comment(2)
Did not change anything, although that would have been niceExponible
Thanks. Was looking for something like this. Not sure if it'll work on all models though! Worked on Xiaomi 7A, but not on my S8Sos
H
2

If your image is rotated, you can use this:

mCamera.setDisplayOrientation(90);

after

mCamera.startPreview();
Horsepowerhour answered 10/7, 2014 at 16:6 Comment(0)
S
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

Simmons answered 30/4, 2013 at 10:34 Comment(0)
R
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");
Rattan answered 5/1, 2015 at 5:49 Comment(0)
K
-3

Use MediaStore.EXTRA_OUTPUT param for you camera application running intent

intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
Kenon answered 30/4, 2013 at 10:31 Comment(4)
Are you sure this fulfils the OPs desire to bypass the save/delete confirmation. It doesn't for me.Henpeck
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")));Triolein
Here is the link to official documentation developer.android.com/guide/topics/media/…Kenon
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.Magpie

© 2022 - 2024 — McMap. All rights reserved.