Android Moto Droid Camera Hangs EVERY Time onTakePicture - android

All, I've googled over and over again to find a solution and while I found a bug regarding camera release, etc I can not for the life of me seem to get the cam code to work. Every time I executed takePicture the system simply hangs, sometimes it calls the PictureCallback, but most of the time it simply hangs.
Weird issues about not being able to read /data/ap_gain.bin files, etc
Below is the code:
public class CameraActivity extends Activity implements Camera.PictureCallback, RequestConstants {
private static final String TAG = "Camera";
private Preview preview;
private boolean previewRunning;
private int addressNotificationId;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addressNotificationId = getIntent().getIntExtra(REQ_RA_ID, 0);
getWindow().setFormat(PixelFormat.TRANSLUCENT);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
if (preview == null) {
preview = new Preview(this);
}
setContentView(preview);
}
#Override
protected void onDestroy() {
if (isFinishing()) {
preview.cleanup();
}
super.onDestroy();
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_CAMERA) {
/*
preview.setDrawingCacheEnabled(true);
Bitmap ss = preview.getDrawingCache();
byte[] data = ImageUtility.getImageData(ss,75,1);
Log.v(TAG, "Pic with size: " + data.length);
ApplicationManager.getInstance().createPacketRecord(PacketConstants.PT_FLAG_ADDRESS_PHOTO, ApplicationDatabaseManager.getInstance().getRouteAddressBySystemId(addressNotificationId), data);
finish();
*/
preview.getCamera().takePicture(new Camera.ShutterCallback() {
#Override
public void onShutter() {
}
}, null, this);
return true;
}
return super.onKeyDown(keyCode, event);
}
#Override
public void onPictureTaken(byte[] data, Camera camera) {
/*
if (data == null || isFinishing())
return;
camera.stopPreview();
previewRunning = false;
camera.release();
*/
//Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0,data.length);
//data = null;
//data = ImageUtility.getImageData(bitmap, 75,1);
Log.v(TAG, "Pic with size: " + data.length);
ApplicationManager.getInstance().createPacketRecord(PacketConstants.PT_FLAG_ADDRESS_PHOTO, ApplicationDatabaseManager.getInstance().getRouteAddressBySystemId(addressNotificationId), data);
finish();
}
}
class Preview extends SurfaceView implements SurfaceHolder.Callback {
SurfaceHolder mHolder;
Camera mCamera;
Preview(Context context) {
super(context);
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
Camera getCamera() {
return mCamera;
}
void cleanup() {
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
public void surfaceCreated(SurfaceHolder holder) {
if (mCamera == null)
mCamera = Camera.open();
try {
mCamera.setPreviewDisplay(holder);
} catch (IOException exception) {
mCamera.release();
mCamera = null;
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewSize(w, h);
parameters.setPictureSize(w, h);
mCamera.setParameters(parameters);
mCamera.startPreview();
}
}

You are sometimes taking a picture and sometimes not, because you are releasing the camera before the callback has occurred.
When the callback does fire, depending on whether the camera has released or not it will or will not be able to access the taken photo.
I suggest making sure that you are not releasing the camera or closing the form when you take a photo.
Better yet, close the form from the photo callback.
Also, when a photo is taken, the default action of android is to stop the Preview. this is not a bug, but the expected nature.

After you JpegPictureCallback is called, you need to call mCamera.startPreview again.
There isn't enough info in the API Camera sample to really write a camera app, but you can get the source code for Google's own camera app here. Camera.java contains a lot of important, useful code:
git://android.git.kernel.org/platform/packages/apps/Camera.git

Related

Use camera but dont want to take photo

I want to use camera in my app but dont want to take photo, actually I am making a app i.e transparent screen, in this I want to show transparent wallpaper i.e I have to start camera for this and i dont want to take images for this
I tried all these codes but have n't got the desirable results. Can anyone suggest what must i do?
used this permission in all cases
<uses-permission android:name="android.permission.CAMERA"/>
Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivity(intent);
Intent intent = new Intent(Intent.ACTION_CAMERA_BUTTON, null);
startActivity(intent);
Intent intent = new Intent(android.provider.MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
startActivity(intent);
Update 1:
I tried this code it showing camera in not correct way, its diverting the preview to right kindly look over this updated code and tell wht amendment i can make over this
public class MainActivity extends Activity {
private Preview mPreview;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try{
requestWindowFeature(Window.FEATURE_NO_TITLE);
// Create our Preview view and set it as the content of our activity.
mPreview = new Preview(this);
setContentView(mPreview);
}catch(Exception e){
e.printStackTrace();
}
}
******************************************************************************************
public class Preview extends SurfaceView implements SurfaceHolder.Callback {
SurfaceHolder mHolder;
Camera mCamera;
Preview(Context context) {
super(context);
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
try{
mHolder = getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}catch(Exception e){
e.printStackTrace();
}
}
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, acquire the camera and tell it where
// to draw.
try{
if(mCamera!=null){
mCamera.release();
mCamera=null;
}
mCamera = Camera.open();
Log.i("Camera", "Camera is opened");
mCamera.setPreviewDisplay(holder);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
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.
try{
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}catch(Exception e){
e.printStackTrace();
}
}
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.
try{
Parameters parameters = mCamera.getParameters();
List<Camera.Size> sizes = parameters.getSupportedPreviewSizes();
Camera.Size cs = sizes.get(0);
parameters.setPreviewSize(cs.width, cs.height);
mCamera.setParameters(parameters);
mCamera.startPreview();
}catch(Exception e){
e.printStackTrace();
}
}
}
You need to use surfaceView for this. Here is an example:
public class CameraPreview 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);
}
}
public class Preview extends SurfaceView implements SurfaceHolder.Callback {
SurfaceHolder mHolder;
Camera mCamera;
Preview(Context context) {
super(context);
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, acquire the camera and tell it where
// to draw.
mCamera = Camera.open();
mCamera.setPreviewDisplay(holder);
}
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 = null;
}
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 = camera.getParameters();
List<Camera.Size> sizes = parameters.getSupportedPreviewSizes();
Camera.Size cs = sizes.get(0);
parameters.setPreviewSize(cs.width, cs.height);
camera.setParameters(parameters);
mCamera.startPreview();
}
}
I used this code and it worked...
<uses-permission android:name="android.permission.CAMERA"/>
public class MainActivity extends Activity {
private Preview mPreview;
/** Called when the activity is first created. */
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try{
requestWindowFeature(Window.FEATURE_NO_TITLE);
// Create our Preview view and set it as the content of our activity.
mPreview = new Preview(this);
setContentView(mPreview);
}catch(Exception e){
e.printStackTrace();
}
}
}
*****************************************************************************************
public class Preview extends SurfaceView implements SurfaceHolder.Callback {
SurfaceHolder mHolder;
Camera mCamera;
Preview(Context context) {
super(context);
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
try {
mHolder = getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
} catch (Exception e) {
e.printStackTrace();
}
}
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, acquire the camera and tell it where
// to draw.
try {
if (mCamera != null) {
mCamera.release();
mCamera = null;
}
mCamera = Camera.open();
Log.i("Camera", "Camera is opened");
mCamera.setPreviewDisplay(holder);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
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.
try {
mCamera.stopPreview();
mCamera.release();
mCamera = null;
} catch (Exception e) {
e.printStackTrace();
}
}
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.
try {
Camera.Parameters parameters = mCamera.getParameters();
parameters.set("orientation", "portrait");
mCamera.setDisplayOrientation(90);
List<Camera.Size> sizes = parameters.getSupportedPreviewSizes();
Camera.Size cs = sizes.get(0);
parameters.setPreviewSize(cs.width, cs.height);
mCamera.setParameters(parameters);
mCamera.startPreview();
} catch (Exception e) {
e.printStackTrace();
}
}
}

