Android Camera Preview Freezing Right After App Open - java

in the app i'm developing, i used a tutorial to use the camera, but when the app opens, after 1 or 2 seconds, the preview freezes. The thing is: if i press home and after go back for the app, it works normally.
Here my code:
private SurfaceView preview=null;
private SurfaceHolder previewHolder=null;
private Camera camera=null;
private boolean inPreview=false;
private boolean cameraConfigured=false
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
...
preview=(SurfaceView)findViewById(R.id.preview);
previewHolder = preview.getHolder();
previewHolder.addCallback(surfaceCallback);
previewHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
private void startPreview() {
if (cameraConfigured && camera!=null) {
camera.setDisplayOrientation(90);
camera.startPreview();
inPreview=true;
}
}
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;
}
}
}
}
camera.setDisplayOrientation(90);
return(result);
}
private void initPreview(int width, int height) {
if (camera!=null && previewHolder.getSurface()!=null) {
try {
camera.setPreviewDisplay(previewHolder);
}
catch (Throwable t) {
Log.e("Preview-surfaceCallback",
"Exception in setPreviewDisplay()", t);
Toast
.makeText(MainActivity.this, t.getMessage(), Toast.LENGTH_LONG)
.show();
}
if (!cameraConfigured) {
Camera.Parameters parameters=camera.getParameters();
Camera.Size size=getBestPreviewSize(width, height,
parameters);
if (size!=null) {
parameters.setPreviewSize(size.width, size.height);
camera.setParameters(parameters);
cameraConfigured=true;
}
}
}
}
SurfaceHolder.Callback surfaceCallback=new SurfaceHolder.Callback() {
public void surfaceCreated(SurfaceHolder holder) {
// no-op -- wait until surfaceChanged()
}
public void surfaceChanged(SurfaceHolder holder,
int format, int width,
int height) {
initPreview(width, height);
startPreview();
}
public void surfaceDestroyed(SurfaceHolder holder) {
// no-op
}
};
protected void onPause() {
if (inPreview) {
camera.stopPreview();
}
camera.release();
camera=null;
inPreview=false;
super.onPause();
}
protected void onResume() {
super.onResume();
camera = Camera.open();
startPreview();
}

If the behaviour is what you explain think about... there is a lifecycle that makes your app work.
So, check what you have in your onPause and onResume methods that makes your Camera preview work nice...
If I have to bet, i will say:
camera = Camera.open();
must be in onCreate().
UPDATE try this:
SurfaceHolder.Callback surfaceCallback=new SurfaceHolder.Callback() {
public void surfaceCreated(SurfaceHolder holder) {
mCamera = Camera.open();
mCamera.setPreviewDisplay(holder);
}
public void surfaceChanged(SurfaceHolder holder,
int format, int width,
int height) {
initPreview(width, height);
startPreview();
}
}
Check this link for more info

Related

Camera2API: Session has been closed; further changes are illegal

