【问题标题】:hasSystemFeature(PackageManager.FEATURE_CAMERA) returns true for device with no camerahasSystemFeature(PackageManager.FEATURE_CAMERA) 为没有摄像头的设备返回 true
【发布时间】:2014-05-04 08:02:52
【问题描述】:

我有一个使用相机功能的应用程序,但它的部分功能也可以在没有相机功能的情况下运行。所以我把它放在我的清单中。

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

在我的代码中,我使用它检查设备是否有摄像头

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

现在我正在运行 Android 4.0(ICS) 且没有摄像头的平板电脑上测试我的代码。但我仍然得到deviceHasCameraFlag 的真实价值。这很奇怪还是我错过了什么。

我尝试了不同的东西,甚至在蓝牙功能上尝试了相同的东西,因为平板电脑甚至没有蓝牙功能。它适用于蓝牙,但适用于相机。

【问题讨论】:

  • Check if device has a camera? 的可能副本。请查看投票最高的答案:如果设备有前置/后置/双摄像头,它将返回true
  • 是的设备没有一个摄像头......这就是为什么我期望那里有一个错误的值......
  • 我发布了一个代码,它可以正常工作
  • @y.dixit 你会在我的新代码下面试试这个并告诉我......
  • 我一整天都被困在这个问题上,除了 PHONE_STATE 权限。您的问题帮助很大!

标签: android android-camera android-package-managers


【解决方案1】:

对于 CameraX,如果 FEATURE_CAMERA_ANY 方法在设备上没有 Camera 时仍然返回 true,您可以添加以下方法。因此,无论 FEATURE_CAMERA_ANY 在 CameraX 初始化时返回 true 还是 false,如果设备上实际上没有摄像头,下面的方法将确保执行您想要的操作。

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));


    }

【讨论】:

    【解决方案2】:

    虽然我已经接受了亚历克斯的回答,但我仍然想把这个放在一起,作为在这种情况下最好的解决方案。

    我发现的是一些低标准的安卓设备

    pm.hasSystemFeature(PackageManager.FEATURE_CAMERA)
    

    即使相机不存在也返回 true,这对我来说似乎是一个未选中的设备错误。

    因此,每当出现需要检查设备是否存在相机的情况时,我将在下面提出最佳实践(根据我的知识,如果有更有趣和最佳的解决方案,则为最佳实践)欢迎把它放在这个帖子上)

    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);
    }
    

    在此我正在检查摄像头的数量以及设备是否具有摄像头功能 Boolean ,因此无论如何它都不会满足我的条件。

    【讨论】:

    • 您是否仅在单击 captureButton 时打开相机?即使您这样做,我也建议您尝试 { Camera.open() 一次(如果 FEATURE_CAMERA 和 getNumberOfcameras() 检查是肯定的),如果它抛出,写一个带有标志的本地文件,上面写着“这设备无法捕获”。
    • 我在代码中所做的是在应用程序启动时检查设备是否有摄像头,如果摄像头不存在,则为用户禁用捕获按钮,这样即使他按下了按钮没有任何反应。这样它就不会到达camera.open() 调用。
    • 我宁愿检查以下内容: if(deviceHasCameraFlag && numberOfCameras > 0) { //.... 设备有摄像头 } else { //... 没有摄像头 }
    • @TashPemhiwa 有什么特别的原因吗?因为我想这只是做同样方式的另一种方式?
    • @y.dixit 好吧,也许这只是一个偏好问题,但我发现它更容易阅读。
    【解决方案3】:

    就我而言,我有这个代码:

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

    它在运行 Android 4.1.1 (API 16) 的 Genymotion 设备上一直返回 false。一旦我将常量PackageManager.FEATURE_CAMERA_ANY 更改为PackageManager.FEATURE_CAMERA,我的问题就消失了。我猜不是所有的设备/API 级别都支持PackageManager.FEATURE_CAMERA_ANY

    【讨论】:

    • 感谢您对此提供的帮助...但如果您看到我的代码,我使用的是 PackageManager.FEATURE_CAMERA 而不是 PackageManager.FEATURE_CAMERA_ANY
    • @y.dixit 或许你应该试试PackageManager.FEATURE_CAMERA_ANY
    • 是的,我同意......但即使它有效,它也不能保证它适用于所有设备,因为在你的情况下它不能正常工作?所以我的意思是我们需要一些可以在所有设备上运行的东西。我已经发布了我的解决方案检查一次,如果您同意,请告诉我....
    • @y.dixit 是的,恕我直言,这似乎是一个可行的解决方案,只需稍作修改。见我上面的评论
    • FEATURE_CAMERA_ANY 是 API >= 17,这可能是它在旧设备(如 OP 的设备)上返回错误值的原因
    【解决方案4】:

    我知道了,你会试试这个,肯定会奏效....

       import android.hardware.Camera;
       int numCameras = Camera.getNumberOfCameras();
        if (numCameras > 0) {
          System.out.println("camera");
        } else {
            System.out.println("No Camera");
        }
    

    【讨论】:

    • 所以在我的代码中我应该只添加context.getPackageManager() 而不是getPackageManager() 我会试试的。但是为什么它对蓝牙有效呢..?
    • @kalyanpvs 那么我的代码有什么问题.....应该是Context 还是context 因为没有context 这样的东西,它提示我在我创建局部变量时尝试做context.getPackageManager()
    • 它是一个Context实例或者像这样使用getApplicationContext().getPackageManager();
    • 如果你有任何错误,只需发布​​它,它可以用来找到解决方案
    • @NaveenKumar 这就是我所说的代码中没有错误......但是即使设备没有摄像头,hasSystemFeature(PackageManager.FEATURE_CAMERA) 也会返回 true。
    【解决方案5】:

    它是什么设备?你得到的答案是一个错误,现在 4.0 已经很老了。许多仍运行此版本的平板电脑设计不正确,硬件和软件都存在多个问题。

    无论如何,您应该随时准备处理Camera.open()Camera.open(0) 上的故障:例如,在某些情况下,您设备上的其他软件不会正常释放相机。

    因此,在您的情况下,您有误报,您尝试打开摄像头,但它失败了,并且您继续,就好像设备上没有摄像头一样,即使 PackageManager 认为 PackageManager strong>PackageManager.FEATURE_CAMERA 可用。

    【讨论】:

    • 这就是我的想法,但不确定是否得出结论......因为相同的调用适用于蓝牙功能,而相机同样失败......那么在这种设备错误情况下,这里的解决方案是什么。 .?我应该让应用程序保持原样,它会在所有这些有问题的设备上崩溃,还是应该总是检查 getNumberOfCameras 然后继续。>?
    • 我不知道getNumberOfCameras() 在此设备上返回什么。但我相信Camera.open() 会抛出,所以你应该用catch (RuntimeException e) { deviceHasCameraFlag = false; } 包装这个调用。这意味着您必须从此标志中删除 final
    【解决方案6】:

    请试试这个代码:

    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;
        }
    }
    

    还是不行,请告诉我

    【讨论】:

    • 你用这个方法试过了吗,它仍然返回true吗?
    • if (FOO) return true; else return false; 实在是太多余了……就做return FOO;
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多