I am making an android camera app that can show the preview and taking photo. There are 2 buttons implemented in this activity: Start the preview and stop the preview. When users click on the stop preview button, the app would capture a photo. However, when I was testing my app, the code associated with the stop preview seems to be skipped and not executed. Below is my code:
SuppressWarnings("deprecation")
public class CameraOpened extends Activity implements SurfaceHolder.Callback{
Camera camera;
SurfaceView surfaceView;
SurfaceHolder surfaceHolder;
boolean previewing = false;
static final int REQUEST_IMAGE_CAPTURE = 1;
int count;
PictureCallback rawCallback;
ShutterCallback shutterCallback;
PictureCallback jpegCallback;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera_opened);
Button buttonStartCameraPreview = (Button)findViewById(R.id.startcamerapreview);
Button buttonStopCameraPreview = (Button)findViewById(R.id.stopcamerapreview);
getWindow().setFormat(PixelFormat.UNKNOWN);
surfaceView = (SurfaceView)findViewById(R.id.surfaceview);
surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(this);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
shutterCallback = new ShutterCallback() {
public void onShutter() {
Log.i("Log", "onShutter'd");
}
};
rawCallback = new PictureCallback() {
public void onPictureTaken(byte[] data, Camera camera) {
Log.d("Log", "onPictureTaken - raw");
}
};
jpegCallback = new PictureCallback() {
public void onPictureTaken(byte[] data, Camera camera) {
FileOutputStream outStream = null;
try {
String dir;
dir = Environment.getExternalStorageDirectory().toString() + "/DCIM/";
File newdir = new File(dir);
newdir.mkdirs();
File imageFileName = new File(newdir, "crop_"+ ".jpg");
outStream = new FileOutputStream(imageFileName);
outStream.write(data);
outStream.close();
Log.d("Log", "onPictureTaken - wrote bytes: " + data.length);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
Log.d("Log", "onPictureTaken - jpeg");
}
};
buttonStartCameraPreview.setOnClickListener(new Button.OnClickListener(){
public void onClick(View v) {
// TODO Auto-generated method stub
if(!previewing){
camera = Camera.open();
camera.setDisplayOrientation(90);
if (camera != null){
try {
camera.setPreviewDisplay(surfaceHolder);
camera.startPreview();
previewing = true;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}});
buttonStopCameraPreview.setOnClickListener(new Button.OnClickListener(){
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(camera != null && previewing){
camera.takePicture(shutterCallback, rawCallback, jpegCallback);
previewing = false;
camera.stopPreview();
camera.release();
camera = null;
}
}});
}
public void savePhoto(Bitmap bmp)
{
String dir;
dir = Environment.getExternalStorageDirectory().toString() + "/DCIM/";
File newdir = new File(dir);
newdir.mkdirs();
FileOutputStream out = null;
//file name
Calendar c = Calendar.getInstance();
String date = fromInt(c.get(Calendar.MONTH))
+ fromInt(c.get(Calendar.DAY_OF_MONTH))
+ fromInt(c.get(Calendar.YEAR))
+ fromInt(c.get(Calendar.HOUR_OF_DAY))
+ fromInt(c.get(Calendar.MINUTE))
+ fromInt(c.get(Calendar.SECOND));
File imageFileName = new File(newdir, "crop_"+ ".jpg");
try
{
out = new FileOutputStream(imageFileName);
bmp.compress(Bitmap.CompressFormat.JPEG, 100, out);
out.flush();
out.close();
out = null;
} catch (Exception e)
{
e.printStackTrace();
}
}
public String fromInt(int val)
{
return String.valueOf(val);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.camera_opened, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
}
private void captureImage() {
// TODO Auto-generated method stub
//camera.takePicture(shutterCallback, rawCallback, jpegCallback);
}
}
And below is my LogCat:
10-22 20:28:38.218: D/Camera(14375): [CTA] Camera open urrentpackagename = com.camera
10-22 20:28:38.218: D/Camera(14375): [CTA] Camera open application != null
10-22 20:28:38.218: D/Camera(14375): [CTA] check CTA permisson mAllowUsing = true
10-22 20:28:39.258: I/Choreographer(14375): Skipped 61 frames! The application may be doing too much work on its main thread.
10-22 20:28:49.318: D/Camera(14375): [CTA] Camera open urrentpackagename = com.camera
10-22 20:28:49.318: D/Camera(14375): [CTA] Camera open application != null
10-22 20:28:49.318: D/Camera(14375): [CTA] check CTA permisson mAllowUsing = true
10-22 20:28:53.028: I/Choreographer(14375): Skipped 77 frames! The application may be doing too much work on its main thread.
Any idea on how to solve this problem?
Use Background Thread for camera operations i am hopeful it will helpful
ref# AsyncTask Android Guide
Related
I do not want my app to call native Camera app. All I want is to enable my app to take pics programatically when the app starts without any user interaction or involvement.
Here is my code:
public class CameraActivity extends Activity implements SurfaceHolder.Callback{
Camera camera;
PictureCallback rawCallback;
ShutterCallback shutterCallback;
PictureCallback jpegCallback;
ImageView view;
boolean inPreview = false;
#SuppressLint("NewApi")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
view = (ImageView)findViewById(R.id.pic);
Log.e("Camera Status: ",String.valueOf(checkCameraHardware(getApplicationContext())));
Log.e("Number Of Cameras: ",String.valueOf(Camera.getNumberOfCameras()));
start_camera();
captureImage();
rawCallback = new PictureCallback() {
public void onPictureTaken(byte[] data, Camera camera) {
Log.d("Log", "onPictureTaken - raw");
}
};
/** Handles data for jpeg picture */
shutterCallback = new ShutterCallback() {
public void onShutter() {
Log.i("Log", "onShutter'd");
}
};
jpegCallback = new PictureCallback() {
public void onPictureTaken(byte[] data, Camera camera) {
//Set the Image to ImageView
Bitmap bitmapPicture
= BitmapFactory.decodeByteArray(data, 0, data.length);
//view.setImageBitmap(bitmapPicture);
//Save the Image to SD Card
FileOutputStream outStream = null;
try {
outStream = new FileOutputStream(String.format(
"/sdcard/%d.jpg", System.currentTimeMillis()));
outStream.write(data);
outStream.close();
Log.d("Log", "onPictureTaken - wrote bytes: " + data.length);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
Log.d("Log", "onPictureTaken - jpeg");
/**
* The two lines below are used to refresh the Surface View
* It works quickly then the general refresh by Default
**/
stop_camera();
start_camera();
}
};
//start_camera();
}
/** Check if this device has a camera */
private boolean checkCameraHardware(Context context) {
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
// this device has a camera
return true;
} else {
// no camera on this device
return false;
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
public static Camera getCameraInstance(){
Camera c = null;
try {
c = Camera.open(); // attempt to get a Camera instance
}
catch (Exception e){
// Camera is not available (in use or does not exist)
}
return c; // returns null if camera is unavailable
}
private void start_camera()
{
try{
camera = Camera.open();
Log.e("Camera Open Status: ", "Camera opened successfully");
}catch(RuntimeException e){
Log.e("Camera Initialization:", "init_camera: " + e);
return;
}
Camera.Parameters param;
param = camera.getParameters();
//modify parameter
param.setPreviewFrameRate(20);
param.setPreviewSize(176, 144);
camera.setParameters(param);
try {
//camera.setPreviewDisplay(surfaceHolder);
camera.startPreview();
//camera.takePicture(shutter, raw, jpeg)
} catch (Exception e) {
Log.e("Camera Initialization:", "init_camera: " + e);
return;
}
inPreview=true;
}
private void captureImage() {
// TODO Auto-generated method stub
AudioManager mgr = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
mgr.setStreamMute(AudioManager.STREAM_SYSTEM, true);
camera.takePicture(shutterCallback, rawCallback, jpegCallback);
Log.e("Picture Status: ","picture taken successfully");
final Handler handler = new Handler();
Timer t = new Timer();
t.schedule(new TimerTask() {
public void run() {
handler.post(new Runnable() {
public void run() {
AudioManager mgr = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
mgr.setStreamMute(AudioManager.STREAM_SYSTEM, false);
}
});
}
}, 1000);
}
private void stop_camera()
{
camera.stopPreview();
camera.release();
inPreview = false;
}
#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
}
}
Download the project form here
Copy the CameraLibrary into your workspace
Add these to your manifest
<uses-sdk
android:minSdkVersion="10"
android:targetSdkVersion="10" />
<uses-features android:name="android.hardware.camera"/>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<activity android:name="com.girish.cameraLibrary.CameraClass"></activity>
Now in your activity implement the com.girish.cameraLibrary.OnPictureTaken interface and Override the pictureTaken(Bitmap bitmap, File file) method which provides your with the bitmap and File
Now Create and instance of the CustomCamera
private CustomCamera mCustomCamera;
mCustomCamera = new CustomCamera(MainActivity.this);
mCustomCamera.setPictureTakenListner(this);
//To start the custom back camera use this
mCustomCamera.startCamera();
//To send an intent to applications who are listening to Camera request
mCustomCamera.sendCameraIntent();
//To start the front camera use this
mCustomCamera.startCameraFront();
The now you can access the image using pictureTaken(Bitmap bitmap, File file) method, so just use
imageview.setImageBitmap(bitmap);
EDIT
Suppose your main class is called MainActivity the write like this
public class MainActivity extends Activity implements OnPictureTaken {
.....
.....
.....
#Override
protected void onCreate(Bundle savedInstanceState) {
.....
.....
.....
//This is where you get the picture
#Override
public void pictureTaken(Bitmap bitmap, File file) {
imgCapture.setImageBitmap(bitmap);
txtPath.setText(file.getAbsolutePath());
}
Check the sample file as mentioned here
I Created a app that captures image and stores in the SD Card. The app seems to work fine with the previewing. But the problem is that when I run the app on my phone through eclipse the image gets captured. If I run my app in a normal way and try to capture the image, the image doesn't get captured.
I have attached my code below
My MainActivity.class
public class MainActivity extends Activity {
private ImageHandler preview;
Camera camera;
int cameraID, currentCamera;
Button capture;
FrameLayout imageLayout;
SurfaceView imgl;
private static final String TAG = "CallCamera";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/*
* Invoking Camera and Setting the ImageHandler for preview
*/
camera = getCameraInstance();
preview = new ImageHandler(this, camera);
/*
* Getting the ID of the FrameLayout that displays the camera
*/
imageLayout = (FrameLayout) findViewById(R.id.preview_layout);
imageLayout.addView(preview);
/*
* Getting the ID of capture Button and setting its Functionality
*/
capture = (Button) findViewById(R.id.cameraButton);
capture.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
camera.takePicture(null, null, null, pic);
}
});
}
private Camera getCameraInstance() {
// TODO Auto-generated method stub
Camera cam = null;
try {
cam = Camera.open();
} catch (Exception e) {
}
return cam;
}
PictureCallback pic = new PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
// TODO Auto-generated method stub
// File picFile = getOutputPhotoFile();
// if(picFile == null){
// return;
// }
//
// try{
// FileOutputStream fos = new FileOutputStream(picFile);
// fos.write(data);
// fos.close();
//
// }catch(FileNotFoundException e){
//
// }catch (IOException e){
//
// }
//
File pictureFileDir = getDir();
if (!pictureFileDir.exists() && !pictureFileDir.mkdirs()) {
Log.d(TAG, "Can't create directory to save image.");
Toast.makeText(getApplicationContext(),
"Can't create directory to save image.",
Toast.LENGTH_LONG).show();
return;
}
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyymmddhhmmss");
String date = dateFormat.format(new Date());
String photoFile = "Picture_" + date + ".jpg";
String filename = pictureFileDir.getPath() + File.separator
+ photoFile;
File pictureFile = new File(filename);
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
Toast.makeText(getApplicationContext(),
"New Image saved:" + photoFile, Toast.LENGTH_LONG)
.show();
} catch (Exception error) {
Log.d(TAG,
"File" + filename + "not saved: " + error.getMessage());
Toast.makeText(getApplicationContext(),
"Image could not be saved.", Toast.LENGTH_LONG).show();
}
camera.startPreview();
}
private File getDir() {
File sdDir = Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
return new File(sdDir, "CameraAPIDemo");
}
};
// private File getOutputPhotoFile() {
//
// File directory = new File(
// Environment
// .getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
// "IMAGES_CAMERA");
//
// if (!directory.exists()) {
// if (!directory.mkdirs()) {
// Log.e(TAG, "Failed to create storage directory.");
// return null;
// }
// }
//
// String timeStamp = new SimpleDateFormat("yyyMMdd_HHmmss")
// .format(new Date());
//
// return new File(directory.getPath() + File.separator + "IMG_"
// + timeStamp + ".jpg");
// }
//
#Override
public void onResume() {
super.onResume();
if (camera == null) {
camera = Camera.open();
preview.setCamera(camera);
}
}
}
My Preview/ ImageHandler.class
public class ImageHandler extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder holder;
private Camera imgCamera;
List<Size> imgSupportedPreviewSizes;
public ImageHandler(Context context, Camera camera) {
super(context);
// TODO Auto-generated constructor stub
this.imgCamera = camera;
this.holder = this.getHolder();
this.holder.addCallback(this);
this.holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
try {
imgCamera.setPreviewDisplay(holder);
imgCamera.startPreview();
} catch (IOException e) {
}
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
try {
imgCamera.setPreviewDisplay(holder);
imgCamera.startPreview();
imgCamera.setDisplayOrientation(90);
} catch (Exception e) {
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
imgCamera.stopPreview();
imgCamera.release();
}
public void setCamera(Camera camera) {
imgCamera = camera;
if (imgCamera != null) {
imgSupportedPreviewSizes = imgCamera.getParameters()
.getSupportedPreviewSizes();
requestLayout();
}
}
}
I want to be able to capture image when I run the app normally through my phone.
In my code i have camera preview and video recording on button click so my code works well for recording and preview.
but when i press back button then surfaceview create and surface view change method get called after that surfaceview destroy method called so i have to press back button again and at this time it directly call surface destroy ( second time surface create and surface change is not called)
Here is my code any body can help me?
public class VideoCapture extends Activity implements SurfaceHolder.Callback {
public static final String LOGTAG = "VIDEOCAPTURE";
private static final int SELECT_PHOTO = 100;
private MediaRecorder recorder;
private SurfaceHolder holder;
private CamcorderProfile camcorderProfile;
private Camera camera;
boolean recording = false;
boolean usecamera = true;
boolean previewRunning = false;
Button recorderButton,selectVideo;
long init,now,time;
Handler handler;
Runnable updater;
SimpleDateFormat df;
Camera.Parameters parameters;
String timeString, timeStamp,selectedVideoPath;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
setContentView(R.layout.main);
handler = new Handler();
df = new SimpleDateFormat("mm:ss");
camcorderProfile = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH);
recorderButton = (Button)findViewById(R.id.button);
selectVideo = (Button)findViewById(R.id.videoselect);
final TextView timerText = (TextView)findViewById(R.id.time);
File dir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DCIM), "/Filme");
if (!dir.exists()) {
dir.mkdirs();
}
// Animation for blinking red dot while recording
SurfaceView cameraView = (SurfaceView) findViewById(R.id.CameraView);
holder = cameraView.getHolder();
holder.addCallback(this);
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
cameraView.setClickable(true);
cameraView.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v) {
camera.autoFocus(new AutoFocusCallback(){
#Override
public void onAutoFocus(boolean arg0, Camera arg1) {
//camera.takePicture(shutterCallback, rawCallback, jpegCallback);
}
});
}
});
selectVideo.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
photoPickerIntent.setType("video/*");
startActivityForResult(photoPickerIntent, SELECT_PHOTO);
}
});
recorderButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if (recording) {
recorderButton.setBackgroundResource(R.drawable.recordbutton_background_selector);
recorder.stop();
handler.removeCallbacks(updater); // stop handler
// to refresh media scan on storage
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse
("file://" + Environment.getExternalStorageDirectory())));
String filepath =Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)+File.separator+"Filme"+File.separator+"Filme_"+timeStamp+".mp4";
Intent i = new Intent(getBaseContext(),VideoCutActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.putExtra("path", filepath);
getBaseContext().startActivity(i);
finish();
/*
if (usecamera) {
try {
camera.reconnect();
} catch (IOException e) {
e.printStackTrace();
}
}
*/
recording = false;
Log.v(LOGTAG, "Recording Stopped");
// Let's prepareRecorder so we can record again
// prepareRecorder();
} else {
recorderButton.setBackgroundResource(R.drawable.stopbutton_background_selector);
recording = true;
prepareRecorder();
// recorder.start();
Log.v(LOGTAG, "Recording Started");
}
}
});
// Recording timmer
updater = new Runnable() {
#Override
public void run() {
now=System.currentTimeMillis();
time=now-init;
timeString = df.format(new Date(time));
timerText.setText(timeString);
handler.postDelayed(this, 30);
}
};
}
#Override
protected void onResume() {
super.onResume();
Log.e("onresume", "on resume");
// Open the default i.e. the first rear facing camera.
}
#Override
protected void onPause() {
super.onPause();
// Because the Camera object is a shared resource, it's very
// important to release it when the activity is paused.
if (recording) {
recorder.stop();
recording = false;
recorder.release();
camera.stopPreview();
camera.setPreviewCallback(null);
camera.release();
camera = null;
}
else
{
if (camera != null) {
previewRunning = false;
camera.release();
camera = null;
}
}}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent imageReturnedIntent) {
super.onActivityResult(requestCode, resultCode, imageReturnedIntent);
switch(requestCode) {
case SELECT_PHOTO:
if(resultCode == RESULT_OK){
Uri selectedImage = imageReturnedIntent.getData();
selectedVideoPath = getPath(selectedImage);
Intent i = new Intent(getBaseContext(),VideoCutActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.putExtra("path", selectedVideoPath);
VideoCapture.this.startActivity(i);
finish();
}
}
}
public String getPath(Uri uri) {
String[] proj = { MediaStore.Images.Media.DATA };
CursorLoader loader = new CursorLoader(getBaseContext(), uri, proj, null, null, null);
Cursor cursor = loader.loadInBackground();
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
}
private void prepareRecorder() {
recorder = new MediaRecorder();
recorder.setPreviewDisplay(holder.getSurface());
if (usecamera) {
camera.unlock();
recorder.setCamera(camera);
}
recorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
recorder.setVideoSource(MediaRecorder.VideoSource.DEFAULT);
recorder.setProfile(camcorderProfile);
timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
recorder.setOutputFile(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)+File.separator+"Filme"+File.separator+"Filme_"+timeStamp+".mp4");
Log.v(LOGTAG, "camcorderProfile");
try {
recorder.prepare();
recorder.start();
init = System.currentTimeMillis();
handler.post(updater);
} catch (IllegalStateException e) {
e.printStackTrace();
finish();
} catch (IOException e) {
e.printStackTrace();
finish();
}
}
public void surfaceCreated(SurfaceHolder holder) {
Log.v(LOGTAG, "surfaceCreated");
if (usecamera) {
camera = Camera.open();
parameters = camera.getParameters();
try {
Log.i("Capture","surface created");
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
camera.setParameters(parameters);
camera.setPreviewDisplay(holder);
camera.startPreview();
previewRunning = true;
}
catch (IOException e) {
Log.e(LOGTAG,e.getMessage());
e.printStackTrace();
}
}
}
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
Log.v(LOGTAG, "surfaceChanged");
if (!recording && usecamera) {
if (previewRunning){
Log.e("Capture","preview is running");
camera.stopPreview();
}
try {
Log.e("Capture","inside try of surface changed");
parameters = camera.getParameters();
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
parameters.setPreviewSize(camcorderProfile.videoFrameWidth, camcorderProfile.videoFrameHeight);
parameters.setPreviewFrameRate(camcorderProfile.videoFrameRate);
camera.setParameters(parameters);
camera.setPreviewDisplay(holder);
camera.startPreview();
previewRunning = true;
}
catch (IOException e) {
Log.e(LOGTAG,e.getMessage());
e.printStackTrace();
}
// prepareRecorder();
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
Log.v(LOGTAG, "surfaceDestroyed");
if (camera != null) {
camera.stopPreview();
}
if (recording) {
try{
Log.e("Capture","inside recording of surface destory");
recorder.stop();
recording = false;
recorder.release();
camera.stopPreview();
camera.setPreviewCallback(null);
camera.release();
camera = null;
}
catch (RuntimeException e) {
Log.d("surface destroyed", "Problem in surfaceDestroyed");
e.printStackTrace();
}
}
Based on debugging/discussion on chat:
the first time back is being hit, the existing Camera activity gets destroyed and another one is created. Used the following to follow the changes in the back stack:
adb shell dumpsys activity | grep -i run
No new task is required, so this is useless:
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Apparently, using i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) helps!
I'm not sure why exactly this is helping though. (Especially, because IIUC, with *CLEAR_TOP, the existing instance of the activity on the stack would be used (with onNewIntent), but here (based on the output from dumpsys, a new activity gets created :|). But it works on archos.
UPDATE
Added
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
to the manifest all works ok now.
Ok so I have a app I have started to create which in the end I want to be able to take a picture, which then takes you to another screen which lets you be able to "Use" or "Retake" the picture.
When the image is took it needs to be saved into a new folder on the SD Card, (if the folder is not there then it needs to create it). I had all this working a couple of weeks ago but after i did some editing and shut down eclipse I cant seem to get it back working?
The section for this is after int imageNum = 0; i have added imagesFolder.mkdirs(); which i belive is correct to create a new folder but even this seems not to be working now.
Now the image just gets took and neither the new folder gets created or the image gets saved.
public class AndroidCamera extends Activity implements SurfaceHolder.Callback {
Camera camera;
SurfaceView surfaceView;
SurfaceHolder surfaceHolder;
boolean previewing = false;
LayoutInflater controlInflater = null;
final int RESULT_SAVEIMAGE = 0;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
getWindow().setFormat(PixelFormat.UNKNOWN);
surfaceView = (SurfaceView) findViewById(R.id.camerapreview);
surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(this);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
controlInflater = LayoutInflater.from(getBaseContext());
View viewControl = controlInflater.inflate(R.layout.control, null);
LayoutParams layoutParamsControl = new LayoutParams(
LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
this.addContentView(viewControl, layoutParamsControl);
Button buttonTakePicture = (Button) findViewById(R.id.takepicture);
buttonTakePicture.setOnClickListener(new Button.OnClickListener() {
public void onClick(View arg0) {
// TODO Auto-generated method stub
camera.takePicture(myShutterCallback, myPictureCallback_RAW,
myPictureCallback_JPG);
}
});
}
ShutterCallback myShutterCallback = new ShutterCallback() {
public void onShutter() {
// TODO Auto-generated method stub
}
};
PictureCallback myPictureCallback_RAW = new PictureCallback() {
public void onPictureTaken(byte[] arg0, Camera arg1) {
// TODO Auto-generated method stub
}
};
PictureCallback myPictureCallback_JPG = new PictureCallback(){
public void onPictureTaken(byte[] arg0, Camera arg1) {
// TODO Auto-generated method stub
/*Bitmap bitmapPicture
= BitmapFactory.decodeByteArray(arg0, 0, arg0.length); */
int imageNum = 0;
Intent imageIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
File imagesFolder = new File(Environment.getExternalStorageDirectory(), "BeatEmUp");
imagesFolder.mkdirs();
String fileName = "image_" + String.valueOf(imageNum) + ".jpg";
File output = new File(imagesFolder, fileName);
while (output.exists()){
imageNum++;
fileName = "image_" + String.valueOf(imageNum) + ".jpg";
output = new File(imagesFolder, fileName);
}
Uri uriSavedImage = Uri.fromFile(output);
imageIntent.putExtra(MediaStore.EXTRA_OUTPUT, uriSavedImage);
OutputStream imageFileOS;
try {
imageFileOS = getContentResolver().openOutputStream(uriSavedImage);
imageFileOS.write(arg0);
imageFileOS.flush();
imageFileOS.close();
Toast.makeText(AndroidCamera.this,
"Image saved: ",
Toast.LENGTH_LONG).show();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
camera.startPreview();
}};
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
if (previewing) {
camera.stopPreview();
previewing = false;
}
if (camera != null) {
try {
camera.setPreviewDisplay(surfaceHolder);
camera.startPreview();
previewing = true;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
camera = Camera.open();
try {
Camera.Parameters parameters = camera.getParameters();
if (this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE) {
// This is an undocumented although widely known feature
parameters.set("orientation", "portrait");
// For Android 2.2 and above
camera.setDisplayOrientation(90);
// Uncomment for Android 2.0 and above
parameters.setRotation(90);
} else {
// This is an undocumented although widely known feature
parameters.set("orientation", "landscape");
// For Android 2.2 and above
camera.setDisplayOrientation(0);
// Uncomment for Android 2.0 and above
parameters.setRotation(0);
}
camera.setParameters(parameters);
camera.setPreviewDisplay(holder);
} catch (IOException exception) {
camera.release();
}
camera.startPreview();
}
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
camera.stopPreview();
camera.release();
camera = null;
previewing = false;
}
}
You should make sure the manifest lists the permission to write to the SD card:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Ok this has been happening to me a few times over the past few weeks and I can't figure out how to fix it. Basically my app uses the camera but every so often after a few goes with the camera on the app it then force closes sometimes and cannot be used even with other apps or the default camera on the phone.
I found the only way to fix this is to restart the phone.
From what I have read so far I understand I need to call
camera.release();
camera = null;
But I still get the error of force close sometimes, is it possible for someone just to take a look through maybe I am missing a camera.release(); somewhere.
public class AndroidCamera extends Activity implements SurfaceHolder.Callback{
Camera camera;
SurfaceView surfaceView;
SurfaceHolder surfaceHolder;
boolean previewing = false;
LayoutInflater controlInflater = null;
final int RESULT_SAVEIMAGE = 0;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
getWindow().setFormat(PixelFormat.UNKNOWN);
surfaceView = (SurfaceView)findViewById(R.id.camerapreview);
surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(this);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
controlInflater = LayoutInflater.from(getBaseContext());
View viewControl = controlInflater.inflate(R.layout.control, null);
LayoutParams layoutParamsControl
= new LayoutParams(LayoutParams.FILL_PARENT,
LayoutParams.FILL_PARENT);
this.addContentView(viewControl, layoutParamsControl);
Button buttonTakePicture = (Button)findViewById(R.id.takepicture);
buttonTakePicture.setOnClickListener(new Button.OnClickListener(){
public void onClick(View arg0) {
// TODO Auto-generated method stub
camera.takePicture(myShutterCallback,
myPictureCallback_RAW, myPictureCallback_JPG);
}});
}
ShutterCallback myShutterCallback = new ShutterCallback(){
public void onShutter() {
// TODO Auto-generated method stub
}};
PictureCallback myPictureCallback_RAW = new PictureCallback(){
public void onPictureTaken(byte[] arg0, Camera arg1) {
// TODO Auto-generated method stub
}};
PictureCallback myPictureCallback_JPG = new PictureCallback(){
public void onPictureTaken(byte[] arg0, Camera arg1) {
// TODO Auto-generated method stub
/*Bitmap bitmapPicture
= BitmapFactory.decodeByteArray(arg0, 0, arg0.length); */
int imageNum = 0;
Intent imageIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
File imagesFolder = new File(Environment.getExternalStorageDirectory(), "Punch");
imagesFolder.mkdirs(); // <----
String fileName = "image_" + String.valueOf(imageNum) + ".jpg";
File output = new File(imagesFolder, fileName);
while (output.exists()){
imageNum++;
fileName = "image_" + String.valueOf(imageNum) + ".jpg";
output = new File(imagesFolder, fileName);
}
Uri uriSavedImage = Uri.fromFile(output);
imageIntent.putExtra(MediaStore.EXTRA_OUTPUT, uriSavedImage);
OutputStream imageFileOS;
try {
imageFileOS = getContentResolver().openOutputStream(uriSavedImage);
imageFileOS.write(arg0);
imageFileOS.flush();
imageFileOS.close();
Toast.makeText(AndroidCamera.this,
"Image saved",
Toast.LENGTH_LONG).show();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Intent intent = new Intent(getBaseContext(), Punch.class);
intent.putExtra("filepath",uriSavedImage.toString());
//just using a request code of zero
int request=0;
startActivityForResult(intent,request);
}};
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
if(previewing){
camera.stopPreview();
previewing = false;
}
if (camera != null){
try {
camera.setPreviewDisplay(surfaceHolder);
camera.startPreview();
previewing = true;
} catch (IOException e) {
// TODO Auto-generated catch block
camera.release();
e.printStackTrace();
}
}
}
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
camera = Camera.open();
try {
Camera.Parameters parameters = camera.getParameters();
if (this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE) {
// This is an undocumented although widely known feature
parameters.set("orientation", "portrait");
// For Android 2.2 and above
camera.setDisplayOrientation(90);
// Uncomment for Android 2.0 and above
parameters.setRotation(90);
} else {
// This is an undocumented although widely known feature
parameters.set("orientation", "landscape");
// For Android 2.2 and above
camera.setDisplayOrientation(0);
// Uncomment for Android 2.0 and above
parameters.setRotation(0);
}
camera.setParameters(parameters);
camera.setPreviewDisplay(holder);
} catch (IOException exception) {
camera.release();
}
camera.startPreview();
}
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
if(previewing && camera != null) {
if(camera!=null) {
camera.stopPreview();
camera.release();
camera = null;
}
previewing = false;
}
}
}
The logcat gave me (there is more but I think its because the camera force closes on me so the rest of the app doesn't run.
01-03 14:59:17.835: D/AndroidRuntime(16531): Shutting down VM
01-03 14:59:17.835: W/dalvikvm(16531): threadid=1: thread exiting with uncaught exception (group=0x4001d5a0)
01-03 14:59:17.845: E/AndroidRuntime(16531): FATAL EXCEPTION: main
01-03 14:59:17.845: E/AndroidRuntime(16531): java.lang.RuntimeException: Fail to connect to camera service
I solved the same problem with closing camera in onPause() event
#Override
protected void onPause()
{
super.onPause();
if (camera != null) {
camera.stopPreview();
camera.release();
camera = null;
}
}