18

I have a application which uses camera functionality in it but part of its functionality can also run without camera feature. SO I have put this in my manifest.

<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera"  android:required="false"/> 

and in my code I check whether the device has camera or not using this

final boolean deviceHasCameraFlag = pm.hasSystemFeature(PackageManager.FEATURE_CAMERA);

Now I am testing my code on a tablet which runs Android 4.0(ICS) and has no camera. But still I get True value for the deviceHasCameraFlag. Is this weird or am I missing something.

I tried different things and even tried the same thing on Bluetooth feature as Tablet even doesn't have Bluetooth feature. It works fine for Bluetooth but gives me true for camera.

Yogesh D
  • 1,663
  • 2
  • 23
  • 38

6 Answers6

10

Which device is it? The answer you get is a bug, and 4.0 is very old nowadays. Many tablets that still run this version were not crafted correctly, both hardware and software featuring multiple problems.

Regardless, you should always be prepared to handle failure on Camera.open() or Camera.open(0): for example, in some cases other software on your device will not release the camera gracefully.

So, in your case you have a false positive, you try to open the camera, it fails, and you continue as if there is no camera on the device, even if PackageManager thinks that PackageManager.FEATURE_CAMERA is availabe.

Alex Cohn
  • 56,089
  • 9
  • 113
  • 307
  • That's what I was thinking but was not sure to conclude that ...because the same call works for Bluetooth feature and same fails for Camera...So whats the solution here in such device bug case..? Should I leave the application as it is and it will crash on all such buggy devices or should I always check getNumberOfCameras and then proceed.>? – Yogesh D Mar 26 '14 at 06:07
  • I don't know what `getNumberOfCameras()` returns on this device. But I believe that `Camera.open()` will throw, so you should wrap this call with `catch (RuntimeException e) { deviceHasCameraFlag = false; }`. This means that you have to remove `final` from this flag. – Alex Cohn Mar 26 '14 at 06:15
9

Though I have accepted Alex's answer I still want to put this one collectively as what can be the best solution in such condition.

What I found was in case of some low standard android devices

pm.hasSystemFeature(PackageManager.FEATURE_CAMERA)

returns true even if camera doesn't exist and that seems to be a device bug for me which in unchecked.

So whenever there is scenario that you need to check if camera exists for a device or not best practice is something that I am putting below (best practice as per my knowledge if there is something more interesting and best solution that this you are welcome to put it here on this post)

int numberOfCameras = Camera.getNumberOfCameras();
context = this;
PackageManager pm = context.getPackageManager();
final boolean deviceHasCameraFlag = pm.hasSystemFeature(PackageManager.FEATURE_CAMERA);

if( !deviceHasCameraFlag || numberOfCameras==0 )
{
  Log.e(TAG, "Device has no camera" + numberOfCameras);
  Toast.makeText(getApplicationContext(), "Device has no camera",      Toast.LENGTH_SHORT).show();
  captureButton.setEnabled(false);
}
else
{
  Log.e(TAG, "Device has camera" + deviceHasCameraFlag + numberOfCameras);
}

In this I am checking both number of cameras as well as device has camera feature Boolean , so in any case it would not fail my condition.

