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的主要内容,如果未能解决你的问题,请参考以下文章