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.
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;
public class PhotoActivity extends Activity implements SurfaceHolder.Callback {
private ImageView imageView;
private SurfaceView mSurfaceView;
private Bitmap bmp;
private SurfaceHolder mSurfaceHolder;
private Camera mCamera;
private Parameters parameters;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mSurfaceView = (SurfaceView) findViewById(R.id.surface_camera);
imageView = (ImageView) findViewById(R.id.image_view);
mSurfaceHolder = mSurfaceView.getHolder();
mSurfaceHolder.addCallback(this);
mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
#Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
parameters = mCamera.getParameters();
mCamera.setParameters(parameters);
mCamera.startPreview();
Camera.PictureCallback mCall = new Camera.PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
bmp = BitmapFactory.decodeByteArray(data, 0, data.length);
imageView.setImageBitmap(bmp);
mSurfaceView.setVisibility(View.INVISIBLE);
// Call web service
SendPhotoAsync photoToWeb = new SendPhotoAsync(data);
photoToWeb.execute();
}
};
mCamera.takePicture(null, null, mCall);
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
mCamera = Camera.open();
mCamera.setDisplayOrientation(90);
try {
mCamera.setPreviewDisplay(holder);
} catch (IOException exception) {
mCamera.release();
mCamera = null;
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
#Override
protected void onResume() {
super.onResume();
}
#Override
protected void onPause() {
super.onPause();
}
how i could modify this code to detect face on camera preview,using face detector api in android.. any help please..
i also want to detect eyes then..hope someone can help me..i went through thiswhich works on button click.in my case for taking photo no button click is there..
someone with some productive code will be appreciable..please help me its very critical
if you have the android API for face detector..call this activity from the photo activity..in photo activity save the captured image to sd card...read this file in the face detector api..thus we can make it..but samsung galaxy+google nexus doesnt perform face detection..AAkash does..
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 have searched some solutions with my problem and sure there are many related issues regarding it but nothing solves my concern.
I am receiving a runtime exception : takepicture failed:native_autofocus..etc.
I tried to take picture from camera using autofocus and I can't seem to understand what could have caused the error.
Here is my code.
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mholder;
private Camera mcamera;
private Handler handler = new Handler();
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 surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
if (mholder.getSurface() == null) {
return;
}
try {
mcamera.stopPreview();
} catch (Exception e) {
Log.d("surfaceChanged", e.toString());
}
try {
mcamera.setPreviewDisplay(holder);
mcamera.startPreview();
} catch (IOException e) {
Log.d("surfaceChanged--->surfaceCreated", e.toString());
}
}
I think somethings is lacking in my runnable code, I tried to omit the runnable and execute autofocus once, it removed the runtime error. Did I missed to reinitialize something in this part?
private void autoFocus(Camera mcamera){
final Camera cam=mcamera;
handler.postDelayed(new Runnable() {
#Override
public void run() {
cam.autoFocus(autoFocusCallback);
handler.postDelayed(this, 1500L);
}
}, 1500L);
}
AutoFocusCallback autoFocusCallback=new AutoFocusCallback() {
#Override
public void onAutoFocus(boolean success, Camera camera) {
camera.takePicture(null, null, mPicture);
}
};
private PictureCallback mPicture=new PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
//do something
}
};
#Override
public void surfaceCreated(SurfaceHolder holder) {
try {
mcamera.setPreviewDisplay(holder);
mcamera.startPreview();
mcamera.autoFocus(autoFocusCallback);
} catch (IOException e) {
Log.d("surfaceCreated", e.toString());
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
}
You didn't mention it but be sure to include the permission in your manifest.
< uses-feature android:name="android.hardware.camera.autofocus" />
Have a look here
or here
and you are calling autofocus on surfacecreated ,
It should be called on surface changed