I was working on an android app that is using the camera (CWAC) and it worked ok before updating to android 5.0.2, after the update if I take a picture the camera.takePicture is called in CameraView:
postDelayed(new Runnable() {
#Override
public void run() {
try {
camera.takePicture(xact, new PictureTransactionCallback(xact),
new PictureTransactionCallback(xact));
}
catch (Exception e) {
android.util.Log.e(getClass().getSimpleName(),
"Exception taking a picture", e);
// TODO get this out to library clients
}
}
}, xact.host.getDeviceProfile().getPictureDelay());
This is the PictureTransactionCallback:
private class PictureTransactionCallback implements
Camera.PictureCallback {
PictureTransaction xact=null;
PictureTransactionCallback(PictureTransaction xact) {
this.xact=xact;
}
#Override
public void onPictureTaken(byte[] data, Camera camera) {
camera.setParameters(previewParams);
if (data != null) {
new ImageCleanupTask(getContext(), data, cameraId, xact).start();
}
if (!xact.useSingleShotMode()) {
startPreview();
}
}
}
The problem is that if I run the app on android 5.0.2 onPictureTaken from the PictureTransactionCallback is never triggered (I ran the app with debug) on the same phone but with android 4.4.2 onPictureTaken is triggered and simpleCameraHost.saveImage is called. I can't find the cause of the problem.
Related
I want to create an application, and it needs to know when the camera is turned on by other app, whether the camera application is open or if a third party app is using the camera
how can i detect that if other app is try to open the camera . if other app try to open the camera i want to receive any broadcast before open the camera how can i do this.
i have also try this.
public boolean isCameraUsebyApp() {
Camera camera = null;
try {
camera = Camera.open();
} catch (RuntimeException e) {
return true;
} finally {
if (camera != null) camera.release();
}
return false;
}
but its alwys return true.
There is no broadcast for camera open or not but Camera Avaiability Listener in Camera2 Api, use below code
CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
manager.registerAvailabilityCallback(new CameraManager.AvailabilityCallback() {
#Override
public void onCameraAvailable(String cameraId) {
super.onCameraAvailable(cameraId);
//Do your work
}
#Override
public void onCameraUnavailable(String cameraId) {
super.onCameraUnavailable(cameraId);
//Do your work
}
}, mHandler);
}
its only 21 and above
For below 21 you can use your code
public boolean isCameraInUse() {
Camera c = null;
try {
c = Camera.open();
} catch (RuntimeException e) {
return true;
} finally {
if (c != null) c.release();
}
return false;
}
Problem background
I am developing a VR Project on Unreal Engine 4, and the project requires the usage of Android's native camera. Since there are no built-in functions in UE4 to iteract with Android's native methods, I customized this plugin under my need.
The original plugin uses the JNI interface to iteract with C++ code. It calls camera.open() and camera.startPreview() on UE4's EventBeginPlay, and calls camera.stopPreview() and camera.Release() on UE4's EventEndPlay. Since it is a known issue that EventEndPlay never fires up on Android platform, I decided to manipulate the camera in onResume() and onPause() methods. Here is the code:
<gameActivityClassAdditions>
<insert>
/* Unrelevant code goes here */
...
...
/* End of unrelevant code */
public void AndroidThunkJava_startCamera()
{
surfaceTexture = new SurfaceTexture(10);
surfaceTexture.setDefaultBufferSize(preferredWidth, preferredHeight);
if (camera == null){
try {
camera = Camera.open();
} catch (RuntimeException exc) {
return;
}
}
try {
camera.setPreviewTexture(surfaceTexture);
} catch (IOException t) {
return;
}
Parameters cameraParam = camera.getParameters();
cameraParam.setPreviewFormat(ImageFormat.NV21);
cameraParam.setPreviewSize(preferredWidth, preferredHeight);
cameraParam.setPreviewFpsRange(preferredFPS, preferredFPS);
cameraParam.setFocusMode(Camera.Parameters.FOCUS_MODE_MACRO);
if (cameraParam.isVideoStabilizationSupported()) {
cameraParam.setVideoStabilization(false);
}
if (cameraParam.isAutoWhiteBalanceLockSupported()) {
cameraParam.setAutoWhiteBalanceLock(false);
}
camera.setParameters(cameraParam);
camera.setPreviewCallback(new PreviewCallback() {
#Override
public void onPreviewFrame(byte[] data, Camera camera) {
int Height = camera.getParameters().getPreviewSize().height;
int Width = camera.getParameters().getPreviewSize().width;
// calling C++ function via JNI interface
processFrameData(Width, Height, data);
}
});
camera.startPreview();
}
public void AndroidThunkJava_stopCamera()
{
if (camera != null)
{
camera.stopPreview();
camera.release();
camera = null;
}
}
</insert>
</gameActivityClassAdditions>
<gameActivityOnPauseAdditions>
<insert>
AndroidThunkJava_stopCamera();
</insert>
</gameActivityOnPauseAdditions>
<gameActivityOnResumeAdditions>
<insert>
AndroidThunkJava_startCamera();
</insert>
</gameActivityOnResumeAdditions>
The problem
The camera works fine every second time. That means:
I open the app, camera is working. I pushed the home button (which triggers onPause() method), then switch back to the app (triggers onResume() method). Pushed the home button again, and then switched back - camera works. And so on, the camera works every second time.
Anybody have any idea about this issue? Is that connected to the fact that android.hardware.Camera is deprecated? I'm using API version 19, so it is not possible to use newer android.hardware.camera2.
Here is my onStop and onResume methods. I'm not using onPause. And it works perfectly:
#Override
protected void onResume() {
super.onResume();
if (mCamera == null) {
restartPreview();
}
}
#Override
public void onStop() {
// stop the preview
if (mCamera != null) {
stopCameraPreview();
mCamera.release();
mCamera = null;
}
super.onStop();
}
private void restartPreview() {
if (mCamera != null) {
stopCameraPreview();
mCamera.release();
mCamera = null;
}
getCamera(mCameraID);
startCameraPreview();
}
private void startCameraPreview() {
try {
mCamera.setPreviewDisplay(mSurfaceHolder);
mCamera.startPreview();
setSafeToTakePhoto(true);
setCameraFocusReady(true);
} catch (IOException e) {
Log.d("st", "Can't start camera preview due to IOException " + e);
e.printStackTrace();
}
}
private void stopCameraPreview() {
setSafeToTakePhoto(false);
setCameraFocusReady(false);
// Nulls out callbacks, stops face detection
mCamera.stopPreview();
mPreviewView.setCamera(null);
}
maybe some implementations not equals yours but i think it is help you.
At first please excuse my bad English.
I have problem with programmatically taking photo. I wrote an app, that makes collection of photos based on countdown timer and after that, photos are being processed using c++ code.
I'm using dummy SurfaceView, because I don't need preview in UI. The code below is working on my phone Xperia mini - API 15 (so permissions and code would be correct), but I borrowed school Nexus 5 - API 21 and there is problem with preview.
takePicture: camera 0: Cannot take picture without preview enabled
I found a solution, which uses setPreviewTexture (commented below) instead of setPreviewDisplay. It working for the first photo, which is normally saved, but I get the same error after the second call of takePicture().
Thanks for every advice, LS
Camera camera;
#Override
protected void onResume() {
super.onResume();
// is camera on device?
if(!checkCameraHardware()) return;
releaseCamera();
try {
camera.stopPreview();
} catch (Exception e){
Log.d(TAG, "No preview before.");
}
SurfaceView dummy = new SurfaceView(this);
camera = Camera.open();
Camera.Parameters params = camera.getParameters();
params.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
camera.setParameters(params);
try {
//camera.setPreviewTexture(new SurfaceTexture(10));
camera.setPreviewDisplay(dummy.getHolder());
} catch (IOException e) {
e.printStackTrace();
}
camera.startPreview();
}
SOLUTION:
I needed to refresh preview. The code below is working on Xperie and Nexus too.
Question remains why I have to use setPreviewTexture, because setPreviewDisplay always returns error on Nexus.
camera.takePicture(null, null, new PictureCallback() {
#Override
public void onPictureTaken(final byte[] data, Camera camera) {
// save picture
refreshPreview();
}
});
public void refreshPreview() {
try {
camera.stopPreview();
} catch (Exception e) {}
try {
camera.startPreview();
} catch (Exception e) {}
}
and in function onResume()
try {
camera.setPreviewTexture(new SurfaceTexture(10));
} catch (IOException e) {}
Just add a callback for starting preview on your camera instance. The thing is that after starting preview on camera instance, it needs some time to be able take a picture. Try this:
camera.startPreview();
camera.setOneShotPreviewCallback(new Camera.PreviewCallback() {
#Override
public void onPreviewFrame(byte[] data, Camera camera) {
camera.takePicture(null, null, new Camera.PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
// do something you want with your picture and stop preview
camera.stopPreview();
}
});
Once the picture is taken, refresh you're surfaceview & stop the preview and releasee camera and restart the process again.
try {
camera.takePicture(null, null, new PictureCallback() {
public void onPictureTaken(final byte[] data, Camera camera) {
//once ur logic done
refreshCamera();
}
});
} catch (Exception e2) {
// Toast.makeText(getApplicationContext(), "Picture not taken", Toast.LENGTH_SHORT).show();
e2.printStackTrace();
}
public void refreshCamera() {
if (dummy.getHolder().getSurface() == null) {
return;
}
try {
camera.stopPreview();
} catch (Exception e) {
// ignore: tried to stop a non-existent preview
}
try {
camera.setPreviewDisplay(dummy.getHolder());
camera.startPreview();
} catch (Exception e) {
}
}
Hope this solution may help you.
I am working on an application which uses the camera to capture images. I am using callback methods for capture. It's working normally in all devices except "Huawei MediaPad 7inch",which has android 4.0.3. When i am launching my camera, after capturing image the camera freezes and OnPicturetaken method never called. In log cat I got the camera error "E/Camera(4562): Error -2147483648" Please help.
Here is my code.
public void takePicture() {
try {
Camera.PictureCallback mPictureCallbackRaw = new Camera.PictureCallback() {
public void onPictureTaken(byte[] data, Camera c) {
/** Do nothing */
}
};
Camera.ShutterCallback mShutterCallback = new Camera.ShutterCallback() {
public void onShutter() {
/** Do nothing */
}
};
mPreview.mCamera.takePicture(mShutterCallback, mPictureCallbackRaw, this);
} catch (Exception ex) {
NGAndroidUtil.logErr("[CameraPreview] takePicture exception", ex.getMessage(), ex);
}
}
I have built an application which takes photos when you touch the preview.
I can take many photos, but sometimes when i touch the preview to take a photo, there is no shutter sound and the whole application freezes. Moreover, after that, if i try to launch launch the built-in camera application, i get a message that the camera can't be used.
I don't know the reason for that behavior, it happens randomly and when it happens i must restart the device (Samsung Galaxy S) to be able to use the camera again.
In the DDM, after the crash i can see the following line: keyDispatchingTimedOut
Here is the relevant code:
CameraActivity Class:
public class CameraActivity extends Activity {
private static final String TAG = "CameraDemo";
Preview preview;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
preview = new Preview(this);
((FrameLayout) findViewById(R.id.preview)).addView(preview);
((FrameLayout) findViewById(R.id.preview)).setOnTouchListener(preview);
Log.d(TAG, "Camera Activity Created.");
}
}
Preview Class:
class Preview extends SurfaceView implements SurfaceHolder.Callback, OnTouchListener {
private static final String TAG = "Preview";
SurfaceHolder mHolder;
public Camera camera;
Context ctx;
boolean previewing = false;
Preview(Context context) {
super(context);
ctx = 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);
}
// Called once the holder is ready
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, acquire the camera and tell it where
// to draw.
camera = Camera.open();
}
// Called when the holder is destroyed
public void surfaceDestroyed(SurfaceHolder holder) {
if (camera != null) {
camera.setPreviewCallback(null);
camera.stopPreview();
camera.release();
camera = null;
}
previewing = false;
}
// Called when holder has changed
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
if(previewing){
camera.stopPreview();
previewing = false;
}
if (camera != null){
try {
camera.setDisplayOrientation(90);
camera.setPreviewDisplay(holder);
camera.setPreviewCallback(new PreviewCallback() {
// Called for each frame previewed
public void onPreviewFrame(byte[] data, Camera camera) {
Log.d(TAG, "onPreviewFrame called at: " + System.currentTimeMillis());
Preview.this.invalidate();
}
});
camera.startPreview();
previewing = true;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public boolean onTouch(View v, MotionEvent event) {
camera.takePicture(shutterCallback, rawCallback, jpegCallback);
return false;
}
// Called when shutter is opened
ShutterCallback shutterCallback = new ShutterCallback() {
public void onShutter() {
Log.d(TAG, "onShutter'd");
}
};
// Handles data for raw picture
PictureCallback rawCallback = new PictureCallback() {
public void onPictureTaken(byte[] data, Camera camera) {
Log.d(TAG, "onPictureTaken - raw");
}
};
// Handles data for jpeg picture
PictureCallback jpegCallback = new PictureCallback() {
public void onPictureTaken(byte[] data, Camera camera) {
FileOutputStream outStream = null;
try {
// Write to SD Card
outStream = new FileOutputStream(String.format("/sdcard/TVguide/Detection/detected.jpg", System.currentTimeMillis())); // <9>
outStream.write(data);
outStream.close();
Log.d(TAG, "onPictureTaken - wrote bytes: " + data.length);
} catch (FileNotFoundException e) { // <10>
//Toast.makeText(ctx, "Exception #2", Toast.LENGTH_LONG).show();
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {}
Log.d(TAG, "onPictureTaken - jpeg");
Toast.makeText(ctx, "SAVED", Toast.LENGTH_SHORT).show();
camera.startPreview();
}
};
}
Please help, i am trying a few days to understand where the problem is with no success
Eyal
I just run into this issue when testing my application on a Samsung Galaxy SII. You just have to remove the preview callback before taking the picture:
mCamera.setPreviewCallback(null);
mCamera.takePicture(null, null, mPictureCallback);
I don't know what causes that bug, it would really help if you posted the loggcat output from the time from when this error happened.
But, I can make some gusesses. It looks like camera is locked (built-in camera does not work). If your app force closed, the camera lock might be caused by erroneus error handling in Samsung camera HAL. Especially in older phones, like Galaxy S, they did not do the best job at handling wrong, or not standard API calls.
Here are some suggestions of what may have caused this behaviour:
You should add a guard for picture taking. Right now, if you touch the screen and take picture, you can touch the screen again, before the picture finishes taking. So, camera.takePicture() will be called twice. The second one will fail. This is my best guess.
Add some boolean isTakingPicture = false variable and then:
public boolean onTouch(View v, MotionEvent event) {
if (!isTakingPicture) {
camera.takePicture(shutterCallback, rawCallback, jpegCallback);
isTakingPicture = true;
}
return false;
}
...
public void onPictureTaken(byte[] data, Camera camera) {
isTakingPicture = false;
...
What do you use previewCallback for? I doesn't do anything useful here. Preview callbacks sometimes can sometimes cause some pain, although your code looks fine to me. You can alwys try to remove it and check if that helps.
I experienced a similar issue reported here. On LG p705 and Samsung Galaxy Trend, after taking a photo, the preview is frozen and camera was no longer usable until the phone was restarted. On Galaxy S3 however, the preview continues to display properly even after multiple photo snaps.
While debugging, I noticed that the relevant listener class was receiving more than one call when the camera button was pressed to take picture. I am unsure why it is being invoked twice, even though the button was only click once. In any case, thanks to Tomasz's suggestion to use of a boolean variable, the second call skips taking photo while the first attempt is in progress. And thanks Eyal for the question too. :)