3

I just started programming in Java, and I need to get a simple application up that shows the camera, takes a picture, and sends that picture data somewhere.

I have been searching all over the web trying to find a good camera tutorial that worked as expected, but apparently they all require some inner knowledge that I do not have yet.

On this page, commonsWare pointed to code that had some sample code in it for using the camera. I have taken the PictureDemo code and got it running with no errors. However, it only brings up a black screen. I assume this is because the program is not actually activating the preview, or camera in the main function, but every time I try adding the code I think I need, I am getting exceptions.

So my question is, what do I need to add in the main function to get the camera going? Or is there a better tutorial somewhere that I can see simple basic code for getting the camera up?

package assist.core;

import android.app.Activity;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.KeyEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.Toast;
import java.io.File;
import java.io.FileOutputStream;

import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;

public class MainActivity extends Activity
{
    private SurfaceView preview = null;
    private SurfaceHolder previewHolder = null;
    private Camera camera = null;
    private boolean inPreview = false;

    /**
     * 
     */
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        //Call the parent class
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        preview = (SurfaceView) findViewById(R.id.preview);
        previewHolder = preview.getHolder();
        previewHolder.addCallback(surfaceCallback);
        previewHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }

    @Override
    public void onResume() {
        super.onResume();
        //Get the camera instance
        camera = CameraFinder.INSTANCE.open();
    }

    @Override
    public void onPause() {
        if (inPreview) {
            camera.stopPreview();
        }

        camera.release();
        camera = null;
        inPreview = false;

        super.onPause();
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_CAMERA || keyCode == KeyEvent.KEYCODE_SEARCH) {
            if (inPreview) {
                camera.takePicture(null, null, photoCallback);
                inPreview = false;
            }

            return(true);
        }

        return(super.onKeyDown(keyCode, event));
    }

    private Camera.Size getBestPreviewSize(int width, int height, Camera.Parameters parameters) {
        Camera.Size result = null;

        for (Camera.Size size : parameters.getSupportedPreviewSizes()) {
            if (size.width <= width && size.height <= height) {
                if (result == null) {
                  result=size;
                }
                else {
                    int resultArea = result.width * result.height;
                    int newArea = size.width * size.height;

                    if (newArea > resultArea) {
                        result = size;
                    }
                }
            }
        }

        return(result);
    }

    SurfaceHolder.Callback surfaceCallback = new SurfaceHolder.Callback() {
        public void surfaceCreated(SurfaceHolder holder) {
            try {
                camera.setPreviewDisplay(previewHolder);
            }
            catch (Throwable t) {
                Log.e("MainActivity-surfaceCallback", "Exception in setPreviewDisplay()", t);
                Toast.makeText(MainActivity.this, t.getMessage(), Toast.LENGTH_LONG).show();
            }
        }

        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
            Camera.Parameters parameters = camera.getParameters();
            Camera.Size size = getBestPreviewSize(width, height, parameters);

            if (size != null) {
                parameters.setPreviewSize(size.width, size.height);
                parameters.setPictureFormat(PixelFormat.JPEG);

                camera.setParameters(parameters);
                camera.startPreview();
                inPreview = true;
            }
        }

        public void surfaceDestroyed(SurfaceHolder holder) {
            // no-op
        }
    };

    Camera.PictureCallback photoCallback = new Camera.PictureCallback() {
        public void onPictureTaken(byte[] data, Camera camera) {
            new SavePhotoTask().execute(data);
            camera.startPreview();
            inPreview = true;
        }
    };

    class SavePhotoTask extends AsyncTask<byte[], String, String> {
        @Override
        protected String doInBackground(byte[]... jpeg) {
            File photo = new File(Environment.getExternalStorageDirectory(), "photo.jpg");
            if(photo.exists()) {
                photo.delete();
            }

            try {
                FileOutputStream fos = new FileOutputStream(photo.getPath());
                fos.write(jpeg[0]);
                fos.close();
            }
            catch (java.io.IOException e) {
                Log.e("MainActivity", "Exception in photoCallback", e);
            }

            return(null);
        }
    }
}

Update

As for the exceptions I was getting, if I tried making the main function like the code below,

public void onCreate(Bundle savedInstanceState)
{
    //Call the parent class
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    preview = (SurfaceView) findViewById(R.id.preview);
    previewHolder = preview.getHolder();
    previewHolder.addCallback(surfaceCallback);
    previewHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

    Camera.Parameters parameters = camera.getParameters();
    parameters.setPictureFormat(PixelFormat.JPEG);
    camera.setParameters(parameters);

    try {
        //Start the camera preview display
        camera.setPreviewDisplay(previewHolder);
        camera.startPreview();
    } 
    catch (IOException ex) {
        Logger.getLogger(MainActivity.class.getName()).log(Level.SEVERE, null, ex);
    }
}

I get "The application has stopped unexpectedly. Please Try again." I was basically trying to follow the steps that the android documention specifies. I also tried putting this code into the onResume function after the camera object is retrieved, and then calling this.onResume.

Community
  • 1
  • 1
Metropolis
  • 6,542
  • 19
  • 56
  • 86

3 Answers3

6

this is a fully functional camera working with Intents (I am calling the camera immediately, you would obviously include a button or menu item). It saves the image to the gallery and to root as Pic.jpg and then displays the captured image.

