these days i was try to code a custom camera, but there's many bugs i can't figure out. the most serious error log as below.
at android.hardware.Camera.setHasPreviewCallback(Native Method)
at android.hardware.Camera.setPreviewCallback(Camera.java:600)
java.lang.RuntimeException: Method called after release()
at android.hardware.Camera.setHasPreviewCallback(Native Method)
at android.hardware.Camera.setPreviewCallback(Camera.java:600)
at com.baitian.wenta.customcamera.CameraActivity.cameraRelease(SourceFile:210)
at com.baitian.wenta.customcamera.CameraActivity.runExceptionHandle(SourceFile:526)
at com.baitian.wenta.customcamera.CameraActivity.updateFlashStatus(SourceFile:859)
at com.baitian.wenta.customcamera.CameraActivity.onResume(SourceFile:152)
at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1199)
at com.qihoo360.mobilesafe.loader.b.callActivityOnResume(SourceFile:123)
at android.app.Activity.performResume(Activity.java:5280)
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2629)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2667)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2140)
at android.app.ActivityThread.access$700(ActivityThread.java:140)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1237)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4921)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1038 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:805)
at dalvik.system.NativeStart.main(Native Method)
it seems the Method wouldn't called after release. i make the camera null everytime when i try to release it, and there is no multithread call.
here is the camera release code:
private void cameraRelease() {
try {
if (mCamera != null) {
mCamera.stopPreview();
mCamera.release();
mCameraExceptionLog.addLog("Camera release() After", "");
mCamera = null;
}
} catch (Throwable e) {
}
}
here is the camera init code
private void initCamera() {
try {
if (mCamera == null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
mCamera = Camera.open(0);
} else {
mCamera = Camera.open();
}
mCamera.setErrorCallback(new ErrorCallback() {
#Override
public void onError(int error, Camera camera) {
isCanAutoFouce = false;
CameraActivity.this.setResult(ERROR_KEY);
CameraActivity.this.finish();
}
});
setFocusAreaDefault();
}
} catch (Throwable e) {
runExceptionHandle(e);
}
}
Can you help me,thank you .
You need to add mCamera.setPreviewCallback(null) in between mCamera.stopPreview() and mCamera.release(). This way you cancel any callbacks coming.
I provided a complete cameraRelease method here
I see at least three possible problems with the log and posted code:
You might want to call mCamera.setPreviewCallback(null) after mCamera.stopPreview(); and before mCamera.release().
The log seems to refer to a Camera#setPreviewCallback() being called from the cameraRelease() method, which is not being shown on the posted code. Maybe the actual running code log was of an older version of the posted code.
It seems that you reach the cameraRelease() code from some sort of error handling. It might be the case that the error that happened to trigger the cameraRelease() code could have already released the camera because of some illegal state, hence any call inside this method, such as the mCamera.stopPreview() or mCamera.setPreviewCallback(null) calls would likely fail if the camera was already released at this point.
I had the similar issue. This line is the key line.
com.qihoo360.mobilesafe.loader.b.callActivityOnResume
From the log above, the camera permission is disabled by Qihoo 360 mobilesafe. After Camera.open(), although it return normally, the camera is released immediately. So you should check and catch the error after Camera.open().
try {
Camera camera = Camera.open();
if (camera != null) {
cmaera.getParamters(); // empty operation
}
} catch (Exception e) {
e.printStackTrack()
// oops, finish activity
}
As a third-party app, how Qihoo 360 mobilesafe can do like this? How it can perform permission management? This problem confuses me. Does it utilize unknown bug in system to do this?
Related
I am developing a webRTC app using opentok. The app was working fine. I converted the app to library and launching the library activity by adding it to another project. The app is connecting to server but camera not opening. I am getting camera error as follows
E/opentok-videocapturer: The camera is in use by another app
java.lang.RuntimeException: Fail to connect to camera service
at android.hardware.Camera.<init>(Camera.java:518)
at android.hardware.Camera.open(Camera.java:360)
at com.opentok.android.DefaultVideoCapturer.init(DefaultVideoCapturer.java:110)
at com.opentok.android.BaseVideoCapturer.initTrap(BaseVideoCapturer.java:223)
public boolean isCameraUsebyApp() {
Camera camera = null;
try {
camera = Camera.open();
}
catch (RuntimeException e)
{
return true;
}
finally
{
if (camera != null)
{
camera.release();
}
}
return false;
}
How to save the state of the camera so when i close the screen and turn it on again the camera gets back to its previous state.Should i bundle it?
public void getCamera() {
if (camera == null) {
try {
camera = Camera.open();
params = camera.getParameters();
} catch (RuntimeException e) {
Log.e(e.getMessage(), "Camera Error. Failed to Open. Error:Application will close! ");
finish();
}
}
}
Generally you don't want to do this- you want to release the camera in onPause and recapture it in onResume so other apps can use it as well.
I'm writing a program that accesses the camera. It worked for a while, but now it is the Camera API is throwing exceptions because the camera is still in use when I try to open it. I think this is because I am not handling it correctly in my onPause, onResume, and where I use it. Here is my code:
#Override
protected void onResume(){
if (!getPackageManager()
.hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
Toast.makeText(this, "No camera on this device", Toast.LENGTH_LONG)
.show();
} else {
cameraId = findFrontFacingCamera();
if (cameraId < 0) {
Toast.makeText(this, "No front facing camera found.",
Toast.LENGTH_LONG).show();
} else {
try {
if (camera != null) {
camera.release();
camera = null;
}
camera = Camera.open(cameraId);
try {
camera.setPreviewTexture(cameraTexture);
}
catch(IOException e){
Log.i("CameraHome", "could not set camera preview");
}
}
catch (Exception e){
}
}
}
super.onResume();}
Pause:
#Override
public void onPause(){
stopLocationUpdates();
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putLong("timeLeft", timeLeft);
editor.putBoolean("lockedOut", lockedOut);
editor.apply();
if (camera != null) {
camera.release();
camera = null;
}
super.onPause();
}
In use:
//Take picture
camera.startPreview();
camera.takePicture(null, null,
new PhotoHandler(getApplicationContext()));
camera.stopPreview();
camera.release();
Got any ideas what I'm doing wrong? Every time I relaunch the application, it throws an exception saying that the camera is in use, even if I launch the default camera app and close it.
EDIT: The camera is being accessed, but my callback (onPictureTaken in PhotoHandler) is never being called, as if the picture isn't being captured properly.
Turns out this code works. Had to uninstall, restart, and reinstall. Then my onPictureTaken callback wasn't being called. I believe this was because I was calling stopPreview too soon. I moved that to my onPause and took away the release call after the takePicture call. Works fine now
I wanted to make use of the zxing library to detect qrcodes in my app. But for the apps viewing purpose, i had to change the custom display orientation to portrait. Hence i had to integrate the whole zxing library into my app and addded camera.setDisplayOrientation(90) to the openDriver() method.
After doing this, the program works, but I get "Runtime exceptions : Fail to connect to camera service" randomly.
public void openDriver(SurfaceHolder holder) throws IOException {
if (camera == null) {
camera = Camera.open();
camera.setDisplayOrientation(90);
if (camera == null) {
throw new IOException();
}
}
camera.setPreviewDisplay(holder);
if (!initialized) {
initialized = true;
configManager.initFromCameraParameters(camera);
}
configManager.setDesiredCameraParameters(camera);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
reverseImage = prefs.getBoolean(PreferencesActivity.KEY_REVERSE_IMAGE, false);
if (prefs.getBoolean(PreferencesActivity.KEY_FRONT_LIGHT, false)) {
FlashlightManager.enableFlashlight();
}
}
public void closeDriver() {
if (camera != null) {
FlashlightManager.disableFlashlight();
camera.release();
camera = null;
framingRect = null;
framingRectInPreview = null;
}
}
/**
* Asks the camera hardware to begin drawing preview frames to the screen.
*/
public void startPreview() {
if (camera != null && !previewing) {
camera.startPreview();
previewing = true;
}
}
/**
* Tells the camera to stop drawing preview frames.
*/
public void stopPreview() {
if (camera != null && previewing) {
if (!useOneShotPreviewCallback) {
camera.setPreviewCallback(null);
}
camera.stopPreview();
previewCallback.setHandler(null, 0);
autoFocusCallback.setHandler(null, 0);
previewing = false;
}
}
I doubt that the orientation change is causing that. I have found you will get that error whenever an activity stops but fails to call Camera.release in their onPause. The result is that the next time you try to do Camera.open you get that runtime error since the driver still considers it open regardless of the app/activity that opened it being gone.
You can easily get this to happen while debugging/testing stuff when something throws an exception and brings the activity down. You need to be very diligent about catching all exceptions and being sure to release the camera before finishing the activity.
BTW, are you finding you need to power cycle the device in order to be able to open the camera again?
I have following code to play small audio files
private void playVoice() {
if (mPlayVoice != null) {
if (mPlayVoice.isPlaying()) {
mPlayVoice.release();
mPlayVoice = null;
}
}
mPlayVoice =
MediaPlayer.create(BirdsActivity.this, mSoundIds[getCurrentIndex()]);
mPlayVoice.start();
}
It works fine in Samsung galaxy tab but gives below error in small device(I Checked in Sony xperia mini pro my project)
08-17 12:45:45.232: ERROR/AndroidRuntime(6639): java.lang.IllegalStateException
08-17 12:45:45.232: ERROR/AndroidRuntime(6639): at android.media.MediaPlayer.isPlaying(Native Method)
08-17 12:45:45.232: ERROR/AndroidRuntime(6639): at com.android.mds.kidsapps.alphakids.BirdsActivity.playVoice(BirdsActivity.java:146)
You're doing this:
PlayVoice.release();
Do you not mean
mPlayVoice.release();
If you have other issues this is the best document to consult:
Android MediaPlayer
EDIT
Ok if you are here: isPlaying() Invalid States it show's you're trying to call isPlaying() while the player is in the error state. So you need to work out why it is already in the error state.
In general, some playback control operation may fail due to various reasons, such as unsupported audio/video format, poorly interleaved audio/video, resolution too high, streaming timeout, and the like.
Have a look at adding an error listener: setOnErrorListener()
Use the following code as i was facing the same exception.
try {
if(mPlayVoice!=null && mPlayVoice.isPlaying()) {
Log.d("TAG------->", "player is running");
mPlayVoice.stop();
Log.d("Tag------->", "player is stopped");
mPlayVoice.release();
Log.d("TAG------->", "player is released");
}
} catch(Exception e){
}
Here write whatever you want to do. Actually the condition checking like isPlaying() or checking for null generates the IllegalStateException.....
You may have to clear the audioGroup joined with audioStream. Mine worked with the following code:
public static void audioPlayCaptureStop()
{
try
{
if(audioStream.isBusy())
{
audioGroup.clear();
audioStream.release();
System.out.println("audioStream released");
}
} catch (Exception e) {
System.out.println("audioStream release exception: "+e.toString());
}
}