Surface View Camera Preview

Having a little trouble getting my SurfaceView to show my camera preview. I've looked at some questions on here and Google'd some tuts but I think it may be a small error on my end that I'm just not seeing.
Code
public class RoofPitchActivity extends Activity implements SensorEventListener {
...
private SurfaceView mSurfaceView;
private SurfaceHolder mSurfaceHolder;
private Camera mCamera;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_roof_pitch);
initViews();
}
private void initViews() {
...
Preview preview = new Preview(this);
mCamera = Camera.open();
preview.setCamera(mCamera);
}
...
...
class Preview extends ViewGroup implements SurfaceHolder.Callback {
public Preview(Context context) {
super(context);
mSurfaceView = (SurfaceView) findViewById(R.id.preview);
mSurfaceView = new SurfaceView(context);
addView(mSurfaceView);
mSurfaceHolder = mSurfaceView.getHolder();
mSurfaceHolder.addCallback(this);
}
public void setCamera(Camera camera) {
if (mCamera == camera) {
return;
}
stopPreviewAndFreeCamera();
mCamera = camera;
if (mCamera != null) {
requestLayout();
try {
mCamera.setPreviewDisplay(mSurfaceHolder);
} catch (IOException e) {
e.printStackTrace();
}
mCamera.startPreview();
}
}
private void stopPreviewAndFreeCamera() {
if (mCamera != null) {
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
mCamera.startPreview();
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewSize(mSurfaceView.getWidth(), mSurfaceView.getHeight());
requestLayout();
mCamera.setParameters(parameters);
mCamera.startPreview();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
if (mCamera != null) {
mCamera.stopPreview();
}
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
}
}
}
So when the activity is launched the SurfaceView is black. The camera does not appear to be rendering the preview onto the SurfaceView. I'm sure there's something small I'm missing, or maybe it's just a fundemental misunderstanding of how this works. A fresh set of eyes with a little explanation would be very much appreciated. Thanks
So the answer to my question ended up being device specific. The code was acceptable but my device I'm using to debug is a Nexus 7. This means the camera is front facing and the normal call to the camera does not work. An interesting and funny read about this can be found in this article
Camera.open();
does not work. You must use
Camera.open(0);
So my code ended up with a conditional check for the camera and now it works fine.
Like so
public void setCamera() {
stopPreviewAndFreeCamera();
PackageManager pm = getPackageManager();
boolean backCamera = pm.hasSystemFeature(PackageManager.FEATURE_CAMERA);
boolean frontCamera = pm.hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT);
if (frontCamera) {
mCamera = Camera.open(0);
} else if (backCamera) {
mCamera = Camera.open();
}
if (mCamera != null) {
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewSize(mSurfaceView.getWidth(), mSurfaceView.getHeight());
requestLayout();
try {
mCamera.setParameters(parameters);
mCamera.setPreviewDisplay(mSurfaceHolder);
} catch (IOException e) {
e.printStackTrace();
}
mCamera.startPreview();
}
}