this answer is an expanded and complete version of this EXCELLENT snippet by Aleksander O.

import java.io.File;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.Toast;

public class CallCameraActivity extends Activity {

    final int TAKE_PICTURE = 1;
    private Uri imageUri;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        takePhoto();
    }



    public void takePhoto() {
        Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
        File photo = new File(Environment.getExternalStorageDirectory(),  "Pic.jpg");
        intent.putExtra(MediaStore.EXTRA_OUTPUT,
                Uri.fromFile(photo));
        imageUri = Uri.fromFile(photo);
        startActivityForResult(intent, TAKE_PICTURE);
    }
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {

    super.onActivityResult(requestCode, resultCode, data);
    switch (requestCode) {
    case TAKE_PICTURE:
        if (resultCode == Activity.RESULT_OK) {
            //Uri imageUri;
            Uri selectedImage = imageUri;
            getContentResolver().notifyChange(selectedImage, null);
            ImageView imageView = (ImageView) findViewById(R.id.IMAGE);
            ContentResolver cr = getContentResolver();
            Bitmap bitmap;
            try {
                 bitmap = android.provider.MediaStore.Images.Media
                 .getBitmap(cr, selectedImage);

                imageView.setImageBitmap(bitmap);
                Toast.makeText(this, "This file: "+selectedImage.toString(),
                        Toast.LENGTH_LONG).show();
            } catch (Exception e) {
                Toast.makeText(this, "Failed to load", Toast.LENGTH_SHORT)
                        .show();
                Log.e("Camera", e.toString());
            }
        }
    }
}
}

use this as your main.xml layout

<?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" >

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/hello" />


    <ImageView
        android:id="@+id/IMAGE"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/ic_launcher" />

</LinearLayout>

strings.xml

<?xml version="1.0" encoding="utf-8" standalone="no"?>
<resources>
  <string name="hello">Hello World, TonyPicturesInc!</string>
  <string name="app_name">TGCam</string>
</resources>
Community
  • 1
  • 1
tony gil
  • 9,424
  • 6
  • 76
  • 100
  • 1
    Great! Thanks for posting this tony, it will be great to get more working camera stuff on the internet, because I had a tough time working through all the problems with the current examples. I did finally get a working version as well, but it never hurts to have a bunch of examples. – Metropolis Nov 29 '12 at 16:52
2

If what you need is just open up a camera, take a picture, and get the image. then you can do: launch Camera using Intents

Your above code is the integrated version. That integrates the camera into your app. I am not sure if you have the real android device to test. The simulator will show either black or "android icon" screen in replacing the real camera.

so test it on real device if you weren't.

And could you be more specified on the exceptions you got?

Terence Lui
  • 2,778
  • 1
  • 18
  • 17
  • Hmmmm...I saw somebody else using Intents to do this as well, but I did not understand what Intents are for, or why I would want to use it over this functionality. I do need the byte data from the image, not the image itself, if that makes any difference. Also, I am testing it on a Droid Incredible, which is where I am getting the black screen. – Metropolis Sep 30 '11 at 04:38
  • I believe I do need the camera integrated into my app. If I can not do that with Intents, than I will have to stick with this. – Metropolis Sep 30 '11 at 04:39
  • Intents are like "asking someone to do something for you". If you want to read more, [link](http://developer.android.com/guide/topics/intents/intents-filters.html).Back to your question, long for short, Here is an easy way to integrated the camera. [link](http://marakana.com/forums/android/examples/39.html). try to see if you understand it. If not, come back here. – Terence Lui Sep 30 '11 at 04:51
  • That is actually one of the tutorials I already had tried. But let me try it again and see if I can get it working. I know more now than I did then :p – Metropolis Sep 30 '11 at 04:56
  • just dont forget the permission :) – Terence Lui Sep 30 '11 at 05:02
  • Okay cool. I got this up and running, and have worked through some of the bugs. I had to read down in the comments to find out that he was releasing the camera wrong, and he had a newer version to use. Now that I have this basic camera app working, I believe I can add onto it from here and make it more robust. Thanks for your help Terence! – Metropolis Sep 30 '11 at 05:19
0

Hey you have to look in this answer it may help you.

Click here

or also you can use Intent to start inbuilt camera like below

Intent i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(i, CAMERA_RESULT);

And you have to get result from camera activity like below code

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        // TODO Auto-generated method stub
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == RESULT_OK && requestCode == CAMERA_RESULT) {
            Bundle extras = data.getExtras();
            if(extras.containsKey("data")) {
                Bitmap bmp = (Bitmap) extras.get("data");
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                bmp.compress(Bitmap.CompressFormat.PNG, 100, baos);
                byte[] image = baos.toByteArray();
                if(image != null) {
        BitmapFactory.Options options=new BitmapFactory.Options();
        options.inSampleSize = 5;
        Bitmap myImage = BitmapFactory.decodeByteArray(image , 0, image.length, options);
        imageView.setImageBitmap(myImage);

                }
            }else {
                Toast.makeText(getBaseContext(), "Please capture again", Toast.LENGTH_LONG).show();
            }


        }
    }
Community
  • 1
  • 1
Dharmendra
  • 33,296
  • 22
  • 86
  • 129