I would like to request OpenTok does not deprecate the getCameraId/setCameraId functionality, but update it to accept strings in stead of integers, as the CameraManager returns camera ids in the form of strings.
After releasing this code I noticed some crashes. If you use this solution make sure you have the camera permission. Updated code:
val frontCameraIndex: Int = manager.cameraIdList.indexOfFirst { id: String ->
manager.getCameraCharacteristics(id)
.get(CameraCharacteristics.LENS_FACING) == CameraMetadata.LENS_FACING_FRONT
val backCameraIndex: Int = manager.cameraIdList.indexOfFirst { id: String ->
manager.getCameraCharacteristics(id)
.get(CameraCharacteristics.LENS_FACING) == CameraMetadata.LENS_FACING_BACK
buttonSwitchCam.setOnClickListener {
if (mPublisher?.cameraId == frontCameraIndex) {
if (backCameraIndex != -1) {
mPublisher?.cameraId = backCameraIndex
} else {
if (frontCameraIndex != -1) {
mPublisher?.cameraId = frontCameraIndex
This works better with the implementation of Publisher.getCameraId/setCameraId.
Any updates on this?
We started seeing this in Crashlytics after updating to the latest version (2.24.0).
The problem seems to be indeed caused by cycling the camera and it happened so far on the following devices (according to Crashlytics):
Xiaomi Mi 10 lite
Xiaomi Redmi Note 10 Pro
Samsung Galaxy S10e
Galaxy S20
Galaxy Tab S7 FE
It seems that the latest OpenTok versions don't really play well with devices that have multiple cameras. For example Huawei P30 is broken, but Pixel 4a is fine.
How to reproduce: Use a device with more than 2 cameras. Start a session with camera and then call swapCamera()
to switch to the back camera. Now end session. If you start another session again (without restarting the app process) then the camera view will be black.
This has been a bug for so long - we already had a workaround in the past where we would call swapCamera()
again to switch back to the front camera when you end the call. But on 2.24.0 this doesn't work because of the multiple camera support bug.
So basically we now use a similar code like posted above, we keep a list of front and back cameras IDs. And when you end the call we check if user.cameraId
is an ID from the list of back cameras. If yes then we use user.cameraId = frontCameraIndexes.first()
to switch to the front camera again. This fixes the bug when next sessions have a black camara view. But it's just a horrible hack and workaround around OpenTok issues.
Also - swapCamera()
will iterate over all cameras on the device. So on a Huwaei it will not switch between front and back, it will switch to back normal, back wide, back macro and then front. I think that OpenTok should only switch between the default back and front. You can use user.cameraId
to switch to a specific camera.
Hi, @v-kpheng I would appreciate if you have any status updates on this.
I work for a large organization that uses OpenTalk and we are suffering from the same issue after using the 2.24.0 version.
Thanks
@fpiresca, sorry for the lack of updates. The "someone" on the team with the Pixel 6 was me and I just came back from vacation.
Issue is still on our sprint. Will provide an update soon.
Fatal Exception: com.opentok.android.Camera2VideoCapturer$Camera2Exception: CAMERA_DISABLED (1): validateClientPermissionsLocked:1226: Caller "com.android.phoenix" (PID 10042, UID 25578) cannot open camera "0" from background (calling UID 10042 proc state 12).
can any body help
Just wanted to share an update. I couldn't reproduce on my Pixel 6. While doing cycleCamera
I noticed that only one of the rear cameras appeared. This is probably why I can't reproduce.
I asked my colleague to try to reproduce again on her Samsung Z Fold 4, which has three physical rear cameras.
Hello @v-kpheng According to our crash data, 90% of crashes are coming from samsung devices and 100% background. Could you please try to reproduce this from Samsung Note. this is critical issue for us. thanks
Fatal Exception: com.opentok.android.Camera2VideoCapturer$Camera2Exception: CAMERA_DISABLED (1): validateClientPermissionsLocked:1299/.../cannot open camera "1" from background
Thanks, @pc-anuruddha. We'll need to try to get our hands on a Samsung Note 🤞.
My colleague tried to reproduce again on her Samsung Z Fold 3 but couldn't, despite it having multiple rear cameras. This was her test method:
Use "cycleCamera" to iterate through cameras until a rear camera is displayed
Send app to background and back to foreground multiple times, to try to get it to crash
The app never crashed. She also tried to set it to a different rear camera, but no luck there either.
@v-kpheng Could there be a problem with a session restart? In our app an event can be sent to the signaling channel indicating the need to restart the session. In that case current session is ended, using session.disconnect(), and a new one is started. We don't call cycleCamera() anywhere in our code.
It's even worse in the latest library version. A new crash started popping up, on top of the old ones mentioned in this thread:
Fatal Exception: java.lang.IllegalStateException: Session has been closed; further changes are illegal.
at android.hardware.camera2.impl.CameraCaptureSessionImpl.checkNotClosed(CameraCaptureSessionImpl.java:834)
at android.hardware.camera2.impl.CameraCaptureSessionImpl.stopRepeating(CameraCaptureSessionImpl.java:402)
at com.opentok.android.Camera2VideoCapturer.stopCapture(:29)
at com.opentok.android.PublisherKit.d(:4)
at com.opentok.android.PublisherKit.$r8$lambda$6BMkMXi2EstSU_HgeV7ZQb4y6yA()
at com.opentok.android.PublisherKit$$ExternalSyntheticLambda14.run(:2)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7050)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:494)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:965)
@Roman-hub
I was able to get rid of this newest crash by making sure that we don't call session.onPause + session.onResume more than once in quick succession. Maybe add logging when you do this calls to see if you are not calling it several times. But - OpenTok should make sure we don't need to add workarounds and they should handle this internally.
Overall the newest version helped us to get rid of all the other workarounds we had in code to get OpenTok to work correctly. But we will see if we keep getting new crashes once we deploy this to production...
I dont know if my logs add any value but I am guessing they could help fix this issue so here goes:
Most affected device: Moto g pure
Most affected android version: 13
Place of crash : 95% background
com.opentok.android.Camera2VideoCapturer$Camera2Exception: CAMERA_DISABLED (1): validateClientPermissionsLocked:1560: Caller "com.varsitytutors.tutoringtools" (PID 10270, UID 12887) cannot open camera "1" from background (calling UID 10270 proc state 15)
com.opentok.android.Camera2VideoCapturer.initCamera(SourceFile:70)
com.opentok.android.Camera2VideoCapturer.$r8$lambda$EOJ6zJ_KyEal1aLQznxfTJOPcJc(SourceFile:15)
com.opentok.android.Camera2VideoCapturer.$r8$lambda$EOJ6zJ_KyEal1aLQznxfTJOPcJc(SourceFile:0)
com.opentok.android.Camera2VideoCapturer$$InternalSyntheticLambda$1$a584d3ebc8d132fd4b66cb4078f8bb1f3b20fd84f6152b5277de9aa5ac276da7$0.run(Camera2VideoCapturer.java:4)
com.opentok.android.Camera2VideoCapturer$4.onClosed(SourceFile:44)
android.hardware.camera2.impl.CameraDeviceImpl$5.run(CameraDeviceImpl.java:237)
android.os.Handler.handleCallback(Handler.java:942)
android.os.Handler.dispatchMessage(Handler.java:99)
android.os.Looper.loopOnce(Looper.java:226)
android.os.Looper.loop(Looper.java:313)
android.app.ActivityThread.main(ActivityThread.java:8757)
java.lang.reflect.Method.invoke(Method.java:0)
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571)
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1067)
This issue doesn't happen regularly, is difficult to replicate reliably, and in my opinion, is isolated to slower devices. I tested with the emulator, and was not seeing it occur, but when tested on a older, slower device it occurred once every 4 minutes of testing.
I was not able to reproduce this reliably, but one way was to call onResume
and onPause
on the session object in quick succession. This was my stack trace of the crash on a slow device:
Fatal Exception: com.opentok.android.Camera2VideoCapturer$Camera2Exception: CAMERA_IN_USE (4): connectHelper:1749: Higher-priority client using camera, ID "0" currently unavailable
at com.opentok.android.Camera2VideoCapturer.initCamera(Camera2VideoCapturer.java:79)
at com.opentok.android.Camera2VideoCapturer.startCapture(Camera2VideoCapturer.java:51)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:250)
at android.app.ActivityThread.main(ActivityThread.java:7851)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:958)
Device: Pixel 6 Android 13
Vonage SDK: 2.26
We see this occur when closing a previous session and creating a new close together. There seems to be no 'good' or recommended way to close a session other than nulling its reference and hoping that the garbage collector collects. That being said we are trying to use the life cycle methods to gracefully close the vonage session. Currently we are doing the following to close the old session before creating a new one:
If you run this code to close the previous sessions references x3-4 times you will run into the error i got.
session?.onPause()
patientPublisher?.onStop()
The main issue seems to be that vonage is attempting to remove something that does not exist.
The fact that I have to jump though so many hoops just to dispose and ensure vonage is not controlling the camera anymore is a bit crazy to me.
FATAL EXCEPTION: main
Process: com.transcarent.app, PID: 550
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.os.Handler.removeCallbacks(java.lang.Runnable)' on a null object reference
at com.opentok.android.Camera2VideoCapturer.stopDisplayOrientationCache(Unknown Source:4)
at com.opentok.android.Camera2VideoCapturer.destroy(Unknown Source:11)
at com.opentok.android.PublisherKit.a(Unknown Source:4)
at com.opentok.android.PublisherKit.z(Unknown Source:0)
at com.opentok.android.m0.run(Unknown Source:2)
at android.os.Handler.handleCallback(Handler.java:942)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:201)
at android.os.Looper.loop(Looper.java:288)
at android.app.ActivityThread.main(ActivityThread.java:7918)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)
It should be noted we have also tried to go directly to the capture of the publisher and stop that however stopping that results in a separate error.
Please give us a guaranteed way to COMPLETELY dispose of a session/publisher this is so frustrating.