I'm using Camera2API to build camera activity which sends taken image to another activity. On some devices it works, but on other (slower ones) I get an java.lang.IllegalStateException which says "Session has been closed; further changes are illegal".
I get this exception on this line (in updatePreview()):
cameraCaptureSessions.setRepeatingRequest(captureRequestBuilder.build(), null, mBackgroundHandler);
Here is my full code:
public class NewCamera extends CustomActivity implements TimingActivity {
private static final String TAG = "NewCamera";
private ImageView takePictureButton;
private TextureView textureView;
private static final SparseIntArray ORIENTATIONS = new SparseIntArray();
static {
ORIENTATIONS.append(Surface.ROTATION_0, 90);
ORIENTATIONS.append(Surface.ROTATION_90, 0);
ORIENTATIONS.append(Surface.ROTATION_180, 270);
ORIENTATIONS.append(Surface.ROTATION_270, 180);
}
private String cameraId;
protected CameraDevice cameraDevice;
protected CameraCaptureSession cameraCaptureSessions;
protected CaptureRequest.Builder captureRequestBuilder;
private Semaphore mCameraOpenCloseLock = new Semaphore(1);
private Size imageDimension;
private ImageReader imageReader;
private static final int REQUEST_CAMERA_PERMISSION = 200;
private Handler mBackgroundHandler;
private HandlerThread mBackgroundThread;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.new_camera);
textureView = (TextureView) findViewById(R.id.textureView);
textureView.setSurfaceTextureListener(textureListener);
takePictureButton = (ImageView) findViewById(R.id.capture);
takePictureButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
takePicture();
captureRequestBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_OFF);
finish();
}
});
changeFlashImage();
}
TextureView.SurfaceTextureListener textureListener = new TextureView.SurfaceTextureListener() {
#Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
//open your camera here
//transfromImage(width, height);
openCamera();
}
#Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
// Transform you image captured size according to the surface width and height
}
#Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
return false;
}
#Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
}
};
private final CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {
#Override
public void onOpened(CameraDevice camera) {
mCameraOpenCloseLock.release();
cameraDevice = camera;
createCameraPreview();
}
#Override
public void onDisconnected(CameraDevice camera) {
mCameraOpenCloseLock.release();
camera.close();
cameraDevice = null;
}
#Override
public void onError(CameraDevice camera, int error) {
mCameraOpenCloseLock.release();
camera.close();
cameraDevice = null;
safeDestroy();
}
};
final CameraCaptureSession.CaptureCallback captureCallbackListener = new CameraCaptureSession.CaptureCallback() {
#Override
public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
super.onCaptureCompleted(session, request, result);
createCameraPreview();
}
};
private void safeDestroy() {
Intent intent = getIntent();
finish();
startActivity(intent);
}
protected void startBackgroundThread() {
mBackgroundThread = new HandlerThread("Camera Background");
mBackgroundThread.start();
mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
}
protected void stopBackgroundThread() {
mBackgroundThread.quitSafely();
try {
mBackgroundThread.join();
mBackgroundThread = null;
mBackgroundHandler = null;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
protected void takePicture() {
if(null == cameraDevice) {
Log.e(TAG, "cameraDevice is null");
return;
}
try {
ImageReader reader = ImageReader.newInstance(imageDimension.getWidth(), imageDimension.getHeight(), ImageFormat.JPEG, 1);
List<Surface> outputSurfaces = new ArrayList<Surface>(2);
outputSurfaces.add(reader.getSurface());
outputSurfaces.add(new Surface(textureView.getSurfaceTexture()));
captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
captureRequestBuilder.addTarget(reader.getSurface());
captureRequestBuilder.set(CaptureRequest.JPEG_QUALITY, (byte) 100);
switch(Preferences.getInstance().flashMode % 2) {
case 0:
//off
captureRequestBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_OFF);
break;
case 1:
//on
captureRequestBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_TORCH);
break;
}
// Orientation
int rotation = getWindowManager().getDefaultDisplay().getRotation();
captureRequestBuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS.get(rotation));
ImageReader.OnImageAvailableListener readerListener = new ImageReader.OnImageAvailableListener() {
#Override
public void onImageAvailable(ImageReader reader) {
ByteBuffer buffer = reader.acquireLatestImage().getPlanes()[0].getBuffer();
byte[] bytes = new byte[buffer.capacity()];
buffer.get(bytes);
//handle bytes - pass to another activity
}
};
reader.setOnImageAvailableListener(readerListener, mBackgroundHandler);
final CameraCaptureSession.CaptureCallback captureListener = new CameraCaptureSession.CaptureCallback() {
#Override
public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
super.onCaptureCompleted(session, request, result);
}
};
cameraDevice.createCaptureSession(outputSurfaces, new CameraCaptureSession.StateCallback() {
#Override
public void onConfigured(CameraCaptureSession session) {
try {
session.capture(captureRequestBuilder.build(), captureListener, mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
#Override
public void onConfigureFailed(CameraCaptureSession session) {
safeDestroy();
}
}, mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
protected void createCameraPreview() {
try {
SurfaceTexture texture = textureView.getSurfaceTexture();
if(texture == null) {
return;
}
texture.setDefaultBufferSize(imageDimension.getWidth(), imageDimension.getHeight());
Surface surface = new Surface(texture);
captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
captureRequestBuilder.addTarget(surface);
captureRequestBuilder.set(CaptureRequest.JPEG_QUALITY, (byte) 100);
cameraDevice.createCaptureSession(Arrays.asList(surface), new CameraCaptureSession.StateCallback(){
#Override
public void onConfigured(#NonNull CameraCaptureSession cameraCaptureSession) {
//The camera is already closed
if (null == cameraDevice) {
return;
}
// When the session is ready, we start displaying the preview.
cameraCaptureSessions = cameraCaptureSession;
updatePreview();
}
#Override
public void onConfigureFailed(#NonNull CameraCaptureSession cameraCaptureSession) {
}
}, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private void openCamera() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED
|| ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(NewCamera.this, new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CAMERA_PERMISSION);
return;
}
CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
Log.e(TAG, "is camera open");
try {
cameraId = manager.getCameraIdList()[0];
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
assert map != null;
imageDimension = map.getOutputSizes(SurfaceTexture.class)[0];
transfromImage(textureView.getWidth(), textureView.getHeight());
manager.openCamera(cameraId, stateCallback, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
Log.e(TAG, "openCamera X");
}
protected void updatePreview() {
if(null == cameraDevice) {
Log.e(TAG, "updatePreview error, return");
}
captureRequestBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
try {
cameraCaptureSessions.setRepeatingRequest(captureRequestBuilder.build(), null, mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
#Override
protected void onRestart() {
super.onRestart();
changeFlashImage();
}
#Override
protected void onResume() {
super.onResume();
changeFlashImage();
startBackgroundThread();
if (textureView.isAvailable()) {
openCamera();
} else {
textureView.setSurfaceTextureListener(textureListener);
}
}
#Override
protected void onPause() {
closeCamera();
stopBackgroundThread();
super.onPause();
}
private void closeCamera() {
try {
mCameraOpenCloseLock.acquire();
if (cameraCaptureSessions != null) {
cameraCaptureSessions.close();
cameraCaptureSessions = null;
}
if (cameraDevice != null) {
cameraDevice.close();
cameraDevice = null;
}
if (null != imageReader) {
imageReader.close();
imageReader = null;
}
} catch (InterruptedException e) {
throw new RuntimeException("Interrupted while trying to lock camera closing.", e);
} finally {
mCameraOpenCloseLock.release();
}
}
#Override
protected void onDestroy() {
super.onDestroy();
if(cameraCaptureSessions!=null){
cameraCaptureSessions.close();
cameraCaptureSessions=null;
}
if (cameraDevice!=null){
cameraDevice.close();
cameraDevice=null;
if(imageReader!=null){
imageReader.close();
imageReader=null;
}
}
}
private void transfromImage (int width, int height) {
Matrix matrix = new Matrix();
int rotation = getWindowManager().getDefaultDisplay().getRotation();
RectF textureRectF = new RectF(0, 0, width, height);
RectF previewRectF = new RectF(0, 0, imageDimension.getHeight(), imageDimension.getWidth());
float centerX = textureRectF.centerX();
float centerY = textureRectF.centerY();
if ((rotation == Surface.ROTATION_90) || (rotation == Surface.ROTATION_270)) {
previewRectF.offset(centerX - previewRectF.centerX(), centerY - previewRectF.centerY());
matrix.setRectToRect(textureRectF, previewRectF, Matrix.ScaleToFit.FILL);
float scale = Math.max ((float) width / imageDimension.getWidth(), (float)height / imageDimension.getHeight());
matrix.postScale(scale, scale, centerX, centerY);
matrix.postRotate(90 * (rotation - 2), centerX, centerY);
}
textureView.setTransform(matrix);
}
public void changeFlashImage() {
ImageView ivFlash = (ImageView) findViewById(R.id.flash);
switch(Preferences.getInstance().flashMode % 2) {
case 0:
ivFlash.setImageResource(R.drawable.flash_off);
break;
case 1:
ivFlash.setImageResource(R.drawable.flash_on);
break;
}
}
public void changeFlash(View view) {
Preferences.getInstance().flashMode++;
changeFlashImage();
}
}
I get this exception when camera activity is started. When it occurs textureView doesn't get update. I don't have much experience with Camera2API. Big thanks to people ready to help!
Check if all the camera configurations have been set with a flagas as you have to give some delay to the repeatingRequest of your mCaptureSession while it setting the configuration for you in parallel in the background. In my case I solved this exception by giving a delay of 500 mS to set the repeatingRequest like this:
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
try {
mCaptureSession.setRepeatingRequest(mPreviewRequestBuilder.build(),
mCaptureCallback, null);
} catch (CameraAccessException e) {
Log.e(TAG, "Failed to start camera preview because it couldn't access camera", e);
} catch (IllegalStateException e) {
Log.e(TAG, "Failed to start camera preview.", e);
}
}
}, 500);
All the best Happy coding :-)

How do I take a photo in the onCreate method in Android instead of onClick?

I am working on a project that takes a photo. It is currently working fine when I leave it as is, but when I try to change it so that the picture is attempted to be taken in a different method (rather than being activated by an onClick() method), it errors out every time. Currently the WORKING code is as follows:
public class Testing123 extends Activity {
private SurfaceView preview=null;
private SurfaceHolder previewHolder=null;
private Camera camera=null;
private boolean inPreview=false;
private boolean cameraConfigured=false;
public void onCreate(Bundle savedInstanceState) {
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);
testing(); //HERE is where I am testing, but cannot get it to work. [See part 2]
}
public void onResume() {
super.onResume();
if (camera == null) {
camera=Camera.open();
L.m("Camera open in onResume");
}
startPreview();
}
public void onPause() {
if (inPreview) {
camera.stopPreview();
}
camera.release();
camera=null;
inPreview=false;
super.onPause();
}
public boolean onCreateOptionsMenu(Menu menu) {
new MenuInflater(this).inflate(R.menu.options, menu);
return(super.onCreateOptionsMenu(menu));
}
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.camera) {
if (inPreview) {
camera.takePicture(null, null, photoCallback); //THIS IS WHERE THE PHOTO IS BEING TAKEN
inPreview=false;
}
}
return(super.onOptionsItemSelected(item));
}
private void initPreview(int width, int height) {
if (camera != null && previewHolder.getSurface() != null) {
try {
camera.setPreviewDisplay(previewHolder);
}
catch (Throwable t) {
Log.e("PreviewDemo-surfaceCallback", "Exception in setPreviewDisplay()", t);
}
if (!cameraConfigured) {
Camera.Parameters parameters=camera.getParameters();
setCameraResolution(); //Leaving this method out for now
camera.setParameters(parameters);
cameraConfigured=true;
}
}
}
private void startPreview() {
camera.startPreview();
}
SurfaceHolder.Callback surfaceCallback=new SurfaceHolder.Callback() {
public void surfaceCreated(SurfaceHolder holder) {
}
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
initPreview(width, height);
startPreview();
}
public void surfaceDestroyed(SurfaceHolder holder) {
}
};
Camera.PictureCallback photoCallback = new Camera.PictureCallback() {
public void onPictureTaken(byte[] data, Camera camera) {
//This part is no problem, I am able to write it to the file and use the data from the output of the camera
}
}
The issue comes when I try to make a new call, as you see in the onCreate() method, called testing(); Whenever I call the testing method, which is an attempt to bypass a need to press a button, it errors out. Here is the testing() code:
private void testing() {
try{
cameraConfigured=true;
inPreview=true;
camera=Camera.open();
Camera.Parameters parameters=camera.getParameters();
setCameraResolution();
camera.setParameters(parameters);
camera.setPreviewDisplay(previewHolder);
startPreview();
camera.takePicture(null, null, photoCallback); //THIS IS WHERE THE PHOTO IS BEING TAKEN
} catch (Exception e) {
L.m(e.toString());
}
}
And it errors out after that, specifically saying:
java.lang.RuntimeException: takePicture failed
Just to reiterate, it takes photos just fine when I click an icon/ button to do so, what I am trying to accomplish is for it to run that code WITHOUT the need for the button/ icon to be hit. I figure it is something very simple I am missing, I just can't seem to figure it out.
Call testing() at SurfaceHolder.Callback#onSurfaceCreated.
:-)

How to render YV12 video frames in Android

I have got YV12 video frames from MC67 mobile device imager. I want to display it on android surface.So far i unable to do it.
I am using following code.
MainTestActivity.java
public class MainTestActivity extends Activity {
protected static final String TAG = "CameraTestApp";
private Camera mCamera;
private Preview mPreview;
FrameLayout frmLayoutPreview;
Button btnStart;// Test Start button
Button btnRefreshReport ;//Refresh button
ByteArrayOutputStream out;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFormat(ImageFormat.YV12);
setContentView(R.layout.main);
mCamera= Camera.open(42);
//parameters.setPictureFormat(ImageFormat.YV12);
mPreview = new Preview(this,mCamera);
frmLayoutPreview = (FrameLayout) findViewById(R.id.frmLayoutCameraPreview);
frmLayoutPreview.addView(mPreview);
btnStart = (Button) findViewById(R.id.btnStartTest);
btnStart.setOnClickListener(new OnClickListener () {
public void onClick(View v){
btnStart.setEnabled(false);
mCamera.setPreviewCallback(mPreviewCallback);
mCamera.startPreview();
btnRefreshReport.setEnabled(true);
}
});
btnRefreshReport= (Button) findViewById(R.id.btnRefreshReport);
btnRefreshReport.setOnClickListener(new OnClickListener () {
public void onClick(View v){
mCamera.stopPreview();
btnRefreshReport.setEnabled(false);
btnStart.setEnabled(true);
}
});
btnRefreshReport.setEnabled(false);
btnStart.setEnabled(true);
}
PreviewCallback mPreviewCallback = new PreviewCallback() {
#Override
public void onPreviewFrame(byte[] data, Camera camera) {
}
};
#Override
public void onDestroy()
{
super.onDestroy();
this.mCamera.release();
}
}
Preview.java
class Preview extends SurfaceView implements SurfaceHolder.Callback {
public SurfaceHolder mHolder;
private Camera mCamera ;
private String TAG="CAMERA_TEST";
List<Integer> supportformats;//new code
String filename= "/sdcard/BB_FPS.txt";
Preview(Context context,Camera objCamera) {
super(context);
this.mCamera=objCamera;
mHolder = getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder) {
try
{
mCamera.setPreviewDisplay(holder);
}
catch (Exception e) {
Log.i(TAG, "SurfaceCreated error\t"+e.toString());
}
}
public void surfaceDestroyed(SurfaceHolder holder)
{
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h)
{
Log.i(TAG, "SurfaceChanged invoked");
if (mHolder.getSurface() == null)
{
return;
}
try
{
mCamera.stopPreview();
}
catch (Exception e){}
try
{ mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
}
catch (Exception e)
{
Log.d(TAG, "Error starting camera preview: " + e.getMessage());
}
}
}
I tried to set picture format using setPictureFormat(ImageFormat.YV12) method.But it did not work either.Could some one help me here.
I did the same by converting to RGB using libyuv library. But I had to do it frame by frame.

