hasSystemFeature(PackageManager.FEATURE_CAMERA) 为没有摄像头的设备返回 true

Posted

技术标签:

【中文标题】hasSystemFeature(PackageManager.FEATURE_CAMERA) 为没有摄像头的设备返回 true【英文标题】:hasSystemFeature(PackageManager.FEATURE_CAMERA) returns true for device with no camera 【发布时间】: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 权限。您的问题帮助很大! 【参考方案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;

以上是关于hasSystemFeature(PackageManager.FEATURE_CAMERA) 为没有摄像头的设备返回 true的主要内容,如果未能解决你的问题,请参考以下文章

检测安卓设备是不是具有移动数据功能

找不到类 flex

如何打开安卓设备的前置手电筒(不是后置手电筒)

golang反射

Go 接口

时间日期转换+两个日期相减