Android Question Detection of camera usage

freedom2000

Well-Known Member
Licensed User
HI all,

I would like to detect if the camera of the phone is in use (by another app) or free

I tried CamEx2 lib but it seems to "unlock" the camera and then to lock it again without saying anything (the other app in the background claims that it could no longer connect to the camera)

Do you know if there is an easy way to check if the camera is locked or not by another app ?
I had an old version of Camex2 and I saw into the log that a message was written "camera disconnected" when it was locked by the other app just before connecting to it.
This message does no longer exists with the latest version a camex2. (and I do not kept the old lib when upgrading...)
So there should probably be a trick to detect again this !

Thanks
JP
 

freedom2000

Well-Known Member
Licensed User
The "camera disconnected" message is still in Camera2 library code.

It also raises the CameraState event with Open = False.
Thank you for this answer.

Suprisingly the code (same code) has not the same behavior and this event does not raise.
I launched a connection to camera via an activity. I will try tonight via a service to see if it's better

BTW, what I try to do is to detect if the App IPWebcam has released or not the camera after a "no client connection" timeout. Just a way for me to detect if a client is connected or not.
 
Last edited:
Upvote 0

freedom2000

Well-Known Member
Licensed User
Finally I got it working using camera2 lib and removing most of camex2 class

here is the code to be put in a service :

B4X:
Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.

    Dim timer1 As Timer
    Dim cam As Camera2
End Sub

Sub Service_Create
    InitializeCamera
    timer1.Initialize("timer1", 5000)
    timer1.Enabled = True
End Sub

Sub Service_Start (StartingIntent As Intent)

End Sub
Private Sub InitializeCamera
    cam.Initialize("cam")
    'Remote.TimerConnect.Enabled = False
End Sub
Sub Service_Destroy
    timer1.Enabled = False
End Sub

Sub timer1_Tick
    OpenCamera (True)
End Sub

Public Sub OpenCamera (Front As Boolean) As ResumableSub
 
    If cam.IsCameraOpen Then
        Log("camera already opened")
        cam.Stop 'Stop camera
    End If
    Dim id As String
    id = cam.FindCameraId(True)
    If id = "" Then
        Log("Camera not found.")
        id = cam.CameraIDs(0)
    End If
    Try
        cam.OpenCamera(id)
    Catch
        Log("Failed to open camera")
        Return False
    End Try
    Wait For Cam_CameraState (Open As Boolean)
    If Open = False Then
        Log("Failed to open camera")
        Return False
    Else
        Log ("Open Camera Ok")
        cam.Stop
        Return True
    End If
 
End Sub

Something strange, I have been obliged to trap the exception caused by OpenCamera
if not I never detect the cameara in use, but get this exception...

B4X:
Error occurred on line: 48 (CheckCam)
android.hardware.camera2.CameraAccessException: CAMERA_IN_USE (4): connectHelper:979: Higher-priority client using camera, ID "1" currently unavailable
    at android.hardware.camera2.CameraManager.throwAsPublicException(CameraManager.java:634)
    at android.hardware.camera2.CameraManager.openCameraDeviceUserAsync(CameraManager.java:343)
    at android.hardware.camera2.CameraManager.openCamera(CameraManager.java:450)
    at anywheresoftware.b4a.objects.Camera2.OpenCamera(Camera2.java:110)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.shell.Shell.runVoidMethod(Shell.java:755)
    at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:345)
    at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:249)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:139)
    at anywheresoftware.b4a.debug.Debug.delegate(Debug.java:259)
    at b4a.example.checkcam$ResumableSub_OpenCamera.resume(checkcam.java:164)
    at b4a.example.checkcam._opencamera(checkcam.java:148)
    at b4a.example.checkcam._timer1_tick(checkcam.java:387)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:710)
    at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:342)
    at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:249)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:139)
    at anywheresoftware.b4a.objects.Timer$TickTack.run(Timer.java:105)
    at android.os.Handler.handleCallback(Handler.java:751)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at android.os.Looper.loop(Looper.java:154)
    at android.app.ActivityThread.main(ActivityThread.java:6692)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1468)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1358)
