So, I have an Activity (say, OneActivity) that call another activity for result like this
public class OneActivity extends Activity {
private static final int REQUEST_OTHER = 1;
private ImageView btnStartAction;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstaceState);
setContentView(R.layout.homeView);
// UI Component Initialization.
}
// some code.
public void btnActionHandleClick(View v) {
Intent intent = new Intent(getApplicationContext(), OtherActivity.class);
intent.putExtra("parameter", "someValue");
startActivityForResult(intent, REQUEST_OTHER);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(requestCode == REQUEST_OTHER) {
// do something.
}
}
}
In the other hand, I have this OtherActivity that has handle for Camera feature and reciently I added Map handling because it was requested. Until the Map featuring request, the OtherActivity worked perfectly with Camera feature.
public class OtherActivity : FragmentActivity {
private static final int REQUEST_CAMERA = 1;
private ImageView btnTakePicture;
private ImageView btnClose;
private ImageView mImageView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.galeryView);
// UI Component Initialization.
mImageView = (ImageView) findViewById(R.id.mImageView);
}
public void btnTakePictureHandleClick(View v) {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(takePictureIntent, REQUEST_CAMERA);
}
}
public void btnCloseHandleClick(View v) {
Intent intent = new Intent();
intent.putExtra("returnVale", "returnValue");
if (getParent() == null) {
setResult(Activity.RESULT_OK, intent);
} else {
getParent().setResult(Activity.RESULT_OK, intent);
}
finish();
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(requestCode == REQUEST_CAMERA && resultCode == RESULT_OK) {
Bundle extras = data.getExtras();
Bitmap imageBitmap = (Bitmap) extras.get("data");
mImageView.setImageBitmap(imageBitmap);
}
}
}
Like I said before, this code was working perfectly but since I added Map interaction to the application I started to notice some weird behaviour when I take a picture: it start the ACTION_IMAGE_CAPTURE intent but after I take the picture it returns to the onActivityResult from OneActivity class with resultCode = RESULT_CANCELED.
By the way, the Map work fine and have the right interaction :P
Does anyone else has notice some behaviour like this before? Could be the Map featuring that cause this situation ?
Any opinion would be gratefully appreciated.
Thanks in advance!
I would suggest doing your own camera activity. This way you do not have to worry about manufactures different implementations. I got burned on this when Samsung changed their onActivityResult implementation with the Camera.
Here is a camera activity I have created:
public class DTechCameraActivity extends Activity implements OnClickListener {
//declare needed layout variables
private FrameLayout mCameraPreviewLayout;
private ImageView mCaputeredBitmapImageView;
private Button mCaptureImageButton, mRetakeImageButton, mSaveImageButton, mCancelImageButton;
//declare needed variables
private Camera mCamera;
private CameraPreview mPreview;
private String mBitmapSaveFileLocation;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dtech_camera);
//Create an instance of Camera
mCamera = CameraHelper.getCameraInstance();
//Get file location to save
mBitmapSaveFileLocation = getIntent().getExtras().getString(DCGroupActivity.CAMERA_DATA);
//Create and all click listeners for camera buttons
mCaptureImageButton = (Button) findViewById(R.id.camera_button_capture);
mCaptureImageButton.setOnClickListener(this);
mCaputeredBitmapImageView = (ImageView) findViewById(R.id.camera_image_holder);
mRetakeImageButton = (Button) findViewById(R.id.camera_button_retake);
mRetakeImageButton.setOnClickListener(this);
mSaveImageButton = (Button) findViewById(R.id.camera_button_save);
mSaveImageButton.setOnClickListener(this);
mCancelImageButton = (Button) findViewById(R.id.camera_button_cancel);
mCancelImageButton.setOnClickListener(this);
//Create our camera preview view and set as main activity view
mPreview = new CameraPreview(this, mCamera);
mCameraPreviewLayout = (FrameLayout) findViewById(R.id.camera_preview);
mCameraPreviewLayout.addView(mPreview);
showImageCaptureControls();
}
#Override
public void onBackPressed() {
closeDownCameraAndReturnResult(false);
}
#Override
public void onClick(View view) {
switch(view.getId()) {
case R.id.camera_button_capture:
mCamera.autoFocus(mAutoFocusCallback);
break;
case R.id.camera_button_retake:
showImageCaptureControls();
break;
case R.id.camera_button_save:
closeDownCameraAndReturnResult(true);
break;
case R.id.camera_button_cancel:
closeDownCameraAndReturnResult(false);
break;
}
}
private PictureCallback mPicture = new PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
showCapturedImageControls(data);
};
};
private AutoFocusCallback mAutoFocusCallback = new AutoFocusCallback() {
#Override
public void onAutoFocus(boolean success, Camera camera) {
mCamera.takePicture(null, null, mPicture);
}
};
private void showCapturedImageControls(byte[] imageBitmapData) {
mCamera.stopPreview();
mCameraPreviewLayout.setVisibility(View.GONE);
mCaptureImageButton.setVisibility(View.GONE);
mCaputeredBitmapImageView.setVisibility(View.VISIBLE);
mRetakeImageButton.setVisibility(View.VISIBLE);
mSaveImageButton.setVisibility(View.VISIBLE);
mCancelImageButton.setVisibility(View.VISIBLE);
saveImageToFile(imageBitmapData);
mCaputeredBitmapImageView.setImageBitmap(ImageManipulator.convertFileToBitmap(mBitmapSaveFileLocation));
}
private void saveImageToFile(byte[] imageBitmapData) {
ImageManipulator.saveInitialBitmap(imageBitmapData, mBitmapSaveFileLocation);
int angle = 90;//ImageManipulator.getTakenImageAngle(mBitmapSaveFileLocation);
if (angle > 0)
ImageManipulator.rotateAndSaveImage(mBitmapSaveFileLocation, angle);
else
ImageManipulator.saveReducedImage(mBitmapSaveFileLocation, BitmapFactory.decodeFile(mBitmapSaveFileLocation), true);
}
private void showImageCaptureControls() {
mCaputeredBitmapImageView.setVisibility(View.GONE);
mRetakeImageButton.setVisibility(View.GONE);
mSaveImageButton.setVisibility(View.GONE);
mCancelImageButton.setVisibility(View.GONE);
mCameraPreviewLayout.setVisibility(View.VISIBLE);
mCaptureImageButton.setVisibility(View.VISIBLE);
mCamera.startPreview();
}
private void closeDownCameraAndReturnResult(boolean actionSaveImage) {
mCamera.release();
if(!actionSaveImage)
setResult(RESULT_CANCELED);
else
setResult(RESULT_OK, new Intent());
this.finish();
}
}
This is how I called it:
mDTech.getSelectedEquipment().setImageDesc(
mEquipmentDescription.getText().toString());
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
cameraIntent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, getImageUri());
startActivityForResult(cameraIntent, DTechMobileApplication.CAMERA_REQUEST);
Here is my activityResult code:
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK
&& requestCode == DTechMobileApplication.CAMERA_REQUEST) {
String imageLocation = Environment.getExternalStorageDirectory()
.getAbsolutePath() + getImageLocation();
int angle = ImageManipulator.getTakenImageAngle(imageLocation);
if (angle > 0)
ImageManipulator.rotateAndSaveImage(imageLocation, angle);
else
ImageManipulator.saveReducedImage(imageLocation,
BitmapFactory.decodeFile(imageLocation), true);
saveEquipmentImageToPhone(mDTech.getSelectedEquipment()
.getImageID(), mDTech.getSelectedEquipment()
.getEquipmentID(), imageLocation, mDTech
.getSelectedJob().getJobID(), mDTech
.getAccessingEmployee().getTechID(), mDTech
.getAccessingEmployee().getName(), mDTech
.getSelectedEquipment().getEquipmentNum(), mDTech
.getSelectedEquipment().getDescription());
mTestImageUpload = SHOULD_UPLOAD_IMAGE;
}
}
Here is CameraHelper:
package com.Utilities;
import android.hardware.Camera;
public class CameraHelper {
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
}
}
And here is CameraPreview:
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
//declare needed constants
private final String CLASS_NAME = getClass().getName();
//declare needed variables
private SurfaceHolder mHolder;
private Camera mCamera;
public CameraPreview(Context context, Camera camera) {
super(context);
mCamera = camera;
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
// deprecated setting, but required on Android versions prior to 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, now tell the camera where to draw the preview.
try {
mCamera.setPreviewDisplay(holder);
mCamera.setDisplayOrientation(90);
} catch (IOException e) {
Log.d(CLASS_NAME, "Error setting camera preview: " + e.getMessage());
}
}
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.
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
// start preview with new settings
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e){
Log.d(CLASS_NAME, "Error starting camera preview: " + e.getMessage());
}
}
}
Well, it turns out that one of the views (layouts) should have the #android:noHistory=true flag set but instead of the right layout I put that configuration into the wrong layout. Because of the layout had the noHistory flag set on true, it never returns to onActivityResult but it returns to the previous activity.
So, it wasn't the Google Map Api nor the Camera feature ... it was my mistake :(
Related
public class CameraActivity
extends Activity
implements SurfaceHolder.Callback {
private LayoutInflater myInflater = null;
Camera myCamera;
byte[] tempdata;
boolean myPreviewRunning = false;
private SurfaceHolder mySurfaceHolder;
private SurfaceView mySurfaceView;
Button takePicture;
#Override
protected 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.activity_camera);
mySurfaceView = (SurfaceView) findViewById(R.id.surface);
if (mySurfaceHolder == null) {
mySurfaceHolder = mySurfaceView.getHolder();
}
mySurfaceHolder.addCallback(this);
mySurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
myInflater = LayoutInflater.from(this);
View overView = myInflater.inflate(R.layout.second_layer_camera,null);
this.addContentView(overView, new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT));
takePicture = (Button) findViewById(R.id.button);
takePicture.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
myCamera.takePicture(myShutterCallback, myPictureCallback, myJpeg);
}
});
}
ShutterCallback myShutterCallback = new ShutterCallback() {
#Override
public void onShutter() {
}
};
PictureCallback myPictureCallback = new PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera myCamera) {
}
};
PictureCallback myJpeg = new PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera myCamera) {
if(data != null){
tempdata = data;
done();
}
}
};
void done(){
Bitmap bm = BitmapFactory.decodeByteArray(tempdata, 0, tempdata.length);
String url = Images.Media.insertImage(getContentResolver(), bm, null, null);
bm.recycle();
Bundle bundle = new Bundle();
if(url != null){
bundle.putString("url",url);
Intent mIntent = new Intent();
mIntent.putExtras(bundle);
setResult(RESULT_OK, mIntent);
}
else{
Toast.makeText(this, "Picture can not be saved", Toast.LENGTH_SHORT).show();
}
// finish();
myCamera.startPreview();
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
try{
if(myPreviewRunning){
myCamera.stopPreview();
myPreviewRunning = false;
}
Camera.Parameters p = myCamera.getParameters();
p.setPreviewSize(width,height);
myCamera.setParameters(p);
myCamera.setPreviewDisplay(holder);
myCamera.startPreview();
myPreviewRunning = true;
}catch(Exception e){}
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
myCamera = Camera.open();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
myCamera.stopPreview();
myPreviewRunning = false;
myCamera.release();
myCamera = null;
}
}
When launching the app, the custom camera appears rotated. I need to show a normal camera. I find the reason for it opens the wrong camera.
I did not find another way to create a customized camera.
You need to tell the OS the orientation of the screen in relationship to the orientation the camera's sensor is mounted in. The orientation of the screen can be rotated, the orientation of the sensor is fixed. You can use the reference code for setDisplayOrientation(int) which can be found here: http://developer.android.com/reference/android/hardware/Camera.html#setDisplayOrientation%28int%29
So I was following the android developers build a camera application sample and have my camera activity up and running. However when I go to another activity then hit the back button I am getting a crash because the camera is null in the surface view's on surface created. Can someone explain how this error is happening. Thanks!
** Activity
public class PhotoCaptureActivity extends AppCompatActivity implements View.OnClickListener{
public static final String TAG = "PhotoCaptureActivity";
CameraPreview mPreviewScreen;
Button mCaptureButton;
ImageView mPreviewThumbnail;
TextView mPhotoActionLabel;
TextView mImageLogText;
Camera mCamera;
Camera.PictureCallback mPicture;
ArrayList<Bitmap> mPictures = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_photo_capture);
getSupportActionBar().hide();
mCaptureButton = (Button) findViewById(R.id.button_capture);
mPreviewThumbnail = (ImageView) findViewById(R.id.thumb_nail_image);
mPhotoActionLabel = (TextView) findViewById(R.id.photo_action_text);
mImageLogText = (TextView) findViewById(R.id.image_log);
mPicture = new Camera.PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
BitmapFactory.Options scalingOptions = new BitmapFactory.Options();
scalingOptions.inSampleSize = camera.getParameters().getPictureSize().width / mPreviewThumbnail.getMeasuredWidth();
final Bitmap bmp = BitmapFactory.decodeByteArray(data, 0, data.length, scalingOptions);
mPictures.add(bmp);
mPreviewThumbnail.setImageBitmap(bmp);
mPreviewThumbnail.setVisibility(ImageView.VISIBLE);
mCamera.startPreview();
mPhotoActionLabel.setText(getString(R.string.done));
}
};
mCaptureButton.setOnClickListener(this);
mPhotoActionLabel.setOnClickListener(this);
mImageLogText.setOnClickListener(this);
}
public static Camera getCameraInstance(){
Camera c = null;
try {
c = Camera.open(); // attempt to get a Camera instance
}
catch (Exception e){
e.printStackTrace();
}
return c; // returns null if camera is unavailable
}
#Override
public void onClick(View v) {
switch (v.getId()){
case R.id.button_capture:
mCamera.takePicture(null, null, mPicture);
break;
case R.id.photo_action_text:
if (mPhotoActionLabel.getText().toString().equalsIgnoreCase(getString(R.string.cancel)))
finish();
else {
Intent photoReviewIntent = new Intent(this,PhotoReviewActivity.class);
startActivity(photoReviewIntent);
}
break;
case R.id.image_log:
Intent imageLogIntent = new Intent(this,ImageLogActivity.class);
startActivity(imageLogIntent);
break;
}
}
#Override
public void onPause(){
super.onPause();
mCamera.stopPreview();
mCamera.release();
}
#Override
public void onResume(){
super.onResume();
if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
mCamera = getCameraInstance();
if (mCamera != null){
mPreviewScreen = new CameraPreview(this,mCamera);
FrameLayout frameLayout = (FrameLayout) findViewById(R.id.camera_preview);
frameLayout.addView(mPreviewScreen);
}
else
Toast.makeText(this, R.string.failed_to_open_camera, Toast.LENGTH_LONG).show();
}
else
Toast.makeText(this, R.string.no_camera_available, Toast.LENGTH_LONG).show();
}
}
** preview screen java class
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
public CameraPreview(Context context, Camera camera) {
super(context);
this.mCamera = camera;
mHolder = getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, now tell the camera where to draw the preview.
try {
mCamera.setPreviewDisplay(holder);
mCamera.setDisplayOrientation(90);
mCamera.startPreview();
} catch (IOException e) {
Log.i("Error starting camera", e.getLocalizedMessage());
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
if (mHolder.getSurface() == null){
// preview surface does not exist
return;
}
// stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception e){
}
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e){
Log.i("Error starting camera", e.getLocalizedMessage());
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
//Handeled in activity
}
}
In onResume(), an old mPreviewScreen may still exist, and cause problems. Consider adding the following to onPause():
if (mPreviewScreen != null) {
FrameLayout frameLayout = (FrameLayout) findViewById(R.id.camera_preview);
frameLayout.removeView(mPreviewScreen);
mPreviewScreen = null;
}
mCamera = null;
I have a surfaceview class used to take a picture with the camera, I want to know how to send back this image taken back to the class that called it. I tried sending the image back through an intent not sure if I implemented this correctly. I have the main class onActivityResult as follows:
//WHAT TO DO WITH RESULT DATA FROM CAMERA
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == CAMERA_PIC_REQUEST && picCount < 5) {
//curPic = (Bitmap) data.getExtras().get("data");
curPic = (Bitmap) data.getExtras().get("files");
ImageView images = new ImageView(getApplicationContext());
//SET PICTURE TO NEW VIEW AND ANIMATE INTO POSITION
images.setImageBitmap(curPic);
//ADD TO PREVPICS LAYOUT
images.setPadding(3, 0, 0, 0);
showCase.addView(images);
badge.setImageBitmap(curPic);
//ADDS CLICK LISTENER TO EACH ELEMENT AND SETS ID
try{
Log.i("AFTER TAKING PIC", "PICCOUNT IS NOW:"+picCount);
showCase.getChildAt(picCount).setId(picCount);
images.setId(picCount);
showCase.getChildAt(picCount).setOnClickListener(btnListener);
images.setTag("pics");
//SAVE PITCTURE
savePic(curPic);
previewImages(picCount);
}catch(Exception e){Log.e("ERROR TAKING PIC", e.toString());}
}else
Toast.makeText(getApplicationContext(), "Unable to add more pictures", Toast.LENGTH_SHORT).show();
}
And the surfaceview class as follows:
public class SecondCamera extends Activity implements SurfaceHolder.Callback {
Camera camera;
SurfaceView surfaceView;
SurfaceHolder surfaceHolder;
boolean previewing = false;
LayoutInflater controlInflater = null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.second_cam);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
getWindow().setFormat(PixelFormat.UNKNOWN);
surfaceView = (SurfaceView) findViewById(R.id.surfaceView1);
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.button1);
buttonTakePicture.setOnClickListener(new Button.OnClickListener() {
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
camera.takePicture(myShutterCallback, myPictureCallback_RAW,
myPictureCallback_JPG);
}
});
}
ShutterCallback myShutterCallback = new ShutterCallback() {
#Override
public void onShutter() {
}
};
PictureCallback myPictureCallback_RAW = new PictureCallback() {
#Override
public void onPictureTaken(byte[] arg0, Camera arg1) {
}
};
PictureCallback myPictureCallback_JPG = new PictureCallback() {
#Override
public void onPictureTaken(byte[] rawImg, Camera arg1) {
Bitmap bitmapPicture = BitmapFactory.decodeByteArray(rawImg, 0, rawImg.length);
try {
Intent cameraIntent = new Intent();
cameraIntent.putExtra("files", bitmapPicture);
setResult(123, cameraIntent);
finish();
} catch (Exception e) {
Log.e("IMAGE CONVERT", e.toString());
}
}
};
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
if (previewing) {
camera.stopPreview();
previewing = false;
}
if (camera != null) {
try {
camera.setPreviewDisplay(surfaceHolder);
camera.startPreview();
previewing = true;
} catch (IOException e) {
e.printStackTrace();
}
}
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
camera = Camera.open();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
camera.stopPreview();
camera.release();
camera = null;
previewing = false;
}
}
AFAIK, you can't pass a Bitmap through an Intent directly. I imagine you want to save this somewhere, say in local storage. You can save it using File methods. You can pass that file path as a String through the Intent and use that to access it in your previous Activity.
Another option could be to store it in an ArrayList and pass that as a Serializable
I'm trying to make a screen where the use will be able to take a photo. This photo will go to the database. The problem is, I've tried multiple approaches and in every approach, I need to use the PictureCallback. But the onPictureMethod from PictureCallback is never called, no matter what.
I already tried looking into this and this, but still can't move.
Edit: Using Android 2.2 (API 8)
EDITED CODE:
package touchcare.idealogix.android;
//imports
public class CameraActivityTest extends Activity implements SurfaceHolder.Callback
{
private SurfaceView surfaceCamera;
private SurfaceHolder holderCamera;
private Camera camera;
private Button btnCapture;
private PictureCallback mPictureJpg;
private PictureCallback mPictureRaw;
private ShutterCallback shutterCallback;
#Override public void onCreate(Bundle bundle){
super.onCreate(bundle);
setContentView(R.layout.layout_camera);
Log.d("PICTURE", "ACTIVITY START");
surfaceCamera = (SurfaceView) findViewById(R.id.surfaceCamera);
btnCapture = (Button) findViewById(R.id.btnCapture);
holderCamera = surfaceCamera.getHolder();
holderCamera.addCallback(this);
holderCamera.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
shutterCallback = new ShutterCallback()
{
#Override
public void onShutter()
{
//DONOTHING
}
};
mPictureRaw = new PictureCallback()
{
#Override
public void onPictureTaken(byte[] data, Camera camera)
{
//DONOTHING
}
};
mPictureJpg = new PictureCallback()
{
#Override
public void onPictureTaken(byte[] data, Camera camera)
{
Log.d("PICTURE", "ON PICTURE TAKEN START");
Intent intent = getIntent();
final boolean beds = intent.getExtras().getBoolean(Main.BEDS, false);
final boolean nurse = intent.getExtras().getBoolean(Main.NURSE, false);
final int position = intent.getExtras().getInt(Main.POSITION, 0);
if(beds)
{
BedroomDataSource bedDs = new BedroomDataSource(CameraActivityTest.this);
String where = SQLiteBedroomHelper.COLUMN_UID + "=" + AppData.getBedrooms().get(position).getUid();
bedDs.open();
bedDs.updateBedroom(where, null, null, null, null, null, null, data);
bedDs.close();
Log.d("PICTURE", "BEDS BOOLEAN");
AppData.getBedrooms().get(position).setImage(data);
}else if(nurse)
{
}
Log.d("PICTURE", "ON PICTURE TAKEN END");
finish();
}
};
btnCapture.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View arg0)
{
camera.takePicture(shutterCallback, mPictureRaw, mPictureJpg);
}
});
}
#Override public void surfaceCreated(SurfaceHolder holder)
{
camera = Camera.open();
Camera.Parameters params = camera.getParameters();
params.setPreviewSize(holder.getSurfaceFrame().width(), holder.getSurfaceFrame().height());
params.setPictureSize(32, 32);
params.setJpegQuality(100);
camera.setParameters(params);
try
{
camera.setPreviewDisplay(holder);
}catch(IOException ex){
Log.d("PICTURE", "PREVIEW EXCEPTION");
}
camera.startPreview();
Log.d("PICTURE", "SURFACE CREATED");
}
#Override public void surfaceChanged(SurfaceHolder holder, int format, int w, int h)
{
Log.d("PICTURE", "SURFACE CHANGED");
}
#Override public void surfaceDestroyed(SurfaceHolder holder)
{
camera.stopPreview();
camera.release();
Log.d("PICTURE", "SURFACE DESTROYED");
}
}
Thanks.
EDIT: Looks like that some photos are taken and the callback is reached. The database gets the photos, and loads back in bitmap just fine. But depending on what I'm taking a photo of, the callback isn't reaching. Smaller and simpler things are 100% chance the callback will be executed.
It looks like you create the callback mPicture, and then never set it as the callback for anything. I've never used any picture stuff, so I can't advise on where to set it, but as far as I know you need to register the callback for it to be called, just defining it won't do you any good.
I am working on an application using the camera. I want my application to have a custom menu that launches when the user presses the menu button.
Right now the application launches properly and the CameraPreview works fine. The menu opens correctly when the menu button is pressed. It even returns to the first activity from the menu when you press the button like it is supposed to.
The problem is that the CameraPreview no longer appears in the first activity when returning from the menu activity. What do I need to do so the CameraPreview will appear properly when returning to the first activity from the menu?
public class CameraMenuTest extends Activity implements Callback {
private Camera camera;
private MediaRecorder mediaRecorder;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
SurfaceView cameraPreview = (SurfaceView)findViewById(R.id.camera_preview);
SurfaceHolder holder = cameraPreview.getHolder();
holder.addCallback(this);
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public boolean onKeyDown(int keyCode, KeyEvent event) {
if ( keyCode == KeyEvent.KEYCODE_MENU ) {
Intent mIntent = new Intent(CameraMenuTest.this, CameraMenuTestMenu.class);
startActivityForResult(mIntent, 0);
return true;
}
return super.onKeyDown(keyCode, event);
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
mediaRecorder = new MediaRecorder();
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT);
mediaRecorder.setOutputFile("/sdcard/myoutputfile.mp4");
try {
mediaRecorder.prepare();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
if (mediaRecorder == null) {
try {
camera = Camera.open();
camera.setPreviewDisplay(holder);
camera.startPreview();
}
catch (IOException e){
Log.d("CAMERA", e.getMessage());
}
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
camera.stopPreview();
camera.release();
}
}
public class CameraMenuTestMenu extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.menu);
Button btn = (Button)findViewById(R.id.btn);
btn.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
finish();
return false;
}
});
}
}
I am assuming I need to do something in the onActivityResult() of the first activity.
I have tried:
public void onActivityResult(int requestCode, int resultCode, Intent data) {
SurfaceView cameraPreview = (SurfaceView)findViewById(R.id.camera_preview);
SurfaceHolder holder = cameraPreview.getHolder();
holder.addCallback(this);
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
and also:
public void onActivityResult(int requestCode, int resultCode, Intent data) {
camera = Camera.open();
camera.setPreviewDisplay(holder);
camera.startPreview();
}
Thank you for your help.
Move this part of your code from onCreate() to onResume():
SurfaceView cameraPreview = (SurfaceView)findViewById(R.id.camera_preview);
SurfaceHolder holder = cameraPreview.getHolder();
holder.addCallback(this);
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
Also modify the above block to this:
SurfaceView surfaceView = (SurfaceView) findViewById(R.id.camera_preview);
SurfaceHolder holder = surfaceView.getHolder();
if ( mediaRecorder != null) {
// The activity was paused but not stopped, so the surface still exists. Therefore
// surfaceCreated() won't be called, so init the camera here.
initCamera(holder);
} else {
// Install the callback and wait for surfaceCreated() to init the camera.
holder.addCallback(this);
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
the method initCamera(holder) should do the same things as the overridden method surfaceCreated().
Don't forget to release the camera in onPause():
#Override
protected void onPause() {
super.onPause();
if (camera != null) {
camera.stopPreview();
camera.release();
}
}
Good Luck!
Ok, sorry I missed the hasSurface flag - it's just set and cleared when surfaceCreated() and surfaceDestroyed() are called.
You have two options:
Option one
Since you are using an object, mediaRecorder, you can just check whether this is null to do the same thing, like this:
mediaRecorder != null. I've added it to the if statement above.
NOTE - if you are going to do this, you need to set mediaRecorder to null in surfaceDestroyed() so that the above if statement works.
Option two
If you wanted to use the boolean (member variable) (hasSurface), set it to
false in onCreate(),
false in surfaceDestroyed()
true in surfaceCreated() eg
if (!hasSurface) {
hasSurface = true;
initCamera(holder);
}
Let me know if this works for you.
Most likely reason is that when you return to your preview activity and surfaceCreated is called again, mediaRecorder is not null, thus the code that is supposed to start the preview is not executed.
That's probably because the SurfaceView breaks due to onPause/onResume being called. You need to reinitialize the camera preview during these times.
From the SDK docs:
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()).