Yogesh D
  • 1,663
  • 2
  • 23
  • 38
  • Do you open camera only on click of the captureButton? Even if you do so, I would suggest to **try {** `Camera.open()` once (if FEATURE_CAMERA and getNumberOfcameras() checks are positive), and if it throws, write a local file with flag that says "this device cannot capture". – Alex Cohn Aug 22 '14 at 05:26
  • What I am doing in my code is check if the device has camera or not when the application starts and if camera doesn't exists then disable the capture button for the user so that even if he presses that button nothing happens. So that it doesn't reach the `camera.open()` call. – Yogesh D Aug 22 '14 at 05:36
  • 2
    I would check rather for the following: if(deviceHasCameraFlag && numberOfCameras > 0) { //.... device has camera } else { //... no camera } – Tash Pemhiwa Aug 25 '14 at 13:01
  • @TashPemhiwa and any particular reason for that? cause I suppose it will be just the another way of doing the same way? – Yogesh D Aug 27 '14 at 04:05
  • 2
    @y.dixit Well, perhaps it's just a matter of preference, but I find it a lot easier to read. – Tash Pemhiwa Aug 27 '14 at 07:35
2

In my case I had this code:

public boolean hasCameraSupport() {
    boolean hasSupport = false;
    if(getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY)) { //<- this constant caused problems
        hasSupport = true;
    }
    return hasSupport;
}

and it kept returning false on a Genymotion device running Android 4.1.1 (API 16). Once I changed the constant PackageManager.FEATURE_CAMERA_ANY to PackageManager.FEATURE_CAMERA, my problems went away. I am guessing that not all devices/API levels support PackageManager.FEATURE_CAMERA_ANY.

Tash Pemhiwa
  • 7,590
  • 4
  • 45
  • 49
  • I appreciate your help on this ... but if you see my code I have used `PackageManager.FEATURE_CAMERA` and not `PackageManager.FEATURE_CAMERA_ANY`. – Yogesh D Aug 22 '14 at 04:03
  • @y.dixit Perhaps you should try `PackageManager.FEATURE_CAMERA_ANY` instead then? – Tash Pemhiwa Aug 22 '14 at 11:15
  • Yes I agree ...but even it works it won't guarantee that it will work for all devices as in your case it didn't work right? So what my point is we need something which will work on all the devices. I have posted my solution check that once and let me know if you agree to it.... – Yogesh D Aug 22 '14 at 12:49
  • @y.dixit Yes, it seems likes a solution that would work IMHO, with a slight edit. See my comment above – Tash Pemhiwa Aug 25 '14 at 13:00
  • FEATURE_CAMERA_ANY is API >= 17, that's maybe why it's returning wrong values on older devices (like the OP's one) – The Berga Dec 21 '16 at 17:48
0

I got it you will try this one definitely it will work....

   import android.hardware.Camera;
   int numCameras = Camera.getNumberOfCameras();
    if (numCameras > 0) {
      System.out.println("camera");
    } else {
        System.out.println("No Camera");
    }
Naveen Kumar Kuppan
  • 1,424
  • 1
  • 10
  • 12
  • So in my code I should just add `context.getPackageManager()` instead of `getPackageManager()` I will try that. But why does it work for bluetooth then as it is..? – Yogesh D Mar 26 '14 at 05:44
  • @kalyanpvs Then whats wrong with my code.....and should it be `Context` or `context` as there is no such `context` thing it prompts me to create local variable when I try to do `context.getPackageManager()` – Yogesh D Mar 26 '14 at 05:59
  • It is a Context instance or use like this getApplicationContext().getPackageManager(); – Naveen Kumar Kuppan Mar 26 '14 at 06:01
  • If you getting any error just post it,it may use to find the solution – Naveen Kumar Kuppan Mar 26 '14 at 06:13
  • @NaveenKumar that's what I am saying there is no error in the code....but `hasSystemFeature(PackageManager.FEATURE_CAMERA)` returns me true even when device has no camera. – Yogesh D Mar 26 '14 at 06:23
  • @NaveenKumar Please edit the answer and remove the first block of code and just keep the second one as it is relevant to the question here....I already did that code i my application and solved my problem but as you have also put that as answer I will accept that as answer for the benefit of the viewers once you remove the first block of code. thnx. – Yogesh D Mar 26 '14 at 06:57
0

For CameraX, if the FEATURE_CAMERA_ANY method is still returning true when there is no Camera on device, you can add the below method. So whether FEATURE_CAMERA_ANY returns true or false when CameraX is getting initialized, Below method will make sure to do what you want if a camera is actually not available on device.

private CameraSelector cameraSelector;
private ProcessCameraProvider cameraAvailableCheck;
private ListenableFuture<ProcessCameraProvider> cameraAvailableCheckFuture;

private void checkIfAnyCameraExist()
    {

        cameraAvailableCheckFuture = ProcessCameraProvider.getInstance(context);

        cameraAvailableCheckFuture.addListener(new Runnable() {
            @Override
            public void run() {
                try {
                    cameraAvailableCheck = cameraAvailableCheckFuture.get();

                    if ((cameraAvailableCheck.hasCamera(cameraSelector.DEFAULT_BACK_CAMERA) || cameraAvailableCheck.hasCamera(cameraSelector.DEFAULT_FRONT_CAMERA) ))
                    {
                        //Do what you want if at least back OR front camera exist

                    }

                    else
                    {
                        //Do what you want if any camera does not exist

                    }

                }

                catch (ExecutionException | InterruptedException | CameraInfoUnavailableException e)

                {
                    // No errors need to be handled for this Future.
                    // This should never be reached.
                }
            }

        }, ContextCompat.getMainExecutor(this));


    }
Rocky666
  • 91
  • 1
  • 5
-4

Please try this code:

private boolean isDeviceSupportCamera() {
    if (getApplicationContext().getPackageManager().hasSystemFeature(
            PackageManager.FEATURE_CAMERA)) {
        // this device has a camera
        return true;
    } else {
        // no camera on this device
        return false;
    }
}

Still it does't work then please let me know

Himanshu Agarwal
  • 4,623
  • 5
  • 35
  • 49