Status Update
Comments
il...@google.com <il...@google.com> #2
Hi Doudera,
Thank you for reporting this issue. It is working as intended. This is because the state of CameraControl follows Camera. Once the Camera is closed, all settings will be restored, just like the settings of the focus area and zoom level. The app can restore the torch state by resetting torch at the time of activity onResume.
la...@gmail.com <la...@gmail.com> #3
thank you for the fast reply. The behaviour is unexpected to me because if you have the same code as before and just add logging like this:
camera = cameraProvider.bindToLifecycle(
this, cameraSelector, preview, imageCapture, imageAnalyzer)
.apply {
Log.d(TAG, "Enabling torch after binding") // <-- called everytime it returns to Activity so next statement should be applied
cameraControl.enableTorch(true)
}
The log is always called even when returning to Activity so I suppose it should be applied. Why it is not applied when it is called?
Unfortunately, I cannot make it work even with your hint. I tried to add camera?.cameraControl?.enableTorch(true) to onResume() but without any effect. Can you please describe more how to reset torch state onResume().
As you said the same happens with setZoomRatio() etc.
Thank you, Martin
il...@google.com <il...@google.com>
ap...@google.com <ap...@google.com> #4
Hi Doudera, Thank you for the detail description. It sounds like some problem in the code. I will investigate it more.
il...@google.com <il...@google.com> #5
From the log, it shows the camera state
-> open -> enable torch -> close -> open
The torch was gone because it restarted the camera.
It needs to investigate more about why it open/close so frequently.
an...@google.com <an...@google.com> #6
In CameraXBasic, it looks like the "cameraProvider.unbindAll()" call in CameraFragment.bindCameraUseCases() method will cause the camera close.
Since camera operation is in another thread, a timing causes the enableTorch() failed because the camera is in closed state at that moment.
It can be detected by checking the returned ListenableFuture result from cameraControl.enableTorch()
020-03-29 12:34:56.139 4946-4946/com.android.example.cameraxbasic E/CameraXBasic: enableTorch
2020-03-29 12:34:56.225 4946-5035/com.android.example.cameraxbasic D/Camera: Transitioning camera internal state: OPENED --> CLOSING
2020-03-29 12:34:56.226 4946-4946/com.android.example.cameraxbasic E/CameraXBasic: enableTorch fail by java.util.concurrent.ExecutionException: androidx.camera.core.CameraControl$OperationCanceledException: Camera is not active.
java.util.concurrent.ExecutionException: androidx.camera.core.CameraControl$OperationCanceledException: Camera is not active.
at androidx.concurrent.futures.AbstractResolvableFuture.getDoneValue(AbstractResolvableFuture.java:518)
at androidx.concurrent.futures.AbstractResolvableFuture.get(AbstractResolvableFuture.java:475)
at androidx.concurrent.futures.CallbackToFutureAdapter$SafeFuture.get(CallbackToFutureAdapter.java:199)
at com.android.example.cameraxbasic.fragments.CameraFragment$bindCameraUseCases$1$2$1.run(CameraFragment.kt:310)
at android.os.Handler.handleCallback(Handler.java:907)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:216)
at android.app.ActivityThread.main(ActivityThread.java:7476)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:549)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:968)
Caused by: androidx.camera.core.CameraControl$OperationCanceledException: Camera is not active.
at androidx.camera.camera2.internal.TorchControl.setActive(TorchControl.java:112)
at androidx.camera.camera2.internal.Camera2CameraControl.setActive(Camera2CameraControl.java:135)
at androidx.camera.camera2.internal.Camera2CameraImpl.tryRemoveOnlineUseCases(Camera2CameraImpl.java:727)
at androidx.camera.camera2.internal.Camera2CameraImpl.lambda$removeOnlineUseCase$13$Camera2CameraImpl(Camera2CameraImpl.java:699)
at androidx.camera.camera2.internal.-$$Lambda$Camera2CameraImpl$5wc8VkOCNW87m5eLEZfzgWUl-nY.run(Unknown Source:4)
at android.os.Handler.handleCallback(Handler.java:907)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:216)
at android.os.HandlerThread.run(HandlerThread.java:67)
It is a defect that CameraX should guarantee the order of the camera request.
Another topic is that why camera will be closed when resuming the CameraFragment.
CameraX is lifecycle aware, if UseCases is bound and pause/resume the page, CameraX will restart those UseCases automatically. So actually it doesn't have to unbind and rebind those UseCases. Unbind and rebind UseCases causes it open camera twice and meet this timing issue. In CameraXBasic, it will unbind and rebind UseCases in onViewCreated().
It is easier to be done in an Activity, just put the bindToLifecycle(...) code in the Activity.onCreate(). For Fragment, maybe Fragment.onAttach() is something like Activity.onCreate, but not pretty sure if it is practical. Or alternatively, it has to unbind all use case in a paired callback such like Fragment.onDestroyView() to prevent Camera from being automatically opened when resuming.
Description
Version used: 1.2.2
The UseRequireInsteadOfGet lint checks in androidx-fragment 1.2.2 can detect false positives. Consider the following Java code in a Fragment:
View view = getSomeCompletelyUnrelatedView();
Objects.requireNonNull(view);
results in the following lint error:
Error: Use requireView() instead of Objects.requireNonNull(view) [UseRequireInsteadOfGet]
which would be valid if view was the result of a getView() call but it isn't.
Workaround: Rename the view variable to some other name