Caused by: android.os.ServiceSpecificException: connectHelper:979: Higher-priority client using camera, ID "1" currently unavailable
    at android.os.Parcel.readException(Parcel.java:1707)
    at android.os.Parcel.readException(Parcel.java:1646)
    at android.hardware.ICameraService$Stub$Proxy.connectDevice(ICameraService.java:324)
    at android.hardware.camera2.CameraManager.openCameraDeviceUserAsync(CameraManager.java:319)
    ... 26 more
Failed to open camera

but as it is it works and detects if the camera is in use or not !
 
Upvote 0

freedom2000

Well-Known Member
Licensed User
trophy.jpg
Thanks to @jordi and @Johan Schoeman I got a new Throphy :cool:

Thank you guys !
 
Upvote 0

freedom2000

Well-Known Member
Licensed User
Ok let's summarize :

I can launch IPWebCam with an intent
I can monitor if a client is connectied or not with the above code

Now I would like to stop the Webcam server as I don't want to have to webcam opened all the time...

I asked to the developper (Pavel -thanks to him-) and he replied this :
Alternatively, use a command line: you can start IP Webcam using
  • am broadcast -a com.pas.webcam.CONTROL -e action start
And stop it like this:
  • am broadcast -a com.pas.webcam.CONTROL -e action stop
So I installed Terminal emulator on the phone and tried to launch the IPWebcam with the command line.

Here is what I got :
broadcast -a com.pas.webcam.CONTROL -e action start <
Broadcasting: Intent { act=com.pas.webcam.CONTROL launchParam=MultiScreenLaunchParams { mDisplayId=0 mFlags=0 } (has extras) }
java.lang.SecurityException: Permission Denial: broadcast asks to run as user -2 but is calling from user 0; this requires android.permission.INTERACT_ACROSS_USERS_FULL or android.permission.INTERACT_ACROSS_USERS
at android.os.Parcel.readException(Parcel.java:1693) at android.os.Parcel.readException(Parcel.java:1646) at android.app.ActivityManagerProxy.broadcastIntent(ActivityManagerNative.java:4012)
at com.android.commands.am.Am.sendBroadcast(Am.java:800)
at com.android.commands.am.Am.onRun(Am.java:408)
at com.android.internal.os.BaseCommand.run(BaseCommand.java:51)
at com.android.commands.am.Am.main(Am.java:125)
at com.android.internal.os.RuntimeInit.nativeFinishInit(Native Method)
at com.android.internal.os.RuntimeInit.main(RuntimeInit.java:301)

So obviously a security problem...

Any idea how to send this on line command without being rooted and from my App ?

Thanks to gurus
 
Last edited:
Upvote 0

freedom2000

Well-Known Member
Licensed User
Oups another question...

I was almost there, everything was running, I could check if the camera was in use or not from a service...

And I tried to install the App on my old HTC One MIni 2... and it failed as this phone does not support Android 5 needed for camera2 library...

So i decided to go back to the old camEx lib.
But I can't find a way to have the same camera.OpenCamera(id) function.
All what I find need a "panel" to work ; making it impossible to run into a service.

Any idea to detect if a camera is in use with camEx lib/Class ?

It seems from the documentation that Open should work :
https://developer.android.com/reference/android/hardware/Camera.html?hl=fr#open(int)

But how to call it with B4A ?

Thank you
 
Last edited:
Upvote 0

freedom2000

Well-Known Member
Licensed User
Camera (1) is an activity object. You will not be able to use it from a service.

Open is called inside when you initialize the camera. It raises the Ready event.
Thank you to confirm that camera(1) is an activity object.

But I thought that there could be a way to use Open method into a service. The documentation is not clear about that...
 
Upvote 0

freedom2000

Well-Known Member
Licensed User
Thanks to @Johan Schoeman excellent post, there is a way to open camera into a service with the old camera class.

I have only changed the inline code like this :

B4X:
#If JAVA

import android.hardware.Camera;

import java.util.List;
    Camera mCamera;
 
    public void OpenCam() {            
      mCamera = Camera.open(1);
    }
   
     public void ReleaseCam() {
        mCamera.release();
     }
#End If
 
Upvote 0
Top