views:

118

answers:

1

I am following very closely to the sample codes in the resources for TicTacToeLib as well as an example of how to display a bitmap in a book titled Android Application Development. I am doing all the same things they are doing, the only difference is I am using a SurfaceView instead of a view. Can anyone tell me what I am doing wrong? The end goal is to display the preview image of the camera manually as well as display an image over top of it.

Sorry I forgot to include what the problem was. The onDraw method is not being called ever. and I was under the impression it should be called by the invalidate method. Secondly the lockCanvas() method is returning a NULL canvas. Even after I fixed the code to not use the PUSH_BUFFER constant from SurfaceHolder (I have edited the code for this correction).

package com.test.combine;

import android.content.res.XmlResourceParser;
import android.app.Activity;
import android.content.Context;
import android.hardware.Camera;
import android.hardware.Camera.Size;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.Window;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import java.io.IOException;
import android.util.Log;
import java.util.List;

public class CombineTestActivity extends Activity
{
private Preview mPreview;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Hide the window title.
    requestWindowFeature(Window.FEATURE_NO_TITLE);

    // Create our Preview view and set it as the content of our activity.
    mPreview = new Preview(this);
    setContentView(mPreview);
}

 }

// ----------------------------------------------------------------------

class Preview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
private Paint mPaint;
private Canvas canvas;
private Bitmap currentprev;
private Picture mPicture;

private Camera.PreviewCallback mPrevCallback = new Camera.PreviewCallback() 
{
        public void onPreviewFrame( byte[] data, Camera Cam ) {
                Log.d("CombineTestActivity", "Preview registered");
                Log.d("CombineTestActivity", "Data length = " 
                        + data.length );
               // currentprev = BitmapFactory.decodeByteArray( data, 0, 
               //       data.length );

               currentprev = BitmapFactory.decodeResource( getResources(),
                   R.drawable.creature00 );
               if( currentprev == null )
                   Log.d("CombineTestActivity", "currentprev is null" );

                Log.d("CombineTestActivity", "Preview Finished" );
                invalidate();
        }
};

private OnTouchListener mCorkyListener = new OnTouchListener() {
        public boolean onTouch(View v, MotionEvent me) {
                Log.d("CombineTestActivity", "touch registered" );
                mCamera.takePicture( null, null, mPicCallback );
                return false;
        }
};

private Camera.PictureCallback mPicCallback = new Camera.PictureCallback() {
        public void onPictureTaken( byte[] data, Camera mCamera ) {

                Log.d("CombineTestActivity", "picture method run" );
        }
};

Preview(Context context) {
    super(context);

    // Install a SurfaceHolder.Callback so we get notified when the
    // underlying surface is created and destroyed.
mPicture = new Picture();
    mHolder = getHolder();
    mHolder.addCallback(this);
    mHolder.setType(SurfaceHolder.SURFACE_TYPE_NORMAL);
    mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    canvas = mHolder.lockCanvas();
    if(canvas==null)
        Log.d( "CombineTestActivity", "canvas is null in constructor");

this.setOnTouchListener( mCorkyListener );

invalidate();

}

@Override
protected void onDraw( Canvas mCanvas ) {

        if( mCanvas == null )
                Log.e("CombineTestActivity", "canvas is null" );
        if( currentprev == null ) {
                Log.e("CombineTestActivity", "currentprev is null" );
                return;
        }

        mCanvas.drawBitmap( currentprev, 0.0f, 0.0f, mPaint );

        Log.d("CombineTestActivity", "exiting onDraw" );

}


public void surfaceCreated(SurfaceHolder holder) {
    // The Surface has been created, acquire the camera and tell it where
    // to draw.

    mCamera = Camera.open();
    mCamera.setPreviewCallback( mPrevCallback );

    /*        
    try {
       mCamera.setPreviewDisplay(holder);
    } catch (IOException exception) {
        mCamera.release();
        mCamera = null;
        // TODO: add more exception handling logic here
    }
    */      

}

public void surfaceDestroyed(SurfaceHolder holder) {
    // Surface will be destroyed when we return, so stop the preview.
    // Because the CameraDevice object is not a shared resource, it's very
    // important to release it when the activity is paused.
    mCamera.stopPreview();
   mCamera.release();
    mCamera = null;
}

private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
    final double ASPECT_TOLERANCE = 0.05;
    double targetRatio = (double) w / h;
    if (sizes == null) return null;

    Size optimalSize = null;
    double minDiff = Double.MAX_VALUE;

    int targetHeight = h;

    // Try to find an size match aspect ratio and size
    for (Size size : sizes) {
        double ratio = (double) size.width / size.height;
        if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
        if (Math.abs(size.height - targetHeight) < minDiff) {
            optimalSize = size;
            minDiff = Math.abs(size.height - targetHeight);
        }
    }

    // Cannot find the one match the aspect ratio, ignore the requirement
    if (optimalSize == null) {
        minDiff = Double.MAX_VALUE;
        for (Size size : sizes) {
            if (Math.abs(size.height - targetHeight) < minDiff) {
                optimalSize = size;
                minDiff = Math.abs(size.height - targetHeight);
            }
        }
    }
    return optimalSize;
}

public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
    // Now that the size is known, set up the camera parameters and begin
    // the preview.
    Camera.Parameters parameters = mCamera.getParameters();

    List<Size> sizes = parameters.getSupportedPreviewSizes();
    if( sizes.isEmpty() )
        Log.d( "CameraTestActivity", "sizes null");
    else
        Log.d( "CameraTestActivity", "sizes not null"); 

    Size optimalSize = getOptimalPreviewSize(sizes, w, h);
    if( optimalSize == null )
        Log.d( "CameraTestActivity", "optimalSize null");
    else
        Log.d( "CameraTestActivity", "optimalSize not null");


    parameters.setPreviewSize(optimalSize.width, optimalSize.height);

if( parameters == null )
    Log.d( "CameraTestActivity", "parameters null" );
else
    Log.d( "CameraTestActivity", "parameters not null" );

    mCamera.setParameters(parameters);
    mCamera.startPreview();
}


}
A: 

I apparently found a solution. although SurfaceView inherits from View, it does not call onDraw like View does. As for why lockCanvas wasn't working, I still do not know.

RyoxSinfar