onPreviewFrame not being called for every frame that is displayed on SurfaceView

My subclass of SurfaceView implements Camera.PreviewCallback & SurfaceHolder.Callback.
private SurfaceHolder mHolder;
private Camera mCamera;
private final FPSCounter fpscounter = new FPSCounter();
public MySurfaceView(Context context, AttributeSet attrs) {
super(context, attrs);
mHolder = getHolder();
mHolder.addCallback(this);
}
#Override
public void onPreviewFrame(byte[] data, Camera camera) {
fpscounter.logFrame();
Log.d("fps", String.valueOf(fpscounter.getLastFrameCount()));
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
synchronized (this) {
mCamera.stopPreview();
Camera.Parameters parameters = mCamera.getParameters();
parameters.setRecordingHint(true);
parameters.setPreviewFormat(ImageFormat.NV21);
mCamera.setParameters(parameters);
try {
mCamera.setPreviewDisplay(holder);
mCamera.setPreviewCallback(this);
mCamera.startPreview();
} catch (IOException e) {
e.printStackTrace();
}
}
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
synchronized (this) {
setWillNotDraw(false);
mCamera = Camera.open();
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
synchronized (this) {
try {
if (mCamera != null) {
mCamera.stopPreview();
mCamera.release();
}
} catch (Exception e) {
Log.e("cam error", e.getMessage());
}
}
}
and the FPSCounter class
private long startTime;
private int frames, lastFrameCount;
public void logFrame() {
frames++;
if (System.nanoTime() - startTime >= 1000000000) {
lastFrameCount = frames;
frames = 0;
startTime = System.nanoTime();
}
}
public int getLastFrameCount() {
return lastFrameCount;
}
Even though the camera preview is extremely smooth, the onPreviewFrame() method is only called about 5 times a second. Why isn't it being called for every frame?
You probably figured it out already: Camera.setPreviewCallback() puts too much pressure on Garbage Collector. You can use Camera.setPreviewCallbackWithBuffer() instead.
Second, if onPreviewFrame() arrives on the main (UI) thread, then it competes for single CPU time with UI events like touch, layout, or even rendering. To keep onPreviewFrame() on a separate thread, you should open() the camera on a secondary Looper thread, see e.g. https://stackoverflow.com/a/19154438/192373.
Third, even in this case, the preview callbacks are serialized. If fpscounter.logFrame() and Log().d take X milliseconds, then the FPS will not exceed 1000/X.
It is called for every frame. You can refer to online reference of Camera. Look at this sentence "Installs a callback to be invoked for every preview frame in addition to displaying them on the screen."

Exit onPreviewFrame and notify user

I am working the onPreviewFrame(byte[] data, Camera camera) on Android. Within the onPreviewFrame I do some image processing. At a point inside the onPreviewFrame I want to stop the preview (I know the point by an if statement) and play a sound - perhaps the phone ringtome. I think you can not play a sound in the preview.
How do I exit the onPreviewFrame and where do I add the code for playing the sound?
Is it on Surface Destroyed?
Here is my code:
public class MyCameraPreview extends Activity {
private Preview mPreview;
public TextView results;
#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, PreviewCallback {
SurfaceHolder mHolder;
Camera mCamera;
public TextView results;
public TextView txt;
private Parameters parameters;
//this variable stores the camera preview size
private Size previewSize;
//this array stores the pixels as hexadecimal pairs
private int[] pixels;
public int[] argb8888;
Preview(Context context) {
super(context);
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, acquire the camera and tell it where
// to draw.
mCamera = Camera.open();
try {
mCamera.setPreviewDisplay(holder);
//sets the camera callback to be the one defined in this class
mCamera.setPreviewCallback(this);
parameters = mCamera.getParameters();
parameters.setZoom(parameters.getMaxZoom());
mCamera.setParameters(parameters);
parameters = mCamera.getParameters();
previewSize = parameters.getPreviewSize();
pixels = new int[previewSize.width * previewSize.height];
} 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;
}
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.
parameters.setPreviewSize(w, h);
//set the camera's settings
mCamera.setParameters(parameters);
mCamera.startPreview();
}
#Override
public void onPreviewFrame(byte[] data, Camera camera) {
Do some image processing.
If condition == true {
Exit the preview and then play the ringtone and exit the application.
}
}
In Preview you can add a definition of a listener and use it to not doint the sound in the Preview.
Something like this :
public static interface OnPreviewListener {
void onImageMakeSound();
}
public void setListener(OnPreviewListener listener) {
this.listener = listener;
}
Then in your onPreviewFrame method :
#Override
public void onPreviewFrame(byte[] data, Camera camera) {
if (countFrame > 5) {
imageBytes = data;
countFrame = 0;
if (listener != null)
listener.onImageMakeSound();
}
countFrame++;
camera.addCallbackBuffer(data);
return;
}
In your activity, that must implements OnPreviewListener :
#Override
public void onImageMakeSound() {
alarmSoundOn();
}

Android camera preview: 1:1 aspect ratio, how?

Hi
I am trying to use the camera to capture an image in one of my application. What is special is that I need a square preview area (and picture in the end). I tried defining the size of both picture and preview to 1:1 pixel ratios, but nothing seams to work. No matter what I does the picture looks "squashed" on a square.
Anyone who has any idea about how to resolve this?
code:
public class AddFromCameraActivity extends Activity implements SurfaceHolder.Callback {
private Camera mCamera;
private Parameters mParameters;
private SurfaceView mCameraPreview;
private SurfaceHolder mSurfaceHolder;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.addimagefromcameramain);
initialise();
//Testing area
mCamera = Camera.open();
mParameters = mCamera.getParameters();
mParameters.setFlashMode(Camera.Parameters.FLASH_MODE_AUTO);
mParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
mParameters.setJpegQuality(50);
mParameters.setJpegThumbnailQuality(50);
mParameters.setPictureSize(1024, 1024);
//mParameters.setPreviewFormat(ImageFormat.JPEG);
mParameters.setJpegThumbnailSize(256, 256);
mParameters.setPreviewSize(500, 500);
mCamera.setParameters(mParameters);
}
private void initialise()
{
mCameraPreview = (SurfaceView)findViewById(R.id.cameraSurfaceView);
mSurfaceHolder = mCameraPreview.getHolder();
mSurfaceHolder.addCallback(this);
mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
mSurfaceHolder.setFixedSize(500, 500);
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
try {
mCamera.setPreviewDisplay(mSurfaceHolder);
mCamera.startPreview();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
mCamera.stopPreview();
mCamera.release();
}
#Override
public void onPause()
{
mCamera.release();
}
}
thanks
You can take a look at the CameraPreview sample code from the Android SDK. The getOptimalPreviewSize method shows how to deal with different camera sizes and the onLayout method shows how to layout the preview surface in the activity.

Categories

Resources