I'm trying to reimplement Redlaser barcode Scanner using Google play services. And face to the problem with flashlight. Android hardware.Camera object can't be using in common with CameraSource from gms.vision.
Is there any opportunity to working with flashlight and Google barcode scanner?
Not sure I fully get what you're asking but my approach to this was to use the already created mCamerSource Object and setFlashMode() from there, this worked for me as I used a button to toggle the flash.
In your onCreate add this or in createCameraSource method just like in the samples ->
mCameraSource = builder
.setFlashMode(useFlash ? Camera.Parameters.FLASH_MODE_TORCH : null)
.build();
Then Make a method to toggle the flash, hope this helps.
private void ToggleFlash()
{
fab_flash.startAnimation(spin_it);
if(currentDrawalbe == FLASH_DEFAULT_STATE)
{
fab_flash.setImageResource(FLASH_TOGGLE_STATE);
currentDrawalbe = FLASH_TOGGLE_STATE;
mCameraSource.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
}
else
{
fab_flash.setImageResource(FLASH_DEFAULT_STATE);
currentDrawalbe = FLASH_DEFAULT_STATE;
mCameraSource.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
}
}
The currentDrawable is just an image for the flash light icon, so basically if the image is a turned on flash light executes else clause otherwise if clause
The issue was that the camera API does not support opening the camera multiple times. Turning on the flashlight and starting CameraSource both require separate calls to open the camera. If you try to do both, the one that is requested last will fail.
The good news is that we recently open sourced the CameraSource implementation. This new version includes an option for turning on the flashlight, which should fix this issue. See here:
https://github.com/googlesamples/android-vision/blob/master/visionSamples/barcode-reader/app/src/main/java/com/google/android/gms/samples/vision/barcodereader/ui/camera/CameraSource.java
Currently I'm using this code to find camera object:
private boolean findCameraObject(){
if(mCameraSource == null) {
return false;
}
Field[] declaredFields = null;
try {
declaredFields = CameraSource.class.getDeclaredFields();
} catch (Exception ex) {
ex.printStackTrace();
}
if(declaredFields == null) {
return false;
}
for (Field field : declaredFields) {
if (field.getType() == Camera.class) {
field.setAccessible(true);
try {
Camera camera = (Camera) field.get(this.mCameraSource);
if (camera != null) {
Camera.Parameters params = camera.getParameters();
params.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
camera.setParameters(params);
setCamera(camera);
return true;
}
return false;
} catch (IllegalAccessException e) {
e.printStackTrace();
}
break;
}
}
return false;
}
I am using this code and it is working successfully
Replace : cameraSource.start(surfaceView.getHolder()); OR cameraSource.start(); TO setFlash ();
BY
import java.lang.reflect.Field;
import android.hardware.Camera;
Don't Forgot AndroidManifest:
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<permission android:name="android.permission.FLASHLIGHT"
android:permissionGroup="android.permission-group.HARDWARE_CONTROLS"
android:protectionLevel="normal"/>
Then ADD this methods
public static Camera getCamera(CameraSource cameraSource) {
Field[] declaredFields = CameraSource.class.getDeclaredFields();
for (Field field : declaredFields) {
if (field.getType() == Camera.class) {
field.setAccessible(true);
try {
Camera camera = (Camera) field.get(cameraSource);
if (camera != null) {
return camera;
}
return null;
} catch (IllegalAccessException e) {
e.printStackTrace();
}
break;
}
}
return null;
}
public void setFlash () throws IOException {
getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH);
cameraSource.start(surfaceView.getHolder());
Camera _cam = getCamera (cameraSource);
if (_cam != null) {
Camera.Parameters _pareMeters = _cam.getParameters();
_pareMeters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
_cam.setParameters(_pareMeters);
_cam.startPreview();
}
}
Add permossion on AndroidManifest file
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<permission android:name="android.permission.FLASHLIGHT"
android:permissionGroup="android.permission-group.HARDWARE_CONTROLS"
android:protectionLevel="normal"/>
Turn on torch on Android, using Kotlin.
cameraProvider.bindToLifecycle((LifecycleOwner)this,
cameraSelector, imageAnalysis, preview);
Get Camera for cameraProvider..
camera = cameraProvider!!.bindToLifecycle(
(this as LifecycleOwner),
cameraSelector!!, Preview
)
to turn on/off the FlashLight
private fun navigateflash(isFlash : Boolean) {
try {
if(camera!= null && camera!!.cameraInfo.hasFlashUnit()){
if(isFlash){
camera!!.cameraControl.enableTorch(false); // or false
isFlashOn = false
}else{
camera!!.getCameraControl().enableTorch(true); // or false
isFlashOn = true
}
}
} catch (e: Exception) {
e.printStackTrace()
}
}
Related
I am developing a flashlight app that switch on/off the system tourch.
I have a crash that shown on Android M (v6.0) on
Crashlytics
Here is the Issue details and stacktrace:
Fatal Exception: java.lang.IllegalArgumentException: Receiver not registered: android.hardware.camera2.CameraManager$1#49e5f1b
at android.app.LoadedApk.forgetReceiverDispatcher(LoadedApk.java:789)
at android.app.ContextImpl.unregisterReceiver(ContextImpl.java:1222)
at android.hardware.camera2.CameraManager$3.run(CameraManager.java:1266)
at android.os.Handler.handleCallback(Handler.java:815)
at android.os.Handler.dispatchMessage(Handler.java:104)
at android.os.Looper.loop(Looper.java:207)
at android.app.ActivityThread.main(ActivityThread.java:5728)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:789)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:679)
I have the following Manifest permissions and hardware features:
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.flash" />
and
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.FLASHLIGHT" />
****EDIT:****
Here is the code I am using to access the camera:
// Here, I am checking if SDK >= M
if (VersionUtils.isMarshmallowOrGreater()) {
cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
if (cameraManager != null) {
try {
cameraId = cameraManager.getCameraIdList()[0];
} catch (CameraAccessException | ArrayIndexOutOfBoundsException e) {
e.printStackTrace();
}
}
} else {
if (camera == null || camera.getParameters() == null) {
try {
camera = Camera.open();
params = camera.getParameters();
} catch (RuntimeException e) {
e.printStackTrace();
}
}
}
Here is the code to switch on the flash/tourch:
if (VersionUtils.isMarshmallowOrGreater()) {
try {
cameraManager.setTorchMode(cameraId, true);
} catch (Exception e) {
e.printStackTrace();
}
} else {
if (camera == null || params == null || camera.getParameters() == null) {
getCamera();
return;
}
params = camera.getParameters();
params.setFlashMode(Parameters.FLASH_MODE_TORCH);
camera.setParameters(params);
startCameraPreview();
}
Also, here is the code of switching off the camera flash:
if (VersionUtils.isMarshmallowOrGreater()) {
try {
cameraManager.setTorchMode(cameraId, false);
} catch (Exception e) {
e.printStackTrace();
}
} else {
if (camera == null || params == null || camera.getParameters() == null) {
return;
}
try {
params = camera.getParameters();
params.setFlashMode(Parameters.FLASH_MODE_OFF);
camera.setParameters(params);
stopCameraPreview();
camera.release();
camera = null;
} catch (Exception e) {
e.printStackTrace();
}
}
Code of startCameraPreview() method:
private void startCameraPreview() {
try {
camera.startPreview();
} catch (Exception e) {
e.printStackTrace();
}
}
I don't have any receiver in my app except the widget provider class but I don't have any line of code the do (register/unregister) a receiver!!
I searched and read many links resources regarding this issue but I could not find any clue to exactly know the line which causing it.
Anyone faced this issue, your help is appreciated.
I had the same issue (or similar). My stacktrace was exactly as yours. I've solved my problem by ensuring (in the code of my application) that I don't try to switch torch Off if the torch was not turned ON by my application previously.
Crash occurred when I was calling cameraManager.setTorchMode(cameraId, false) two times sequentially.
So I just maintain boolean flag in my application which shows exact torch state at the moment. Set it to true right after cameraManager.setTorchMode(cameraId, true) call and don't do cameraManager.setTorchMode(cameraId, false) if the flag in not true. Set the flag to false after successful cameraManager.setTorchMode(cameraId, false).
Hope this helps...
Camera.Parameters is deprecated in API level 21. Use CameraManager instead.
For setFlashMode (String value) in Camera.Parameters, there is an equivalent method setTorchMode (String cameraId, boolean enabled) in CameraManager
I think this post (When trying turn off camera led, app crash) is helpful.
In short,
f you try to disable flashlight again (even if flashlight is already disabled), then app is crashed.
I'm using google vision to read QR tags.
everything has be going fine on the phone that I was developing for.
recently I was given an Galaxy Tab A as the target device.
I cannot get the Tab A to auto focus close enough to read the qr tags.
I noticed in the camera app that it has a Macro setting. when I turn it on, it focuses up close and reads the tag just fine.
So...
in Xamarin how do I access the camera object's parameters when I am using the google vision cameraSource?
I've tried the examples I've found here, and I guess I'm missing something, cause I can't make them work.
Thanks for any help.
update
Here's the only way I have been able to get this java code to convert, and it doesn't work. Obviously I'm doing something wrong...
private static bool cameraFocus(CameraSource cameraSource, String focusMode)
{
Java.Lang.Reflect.Field[] declaredFields = cameraSource.Class.GetDeclaredFields();
foreach (Java.Lang.Reflect.Field field in declaredFields) {
if (field.GetType() == typeof(Android.Hardware.Camera)) {
field.Accessible = true;
try {
Android.Hardware.Camera camera = (Android.Hardware.Camera)field.Get(cameraSource);
if (camera != null) {
Android.Hardware.Camera.Parameters parameters = camera.GetParameters();
parameters.FocusMode = Android.Hardware.Camera.Parameters.FocusModeMacro;
camera.SetParameters(parameters);
return true;
}
return false;
} catch {
}
break;
}
}
return false;
}
Please read this, look cameraFocus method:
private static boolean cameraFocus(#NonNull CameraSource cameraSource, #NonNull String focusMode) {
Field[] declaredFields = CameraSource.class.getDeclaredFields();
for (Field field : declaredFields) {
if (field.getType() == Camera.class) {
field.setAccessible(true);
try {
Camera camera = (Camera) field.get(cameraSource);
if (camera != null) {
Camera.Parameters params = camera.getParameters();
params.setFocusMode(focusMode);
camera.setParameters(params);
return true;
}
return false;
} catch (IllegalAccessException e) {
e.printStackTrace();
}
break;
}
}
return false;
}
You need use reflection to get your camera to focused.
I have a problem regarding the camera in the most recent Marshmallow build, more specifically the flashlight.
On any pre-Marshmallow version all I need to do to turn the flash on/off was the following:
private void turnFlashOn(final Camera camera, int flashLightDurationMs) {
if (!isFlashOn()) {
final List<String> supportedFlashModes = camera.getParameters().getSupportedFlashModes();
if (supportedFlashModes != null && supportedFlashModes.contains(Camera.Parameters.FLASH_MODE_TORCH)) {
mParams.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
camera.setParameters(mParams);
}
}
}
and
private void turnFlashOff(Camera camera) {
if (camera != null) {
final List<String> supportedFlashModes = camera.getParameters().getSupportedFlashModes();
if (supportedFlashModes != null && supportedFlashModes.contains(Camera.Parameters.FLASH_MODE_OFF)) {
mParams.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
camera.setParameters(mParams);
}
}
}
Unfortunately, Marshmallow devices began to crash in the wild. Somehow camera.getParameters() and camera.setParameters() began to fail with messages such as:
RuntimeException: getParameters failed (empty parameters)
RuntimeException: setParameters failed
I tried starting and stopping the preview before getting the parameters, which no longer throws errors. However the preview is not resumed when I call camera.startPreview().
I fear releasing the camera and reopening it is out of the question as this takes some seconds and would produce a bad experience.
Any suggestions on how to turn the flashlight on/off in Marshmallow reliably?
Google has introduced torchmode in OS 6 (Android M).
if your purpose is only to turn on/off the flash, below code can help you with that:
private static void handleActionTurnOnFlashLight(Context context){
try{
CameraManager manager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
String[] list = manager.getCameraIdList();
manager.setTorchMode(list[0], true);
}
catch (CameraAccessException cae){
Log.e(TAG, cae.getMessage());
cae.printStackTrace();
}
}
private static void handleActionTurnOffFlashLight(Context context){
try{
CameraManager manager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
manager.setTorchMode(manager.getCameraIdList()[0], false);
}
catch (CameraAccessException cae){
Log.e(TAG, cae.getMessage());
cae.printStackTrace();
}
}
All you have to do is: Get cameraid's list out of which camera ID zero(0) is your primary camera for which you want to turn flash on/off. Simply pass the cameraID to setTochMode API with boolean value for turning it on or off.
Do note that this piece of code will work only with OS 6, so you need to check for device OS and based upon that you need to select which API's to call for pre-marshmallow devices.
Kindly mark this as solution if it solves your problem.
As Saurabh7474 has responded, to check the version of Android and use setTorchMode API it's very correct.
Although you can also use params.setFlashMode (...) in marshmallow using
mCamera.setPreviewTexture (new SurfaceTexture (100))
after Camera.open (...) and before calling mCamera.startPreview();
try {
Log.i(TAG, "getCamera");
int requestedCameraId = getIdForRequestedCamera(mFacing);
if (requestedCameraId == -1) {
throw new RuntimeException("Could not find requested camera.");
}
mCamera = Camera.open(requestedCameraId);
mCamera.setPreviewTexture(new SurfaceTexture(DUMMY_TEXTURE_NAME));
params = mCamera.getParameters();
} catch (RuntimeException e) {
Log.e("Failed to Open. Error:", e.getMessage());
} catch (IOException e) {
Log.e("Failed to Open. can't setPreviewTexture:", e.getMessage());
}
then when you want, you can use
mParams.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
camera.setParameters(mParams);
My answer is based on CameraSource examples of Vision API that uses params.setFlashMode (...) and works in Api 23 and above.
If you decide to inspect CameraSource, the key method that has solved the same problem is "start ()", in the line 312 ...
https://github.com/googlesamples/android-vision/blob/master/visionSamples/barcode-reader/app/src/main/java/com/google/android/gms/samples/vision/barcodereader/ui/camera/CameraSource.java
The reason you can find here
https://stackoverflow.com/a/33333046/4114846
Update your app to check for permissions at runtime. You have to have android.permission.CAMERA granted. Including it in the manifest of your app is not going to grant it to you on Marshmallow. You'll need to detect whether or not it has been granted and request it.
Building off of Saurabh7474's answer, you can toggle Marshmallow's torchMode by registering a torchCallback:
final CameraManager mCameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
CameraManager.TorchCallback torchCallback = new CameraManager.TorchCallback() {
#Override
public void onTorchModeUnavailable(String cameraId) {
super.onTorchModeUnavailable(cameraId);
}
#Override
public void onTorchModeChanged(String cameraId, boolean enabled) {
super.onTorchModeChanged(cameraId, enabled);
boolean currentTorchState = enabled;
try {
mCameraManager.setTorchMode(cameraId, !currentTorchState);
} catch (CameraAccessException e){}
}
};
mCameraManager.registerTorchCallback(torchCallback, null);//fires onTorchModeChanged upon register
mCameraManager.unregisterTorchCallback(torchCallback);
I am integrating barcode scanning functionality using zxing in android, my app includes turn on/off flash light functionality by button press.
When the flash button is pressed it sets the flash to mode torch and that parameter is set to be a camera parameter. I got an exception: Set Paramters failed exception.
Here is my code.
Parameters p = camera.getParameters();
List<String> supportedFlashModes =p.getSupportedFlashModes();
if (active)
{
if(supportedFlashModes!= null)
{
if(supportedFlashModes.contains(Parameters.FLASH_MODE_TORCH))
{
p.setFlashMode(Parameters.FLASH_MODE_TORCH);
}
}
CaptureActivity.flashLightON=true;
}
else
{
p.setFlashMode(Parameters.FLASH_MODE_OFF);
}
camera.setParameters(p);
I got the following exception:
06-07 12:15:26.107: E/AndroidRuntime(24642): FATAL EXCEPTION: main
06-07 12:15:26.107: E/AndroidRuntime(24642): java.lang.RuntimeException:
setParameters failed
06-07 12:15:26.107: E/AndroidRuntime(24642): at
android.hardware.Camera.native_setParameters(Native Method)
Please advice me how to resolve this issue?
I had the same problem with my Google Nexus One.
The problem was solved for me by canceling autofocus, set parameters and then reset autofocus
camera.cancelAutoFocus();
camera.setParameters(parameters);
camera.autoFocus(autoFocusCallback);
Unfortunately its not an universal workaround since it does not work for S3 or Galaxy Nexus who totally loses it...
S-G starts to flashes and S3 stop autofocus.
I solved the issue for S3 by stoping preview and then restarting after the parameters were set
I had the same problem, turning the flaslight with the camera on causes some autofocus collision, when setting the parameters at the same time (especially when your autofocus interval is low).
Paste this right before enabling/disabling the flashlight, it will slow down the enabling event, but hey, no crash (not 100% crash proof though).
//sleep time should be long, 3000ms should be enough to prevent crash on some devices, 2000 may by to little (still crashes on Sony Xperia devices) - I have no idea wy this works that way :D
try {
Thread.currentThread().sleep(3000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
Edit:
Better way to solve this problem, is to put your setParameters method in a loop, and catch runtime exception everytime. Exit the loop when there is no exception, or when your (optional) loop counter reaches max value.
final int MAX_TRIES = 100;
boolean success = false;
int triesCounter = 0;
while (!success) {
try {
triesCounter++;
if (triesCounter > MAX_TRIES) {
success = true;
}
parameters = camera.getParameters();
if (parameters != null) {
parameters.setFlashMode(Parameters.FLASH_MODE_OFF);
camera.setParameters(parameters);
}
success = true;
} catch (Exception exception) {
}
}
Some of the devices do not support and gives such problems. You can refer the link bellow, so that you can get a clear idea about it.
How to turn on camera flash light programmatically in Android?
One solution that works is to create a queue of camera parameters. Setting the torch would add a torch parameter to the queue.
Inside the onAutoFocus callback, call a function that iterates through all of the queue items and commits them. This way you are guaranteed that you are not autofocusing.
turning the flaslight with the camera on/trouch (FLASH_MODE_TORCH)
causes some autofocus collision, when setting the parameters at the
same time (especially when your autofocus interval is low).
I don't like the thread workaround. So I fixed it like this
...
private Boolean _flashOn = null;
...
private Runnable doAutoFocus = new Runnable() {
public void run() {
if (previewing) {
if (_flashOn != null) {
Parameters p = mCamera.getParameters();
if (_flashOn) {
p.setFlashMode(Parameters.FLASH_MODE_TORCH);
}else{
p.setFlashMode(Parameters.FLASH_MODE_OFF);
}
mCamera.setParameters(p);
_flashOn = null;
}
mCamera.autoFocus(autoFocusCB);
}
}
};
No RuntimeException now.
But still has FLASH_MODE_TORCH + autoFocus bug on some adroid devices, e.g. Motorala Milestone/Samsun I9100G/Blahblah...
See also a declined issue for Android: https://code.google.com/p/android/issues/detail?id=14360
BTW. ZBar is faster than ZXing :)
I wanted to start the flash light at the start of scanning and solve it with this.
I have changed in com.google.zxing.client.android.camera method openDriver
Camera theCamera = camera;
if (theCamera == null) {
theCamera = Camera.open();
if (theCamera == null) {
throw new IOException();
}
final Parameters p = theCamera.getParameters();
p.setFlashMode(Parameters.FLASH_MODE_TORCH);
theCamera.setParameters(p);
camera = theCamera;
}
than I have removed from com.google.zxing.client.android.camera.CameraConfigurationManager
initializeTorch(parameters, prefs);
finaly I have changed AndroidManifest.xml
<uses-feature android:name="android.hardware.camera.flash" android:required="true"/>
Try out this code. It worked fine with me.
private void turnOnFlashLight(){
if (!pm.hasSystemFeature(PackageManager.FEATURE_CAMERA))
{
//Check for Device Camera
Toast.makeText(this, getString(R.string.no_device_camera_msg), Toast.LENGTH_SHORT).show();
flashLightControl.setChecked(false);
return;
}else if (!pm.hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH))
{
//Check for Camera flash
Toast.makeText(this, getString(R.string.no_camera_flash), Toast.LENGTH_SHORT).show();
flashLightControl.setChecked(false);
return;
}else
{
//BIG ISSUE Fash mode is device specific
//Turn On Flash
String _model = android.os.Build.MODEL;
String _manufaturer = android.os.Build.MANUFACTURER;
if((_model.contains("GT-S5830") && _manufaturer.contains("samsung"))) //|| (_manufaturer.contains("lge")))
{
new Thread(new Runnable()
{
#Override
public void run()
{
// TODO Auto-generated method stub
Log.d(TAG, "From TimerTask..!!!");
cameraParams = CameraManager.camera.getParameters();
//cameraParams.setFlashMode(Parameters.FLASH_MODE_TORCH);
cameraParams.set("flash-mode", "on");
CameraManager.camera.setParameters(cameraParams);
CameraManager.camera.startPreview();
isFlash_On_Mode_Device = true;
isLightOn = true;
try{
Thread.sleep(2000);
Log.d(TAG, "From TimerTask After sleep!!!");
cameraParams = CameraManager.camera.getParameters();
cameraParams.setFlashMode(Parameters.FLASH_MODE_OFF);
CameraManager.camera.setParameters(cameraParams);
CameraManager.camera.startPreview();
isLightOn = true;
}
catch(Exception e){}
}
}).start();
}else if(_manufaturer.contains("lge"))
{
//Log.d(TAG, "From LG");
cameraParams = CameraManager.camera.getParameters();
cameraParams.setFlashMode(Parameters.FLASH_MODE_ON);
CameraManager.camera.setParameters(cameraParams);
CameraManager.camera.startPreview();
isLightOn = true;
}
else if(CameraManager.camera != null)
{
cameraParams = CameraManager.camera.getParameters();
//cameraParams.setFlashMode(Parameters.FLASH_MODE_TORCH);
cameraParams.set("flash-mode", "torch");
CameraManager.camera.setParameters(cameraParams);
CameraManager.camera.startPreview();
isLightOn = true;
}
}
private void turnOffFlashLight()
{
if (isLightOn)
{
if(CameraManager.camera != null)
{
if(isFlash_On_Mode_Device)
{
CameraManager.get().closeDriver();
SurfaceHolder surfaceHolder = surfaceView.getHolder();
if (hasSurface)
{
initCamera(surfaceHolder);
if(CameraManager.camera != null)
CameraManager.camera.startPreview();
}
//Log.d(TAG, "Stopping camera..!!!");
}else
{
cameraParams = CameraManager.camera.getParameters();
cameraParams.setFlashMode(Parameters.FLASH_MODE_OFF);
CameraManager.camera.setParameters(cameraParams);
CameraManager.camera.startPreview();
}
isLightOn = false;
isFlash_On_Mode_Device = false;
}
}
}
I'm adapting an app so it will work on the KindleFire, which doesn't have a camera.
I don't have any Android devices that lack a camera, so I don't know if the following code actually will return false for the Kindle. I'm using reflection because my app has already been released with Donut compatibility, and Donut doesn't have PackageManager.hasSystemFeature().
I'm assuming Donut devices all have cameras--hasn't caused me trouble yet.
public static boolean isCameraAvailable(Context context){
PackageManager pm = context.getPackageManager();
return tryHasSystemFeature(pm,"android.hardware.camera");
}
private static Method packageManager_hasSystemFeature;
static {
initCompatibility();
};
private static void initCompatibility() {
try {
packageManager_hasSystemFeature = PackageManager.class.getMethod(
"hasSystemFeature", new Class[] { String.class } );
} catch (NoSuchMethodException nsme) {
//leave the Method null
}
}
static private boolean tryHasSystemFeature(PackageManager pm,String feature){
if (packageManager_hasSystemFeature != null) {
try {
final Boolean hasIt = (Boolean) packageManager_hasSystemFeature.invoke(pm,feature);
return hasIt.booleanValue();
} catch (Exception e) {
e.printStackTrace();
} finally {
}
}
return true;
}
Actually it's recommended to add this line in your manifest file, if you want to be sure the device has a camera:
<uses-feature android:name="android.hardware.camera" />
Market will prevent a device without a camera from downloading your application.