Strange delay on start my android app

I should warn you I'm newbie of android developing.
The problem: After my app starts, it has black screen and after few seconds, it starts to draw what I need. I've checked drawing thread already started, and already drew content several times, but screen is still black :(
What I'm missing?
Here is my code:
Activity
public class MainActivity extends Activity {
protected SurfaceView surface;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
surface = new GameSurfaceView(this);
setContentView(surface);
}
}
SurfaceView
public class GameSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
protected DrawThread drawThread;
public GameSurfaceView(Context context) {
super(context);
getHolder().addCallback(this);
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
drawThread = new DrawThread(getHolder());
drawThread.start();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
drawThread.interrupt();
}
}
Drawing thread
public class DrawThread extends Thread {
public static final long FPS = 30;
protected SurfaceHolder surfaceHolder;
public DrawThread(SurfaceHolder surfaceHolder) {
super();
this.surfaceHolder = surfaceHolder;
}
#Override
public void run() {
while (!isInterrupted()) {
Canvas canvas = null;
try {
long renderStartedAt = SystemClock.elapsedRealtime();
canvas = surfaceHolder.lockCanvas();
if (canvas != null) {
canvas.drawColor(Color.CYAN);
// TODO DRAW
}
long duration = (1000 - (SystemClock.elapsedRealtime() - renderStartedAt) * FPS) / FPS;
if (duration > 0) {
sleep(duration);
}
} catch (InterruptedException e) {
interrupt();
} finally {
if (canvas != null) {
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
}
}
I found the solution of my problem! unlockCanvasAndPost() does not send invalidate to SurfaceView, so just adding surface.postInvalidate() right after unlockCanvasAndPost() fix delay on startup.
You can use traceview to find where the holdup is.
Check out the profiling with traceview introduction.
Cheers!

CameraView only works in emulator

I've written a litte Camera-Appliction after I have read this tutorial:
http://www.brighthub.com/mobile/google-android/articles/43414.aspx
In the emulator everything works fine (ok, there's no camera, but at least there are no errors ;) )
Then I tried to get it run on my HTC Wildfire S. But immediately after the start the app crashes.
Here's the code of my Activity, maybe somebody has an idea, how to solve the problem:
public class CameraView extends Activity implements SurfaceHolder.Callback {
android.hardware.Camera mCamera;
boolean mPreviewRunning = false;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
getWindow().setFormat(PixelFormat.TRANSLUCENT);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.camera_surface);
SurfaceView mSurfaceView = (SurfaceView)findViewById(R.id.surface_camera);
SurfaceHolder mSurfaceHolder = mSurfaceView.getHolder();
mSurfaceHolder.addCallback(this);
mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
mCamera = android.hardware.Camera.open();
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
if(mPreviewRunning) {
mCamera.stopPreview();
}
android.hardware.Camera.Parameters params = mCamera.getParameters();
params.setPreviewSize(width, height);
mCamera.setParameters(params);
try {
mCamera.setPreviewDisplay(holder);
} catch (IOException ex) {
ex.printStackTrace();
}
mCamera.startPreview();
mPreviewRunning = true;
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
mCamera.stopPreview();
mPreviewRunning = false;
mCamera.release();
}
android.hardware.Camera.PictureCallback mPictureCallback = new android.hardware.Camera.PictureCallback() {
#Override
public void onPictureTaken(byte[] data, android.hardware.Camera camera) {
}
};
}
You are getting an exception because you are trying to make the camera use a width and height it doesn't support. You are asking it to use the width and height of the SurfaceView, which rarely matches one of the supported preview sizes. Instead, try using the following:
public class CameraView extends Activity implements SurfaceHolder.Callback {
android.hardware.Camera mCamera;
boolean mPreviewRunning = false;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
getWindow().setFormat(PixelFormat.TRANSLUCENT);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.camera_surface);
SurfaceView mSurfaceView = (SurfaceView)findViewById(R.id.surface_camera);
SurfaceHolder mSurfaceHolder = mSurfaceView.getHolder();
mSurfaceHolder.addCallback(this);
mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
try {
mCamera.setPreviewDisplay(previewHolder);
}
catch (Throwable t) {
Log.e(TAG, "Exception in setPreviewDisplay()", t);
}
}
#Override
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);
camera.setParameters(parameters);
camera.startPreview();
inPreview=true;
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
mCamera.stopPreview();
mPreviewRunning = false;
mCamera.release();
}
android.hardware.Camera.PictureCallback mPictureCallback = new android.hardware.Camera.PictureCallback() {
#Override
public void onPictureTaken(byte[] data, android.hardware.Camera camera) {
}
};
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);
}
}
This code is all adapted from the one I wrote for my book. I changed some of your code, so some variable names and imports might need to be fixed, but it should work fine.
getBestPreviewSize() is the magic method here which calculates the optimum and best camera preview size to use.

Categories

Resources