CameraView only works in emulator - java

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.

Related

Android Camera Preview Freezing Right After App Open

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

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!

Android onPreviewFrame callback not getting called for the camera

I'm trying to get the data from onPreviewFrame(byte[] data, Camera camera). But it doesn't seem to be working. Do you see any problems with this code? Most of this just came straight from http://developer.android.com/training/camera/cameradirect.html
public class UAVCamera extends Thread {
Camera mCamera;
CameraPreview mPreview;
public UAVCamera(Context context) {
mPreview = new CameraPreview(context);
}
#Override
public void run() {
safeCameraOpen();
mPreview.setCamera(mCamera);
}
private boolean safeCameraOpen() {
boolean qOpened = false;
try {
releaseCameraAndPreview();
mCamera = Camera.open();
qOpened = (mCamera != null);
} catch (Exception e) {
//Log.e(getString(R.string.app_name), "failed to open Camera");
e.printStackTrace();
}
return qOpened;
}
private void releaseCameraAndPreview() {
mPreview.setCamera(null);
if (mCamera != null) {
mCamera.release();
mCamera = null;
}
}
}
Here is my preview class
class CameraPreview extends ViewGroup implements SurfaceHolder.Callback {
SurfaceView mSurfaceView;
SurfaceHolder mHolder;
Camera mCamera;
CameraPreview(Context context) {
super(context);
mSurfaceView = new SurfaceView(context);
addView(mSurfaceView);
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = mSurfaceView.getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
private void stopPreviewAndFreeCamera() {
if (mCamera != null) {
/*
Call stopPreview() to stop updating the preview surface.
*/
mCamera.stopPreview();
/*
Important: Call release() to release the camera for use by other applications.
Applications should release the camera immediately in onPause() (and re-open() it in
onResume()).
*/
mCamera.release();
mCamera = null;
}
}
public void setCamera(Camera camera) {
if (mCamera == camera) { return; }
stopPreviewAndFreeCamera();
mCamera = camera;
if (mCamera != null) {
try {
mCamera.setPreviewDisplay(mHolder);
} catch (IOException e) {
e.printStackTrace();
}
/*
Important: Call startPreview() to start updating the preview surface. Preview must
be started before you can take a picture.
*/
mCamera.startPreview();
mCamera.setPreviewCallback(new PreviewCallback() {
public void onPreviewFrame(byte[] data, Camera camera) {
}
});
}
}
#Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
// TODO Auto-generated method stub
}
#Override
public void surfaceCreated(SurfaceHolder arg0) {
// TODO Auto-generated method stub
}
#Override
public void surfaceDestroyed(SurfaceHolder arg0) {
// TODO Auto-generated method stub
}
#Override
protected void onLayout(boolean arg0, int arg1, int arg2, int arg3, int arg4) {
// TODO Auto-generated method stub
}
}
Here is my activity
public class MainActivity extends Activity {
private UAVCamera uavCamera;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
uavCamera = new UAVCamera(this);
uavCamera.start();
}
}
I really don't even need to show the picture to the user. I just need to get to the data. Is it possible to do that? I put a break point on onPreviewFrame(byte[] data, Camera camera) but it never gets hit.
You should use
setPreviewCallbackWithBuffer (Camera.PreviewCallback cb) instead of setPreviewCallback.
And, add the callback buffer using addCallbackBuffer(byte[])
When you use addCallbackBuffer(byte[]), byte length is more than preview size (width*height).
Then, I think you can get the data in onPreviewFrame method.
I followed the instructions on http://developer.android.com/guide/topics/media/camera.html#custom-camera
The problem was that I was not creating an activity. I would like to run this as a service and be able to get this information even with the screen is not on. Not sure how to do that.

Categories

Resources