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();
}
Related
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();
}
}
}
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."
I would like to effectively make a simple digital zoom for the camera preview, so I thought I would simply resize my SurfaceView to be larger than the screen. Other questions (such as 3813049) seem to indicate that this is easy, so I created the sample code below which I expect to let me see only half of the image horizontally (since the SurfaceView is twice as wide as the screen) and have the image only take up half of the screen horizontally. However, running it (when targeted to SDK version 4 on my Thunderbolt with Android 2.2.1) results in being able to see the whole image horizontally while filling the screen horizontally. The SurfaceView appears to behave as intended vertically (when I make it smaller than the screen), but Android won't allow me to make the SurfaceView larger than the screen.
How can I implement a digital zoom? (No, I cannot use Camera.Parameters.setZoom; not only is this not supported by Android 1.6, but different cameras support and implement this differently)
public class MagnifyTestActivity extends Activity implements SurfaceHolder.Callback {
private MagnificationView mPreview;
private SurfaceHolder mHolder;
private Camera mCamera = null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mPreview = new MagnificationView(this);
setContentView(mPreview);
mHolder = mPreview.getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public class MagnificationView extends SurfaceView {
public MagnificationView(Context context) {
super(context);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Display display = getWindowManager().getDefaultDisplay();
int width = display.getWidth()*2;
int height = display.getHeight()/2;
widthMeasureSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY);
heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
public void surfaceCreated(SurfaceHolder holder) {
mCamera = Camera.open();
try {
mCamera.setPreviewDisplay(holder);
} catch (IOException e) {
e.printStackTrace();
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
mHolder.setFixedSize(w, h);
mCamera.startPreview();
}
}
UPDATE: Based on #Pulkit Sethi's response, it is possible to stretch/magnify the SurfaceView vertically, just not horizontally. To magnify the SurfaceView vertically, simply replace display.getHeight()/2 with display.getHeight()*2 above. Also observe that changing the width doesn't produce any horizontal magnification, either in my code or in Pulkit's.
//Activity class
public class CameraActivity extends Activity implements SurfaceListener {
private static final String TAG = "CameraActivity";
Camera mCamera;
CameraPreview mPreview;
private FrameLayout mCameraPreview;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_camera);
mCamera = getCameraInstance();
mPreview = new CameraPreview(this, mCamera);
mCameraPreview = (FrameLayout) findViewById(R.id.camera_preview);
mCameraPreview.addView(mPreview);
}
#Override
protected void onPause() {
super.onPause();
releaseCamera();
}
private Camera getCameraInstance() {
Camera camera = null;
try {
camera = Camera.open();
} catch (Exception e) {
}
return camera;
}
private void releaseCamera() {
if (null != mCamera) {
mCamera.release();
}
mCamera = null;
}
#Override
public void surfaceCreated() {
//Change these mate
int width = 1000;
int height = 1000;
// Set parent window params
getWindow().setLayout(width, height);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
width, height);
mCameraPreview.setLayoutParams(params);
mCameraPreview.requestLayout();
}
}
// Preview class
public class CameraPreview extends SurfaceView implements
SurfaceHolder.Callback {
private static final String TAG = "CameraPreview";
Context mContext;
Camera mCamera;
SurfaceHolder mHolder;
public interface SurfaceListener{
public void surfaceCreated();
}
SurfaceListener listener;
public CameraPreview(Context context, Camera camera) {
super(context);
mContext = context;
listener = (SurfaceListener)mContext;
mCamera = camera;
mHolder = getHolder();
mHolder.addCallback(this);
// Required prior 3.0 HC
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
try {
mCamera.setPreviewDisplay(holder);
Parameters params = mCamera.getParameters();
//Change parameters here
mCamera.setParameters(params);
mCamera.startPreview();
listener.surfaceCreated();
} catch (Exception e) {
// TODO: handle exception
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
// empty. Take care of releasing the Camera preview in your activity.
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// If your preview can change or rotate, take care of those events here.
// Make sure to stop the preview before resizing or reformatting it.
Log.i(TAG, "Surface changed called");
if (mHolder.getSurface() == null) {
// preview surface does not exist
return;
}
// stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception e) {
// ignore: tried to stop a non-existent preview
}
// set preview size and make any resize, rotate or
// reformatting changes here
mCamera.setDisplayOrientation(90);
// start preview with new settings
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e) {
Log.d(TAG, "Error starting camera preview: " + e.getMessage());
}
}
}
//Layout file
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<FrameLayout
android:id="#+id/camera_preview"
android:layout_width="300dp"
android:layout_height="400dp"
android:layout_centerHorizontal="true"
android:paddingTop="10dp" >
</FrameLayout>
</RelativeLayout>
You can't make your surfaceView bigger than the screen. That being said there are ways around it.
I found you can adjust the size of the canvas in the SurfaceView, which will allow zooming.
public class DrawingThread extends Thread {
private MagnificationView mainPanel;
private SurfaceHolder surfaceHolder;
private boolean run;
public DrawingThread(SurfaceHolder surface, MagnificationView panel){
surfaceHolder = surface;
mainPanel = panel;
}
public SurfaceHolder getSurfaceHolder(){
return surfaceHolder;
}
public void setRunning (boolean run){
this.run = run;
}
public void run(){
Canvas c;
while (run){
c = null;
try {
c = surfaceHolder.lockCanvas(null);
synchronized (surfaceHolder){
mainPanel.OnDraw(c);
}
} finally {
if (c != null){
surfaceHolder.unlockCanvasAndPost(c);
}
}
}
}
}
In the MagnificationView class add a method:
public void OnDraw(Canvas canvas){
if (canvas!=null){
canvas.save();
canvas.scale(scaleX,scaleY);
canvas.restore();
}
}
DrawingThread would be a thread you start in in your Activity. Also in your MagnificationView class override the OnTouchEvent to handle your own pinch-zoom (which will modify scaleX & scaleY.
Hope This solves your issue
What you can do is to get the window and set its height:
getWindow().setLayout(1000, 1000);
This makes your window larger than the screen making your root view and consequently your surfaceview, probably contained inside a Framelayout larger than screen.
This worked for me let me know.
The above would work no matter what. What you would want to do is listen for onSurfaceCreated event for your surface view. Then after you have the started the camera view and you are able to calculate size of your widget holding the preview, you would want to change size of the container widget.
The concept is your container widget (probably FrameLayout) wants to grow larger than screen. The screen itself is restricted by the activity so first set size of your window,
then set size of your framelayout (it would always be shrunk to max size of windows, so set accordingly).
I do all this logic after my onSurfaceCreated is finished I have started the preview. I listen for this event in my activity by implementing a small interface, as my Camera preview is a separate class.
Working on all API level >= 8
Here's my TouchSurfaceView's onMeasure that performs zoom:
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension((int) (width * scaleFactor), (int) (height * scaleFactor));
}
This properly zooms in and out depending on scaleFactor.
I haven't tested this with camera, but it works properly with MediaPlayer (behaving as VideoView).
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.
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