CameraView restricts access to flash
mksdevelop opened this issue · comments
Description
Hello.
My application uses a flash to blink at a certain frequency. For example, I need to blink at a frequency of 1, 2, 10, 20, 30, 40 Hz in turn, and there may also be a pause between blinks.
In some cases, you also need to shoot a video.
If while recording a video, I try to use the flash, then I get an exception
Android.Hardware.Camera2.CameraAccessException CAMERA_IN_USE (4): setTorchMode:2125: Torch for camera "0" is not available due to an existing camera user
I can't use flash if I'm using a camera.
I understand that this may be a limitation of the system, but the CameraView component does not have the required functionality to enable flash.
Stack Trace
at Java.Interop.JniEnvironment+InstanceMethods.CallVoidMethod (Java.Interop.JniObjectReference instance, Java.Interop.JniMethodInfo method, Java.Interop.JniArgumentValue* args) [0x00068] in /Users/runner/work/1/s/xamarin-android/external/Java.Interop/src/Java.Interop/obj/Release/JniEnvironment.g.cs:11884
at Java.Interop.JniPeerMembers+JniInstanceMethods.InvokeAbstractVoidMethod (System.String encodedMember, Java.Interop.IJavaPeerable self, Java.Interop.JniArgumentValue* parameters) [0x0001a] in /Users/runner/work/1/s/xamarin-android/external/Java.Interop/src/Java.Interop/Java.Interop/JniPeerMembers.JniInstanceMethods_Invoke.cs:47
at Android.Hardware.Camera2.CameraManager.SetTorchMode (System.String cameraId, System.Boolean enabled) [0x00032] in /Users/runner/work/1/s/xamarin-android/src/Mono.Android/obj/Release/monoandroid10/android-33/mcw/Android.Hardware.Camera2.CameraManager.cs:689
at AppName.Droid.Services.FlashlightService.TurnOff () [0x00010] in /Users/dev/Develop/Projects/AppName/AppName.Android/Services/FlashlightService.cs:54
at AppName.Services.Flashlight.Stroboscope.Stop () [0x0003a] in /Users/dev/Develop/Projects/AppName/AppName/Services/Flashlight/Stroboscope.cs:46
at AppName.Services.Flashlight.Stroboscope.Start (System.Int32 frequency) [0x00001] in /Users/dev/Develop/Projects/AppName/AppName/Services/Flashlight/Stroboscope.cs:25
at AppName.Domain.Models.NeoRec.Stages.PhotoStimulationStage.Init (AppName.Domain.Models.NeoRec.Record record) [0x00070] in /Users/dev/Develop/Projects/AppName/AppName/Domain/Models/NeoRec/Stages/PhotoStimulationStage.cs:44
at AppName.Services.Exam.ExaminationService.GetNextStage () [0x00049] in /Users/dev/Develop/Projects/AppName/AppName/Services/Exam/ExaminationService.cs:124
at AppName.Services.Exam.ExaminationService.SkipStage () [0x00014] in /Users/dev/Develop/Projects/AppName/AppName/Services/Exam/ExaminationService.cs:106
at AppName.UI.ViewModels.NeoRecExaminationViewModel.<get_StageSkipCommand>b__74_0 () [0x00015] in /Users/dev/Develop/Projects/AppName/AppName/UI/ViewModels/NeoRecExaminationViewModel.cs:265
at Xamarin.CommunityToolkit.ObjectModel.Internals.BaseAsyncCommand2[TExecute,TCanExecute].ExecuteAsync (TExecute parameter) [0x00093] in <6243432aa10f4b63ae8efc1ac5c0cfbc>:0 at Xamarin.CommunityToolkit.Helpers.SafeFireAndForgetExtensions.HandleSafeFireAndForget[TException] (System.Threading.Tasks.Task task, System.Boolean continueOnCapturedContext, System.Action
1[T] onException) [0x0006f] in <6243432aa10f4b63ae8efc1ac5c0cfbc>:0
at System.Runtime.CompilerServices.AsyncMethodBuilderCore+<>c.b__7_0 (System.Object state) [0x00000] in /Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/company/class/referencesource/mscorlib/system/runtime/compilerservices/AsyncMethodBuilder.cs:1021
at Android.App.SyncContext+<>c__DisplayClass2_0.b__0 () [0x00000] in /Users/runner/work/1/s/xamarin-android/src/Mono.Android/Android.App/SyncContext.cs:36
at Java.Lang.Thread+RunnableImplementor.Run () [0x00008] in /Users/runner/work/1/s/xamarin-android/src/Mono.Android/Java.Lang/Thread.cs:36
at Java.Lang.IRunnableInvoker.n_Run (System.IntPtr jnienv, System.IntPtr native__this) [0x00008] in /Users/runner/work/1/s/xamarin-android/src/Mono.Android/obj/Release/monoandroid10/android-33/mcw/Java.Lang.IRunnable.cs:84
at Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PP_V (_JniMarshal_PP_V callback, System.IntPtr jnienv, System.IntPtr klazz) [0x00005] in /Users/runner/work/1/s/xamarin-android/src/Mono.Android/Android.Runtime/JNINativeWrapper.g.cs:22
at (wrapper native-to-managed) Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PP_V(intptr,intptr)
--- End of managed Android.Hardware.Camera2.CameraAccessException stack trace ---
android.hardware.camera2.CameraAccessException: CAMERA_IN_USE (4): setTorchMode:2125: Torch for camera "0" is not available due to an existing camera user
at android.hardware.camera2.CameraManager.throwAsPublicException(CameraManager.java:1209)
at android.hardware.camera2.CameraManager$CameraManagerGlobal.setTorchMode(CameraManager.java:1756)
at android.hardware.camera2.CameraManager.setTorchMode(CameraManager.java:942)
at crc64ee486da937c010f4.ButtonRenderer.n_onClick(Native Method)
at crc64ee486da937c010f4.ButtonRenderer.onClick(ButtonRenderer.java:107)
at android.view.View.performClick(View.java:7460)
at android.view.View.performClickInternal(View.java:7433)
at android.view.View.access$3700(View.java:840)
at android.view.View$PerformClick.run(View.java:28894)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.L
Steps to Reproduce
- Create page with CameraView
- Try turning on the flashlight from the service (see below FlashlightService.TurnOff())
- App crushing
Expected Behavior
App not crushing
Actual Behavior
App crushing
Basic Information
- Version with issue: 8.2.1
- Last known good version: -
- IDE: Visual Studio for Mac
- Platform Target Frameworks:
- Android: 13
- Android Support Library Version: 28.0.03
- Nuget Packages:
- Affected Devices:
[assembly: Dependency(typeof(FlashlightService))]
namespace AppName.Droid.Services
{
internal class FlashlightService : IFlashlightService
{
private readonly CameraManager _cameraManager;
private readonly string _flashCameraId;
private int _maxTorchLevel;
public bool IsFlashAvailable { get; }
public bool IsTorchLevelAvailable { get; private set; }
public float TorchLevel { get; set; } = 1f;
public FlashlightService()
{
_cameraManager = (CameraManager)Platform.AppContext.GetSystemService(Context.CameraService);
foreach (var id in _cameraManager.GetCameraIdList())
{
var hasFlash = _cameraManager.GetCameraCharacteristics(id).Get(CameraCharacteristics.FlashInfoAvailable);
IsFlashAvailable = Java.Lang.Boolean.True.Equals(hasFlash);
if (Java.Lang.Boolean.True.Equals(hasFlash))
{
_flashCameraId = id;
FindMaxTorchLevel(_flashCameraId);
return;
}
}
}
public void TurnOn()
{
if (!IsFlashAvailable)
return;
if (IsTorchLevelAvailable)
_cameraManager.TurnOnTorchWithStrengthLevel(_flashCameraId, GetCurrentTorchLevel());
else
_cameraManager.SetTorchMode(_flashCameraId, true);
}
public void TurnOff()
{
if (!IsFlashAvailable)
return;
_cameraManager.SetTorchMode(_flashCameraId, false);
}
private int GetCurrentTorchLevel()
{
var min = 1;
var max = _maxTorchLevel;
return (int)((max - min) * TorchLevel) + min;
}
private void FindMaxTorchLevel(string cameraId)
{
var characteristics = _cameraManager.GetCameraCharacteristics(cameraId);
try
{
IsTorchLevelAvailable = characteristics.Keys.Contains(CameraCharacteristics.FlashInfoStrengthMaximumLevel);
}
catch { /*when no find characteristic*/ }
if (!IsTorchLevelAvailable)
return;
_maxTorchLevel = (int)_cameraManager.GetCameraCharacteristics(_flashCameraId).Get(CameraCharacteristics.FlashInfoStrengthMaximumLevel);
}
}
}