Use camera flashlight in Android

AndroidAndroid CameraFlashlight

Android Problem Overview


I'm trying to use the cameras LED flashlight in a widget. I've found several threads about this topic (i.e. the one mentioned later..) , now I'm trying to control the light using:

Camera cam = Camera.open(); 	
Parameters p = cam.getParameters();
p.setFlashMode(Parameters.FLASH_MODE_TORCH);
cam.setParameters(p);
cam.release();

In the AndroidManifest.xml tried different permissions, currently I have:

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.FLASHLIGHT"/>
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<uses-feature android:name="android.hardware.camera.flash" />

I'm testing this on my Galaxy Tab as I don't have any other Android devices at hand: the light does not turn on. So I have a few questions now:

  1. Is there any way to test the led light behavior in the Emulator?
  2. Am I doing something wrong here?
  3. According to this question which deals with the same problem, it works differently on the Galaxy Tab. How?
  4. And finally, if it does work differently, I'm starting to wonder if it's just the Galaxy Tab or if other devices use different methods too. It would be hard to test then and it seems rather odd to me.

Thanks for any insight!

By the way, I quickly tested with quick-settings which gets mentioned a few times here. The flashlight doesn't work with quick-settings either.

Note that the Galaxy Tab stil uses android 2.2. I see there were some changes between 2.2 and 2.3.

Comment: I know it has to work somehow as I have found other apps in the market that work perfectly with the Galaxy Tab.

Comment 2: If I set cam.setParameters(p); and directly ask the camera for the current state with getFlashMode() it correctly returns FLASH_MODE_TORCH. However, if I release the camera and re-open it, it returns FLASH_MODE_OFF. It's almost as if the Camera object aknowledges the request but doesn't really pass it on to the hardware!?

--

After Konstantins comment, I removed the cam.release(); part. He is right, the settings are not persisted if you release the camera. If you use cam.open() again, you will get a fresh instance with the light off. The light's still not working on the galaxy tab though. So, I guess it's hard to keep the light on if you're trying to control it through a widget then. As soon as the background service is finished, the camera object is released automatically and therefore the light switches off again. My questions still remain, especially why the camera doesn't switch on in the first place.

Android Solutions


Solution 1 - Android

Every device is a bit different. Samsung especially likes to make things complicated for app developers.

On the Galaxy Tab you should be good with:

Camera cam;
void ledon() {
    cam = Camera.open();     
    Parameters params = cam.getParameters();
    params.setFlashMode(Parameters.FLASH_MODE_ON);
    cam.setParameters(params);
    cam.startPreview();
    cam.autoFocus(new AutoFocusCallback() {
                public void onAutoFocus(boolean success, Camera camera) {
                }
            });
}

void ledoff() {
    cam.stopPreview();
    cam.release();
}

If that doesn't work then it might be a matter of setting FLASH_MODE_OFF initially and changing it after the startPreview.

Solution 2 - Android

You must not release the camera after setting the parameters. I found that flash is activated (in torch mode) after I have started the preview. ( Applies to motorola defy, 2.1 )

It is also a good idea to check supported flash modes, before trying to activate them.

Messing around with camera settings on android is darkest voodoo: Many devices behave differently and there seems to be no reliable way of targeting them all with one piece of code. Safest bet is to always set up your camera properly when your onResume() method is called. I would also consider doing the same in onConfigChange(), because at least Motorola screen locker can force your application into portrait mode, restarting it completely.

P.s. I suppose that when you close the camera, the native camera app is closed and then recreated in a fresh state.

Solution 3 - Android

I have done it the following way, which works on many phones:

 String manuName = android.os.Build.MANUFACTURER.toLowerCase();
 Camera mCamera;

The below code shows, how to turn lights off and on:

  private void processOnClick() {

	if (manuName.contains("motorola")) {
		DroidLED led;
		try {
			led = new DroidLED();
			led.enable(true);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	} else {
		if (mCamera == null) {
			try {
				mCamera = Camera.open();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

		if (mCamera != null) {

			final Parameters params = mCamera.getParameters();

			List<String> flashModes = params.getSupportedFlashModes();

			if (flashModes == null) {
				return;
			} else {
				if (count == 0) {
					params.setFlashMode(Parameters.FLASH_MODE_OFF);
					mCamera.setParameters(params);
					mCamera.startPreview();
				}

				String flashMode = params.getFlashMode();

				if (!Parameters.FLASH_MODE_TORCH.equals(flashMode)) {

					if (flashModes.contains(Parameters.FLASH_MODE_TORCH)) {
						params.setFlashMode(Parameters.FLASH_MODE_TORCH);
						mCamera.setParameters(params);
					} else {
						// Toast.makeText(this,
						// "Flash mode (torch) not supported",Toast.LENGTH_LONG).show();

						params.setFlashMode(Parameters.FLASH_MODE_ON);

						mCamera.setParameters(params);
						try {
							mCamera.autoFocus(new AutoFocusCallback() {
								public void onAutoFocus(boolean success, Camera camera) {
									count = 1;
								}
							});
						} catch (Exception e) {
							e.printStackTrace();
						}
					}
				}
			}
		}
	}

	if (mCamera == null) {
		return;
	}
}

private void processOffClick() {

	if (manuName.contains("motorola")) {
		DroidLED led;
		try {
			led = new DroidLED();
			led.enable(false);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	} else {
		if (mCamera != null) {
			count = 0;
			mCamera.stopPreview();
		}
	}
}

Below is the class DroidLED:

 class DroidLED {

    private Object svc = null;
    private Method getFlashlightEnabled = null;
    private Method setFlashlightEnabled = null;
    
    @SuppressWarnings("unchecked")
    public DroidLED() throws Exception {
            try {
                    // call ServiceManager.getService("hardware") to get an IBinder for the service.
                    // this appears to be totally undocumented and not exposed in the SDK whatsoever.
                    Class sm = Class.forName("android.os.ServiceManager");
                    Object hwBinder = sm.getMethod("getService", String.class).invoke(null, "hardware");
                    
                    // get the hardware service stub. this seems to just get us one step closer to the proxy
                    Class hwsstub = Class.forName("android.os.IHardwareService$Stub");
                    Method asInterface = hwsstub.getMethod("asInterface", android.os.IBinder.class);
                    svc = asInterface.invoke(null, (IBinder) hwBinder);
    
                    // grab the class (android.os.IHardwareService$Stub$Proxy) so we can reflect on its methods
                    Class proxy = svc.getClass();
                    
                    // save methods
                    getFlashlightEnabled = proxy.getMethod("getFlashlightEnabled");
                    setFlashlightEnabled = proxy.getMethod("setFlashlightEnabled", boolean.class);
            }
            catch(Exception e) {
                    throw new Exception("LED could not be initialized");
            }
    }
    
    public boolean isEnabled() {
            try {
                    return getFlashlightEnabled.invoke(svc).equals(true);
            }
            catch(Exception e) {
                    return false;
            }
    }
    
    public void enable(boolean tf) {
            try {
                    setFlashlightEnabled.invoke(svc, tf);
            }
            catch(Exception e) {}
    }

}

The following permissions must be set in your AndroidManifest.xml:

 <uses-permission android:name="android.permission.CAMERA" />
 <uses-permission android:name="android.permission.FLASHLIGHT"/>
 <uses-feature android:name="android.hardware.camera" />
 <uses-feature android:name="android.hardware.camera.autofocus" />
 <uses-feature android:name="android.hardware.camera.flash" />

Solution 4 - Android

This works for me on a HTC Desire... (with 2.2) (Of course with Camera and Flashlight permissions):

	Camera mycam = Camera.open();
	Parameters p = mycam.getParameters();// = mycam.getParameters();
	p.setFlashMode(Parameters.FLASH_MODE_TORCH); 
	mycam.setParameters(p); //time passes 
	try {
		Thread.sleep(500);
	} catch (InterruptedException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
	p.setFlashMode(Parameters.FLASH_MODE_OFF);
	mycam.release();

Solution 5 - Android

You also could try to add a surface view. Please take a look at my answer to https://stackoverflow.com/questions/8876843/led-flashlight-on-galaxy-nexus-controllable-by-what-api/9379765#9379765

Solution 6 - Android

Solution 7 - Android

private Camera camera;
void openCam(){
    camera = Camera.open();
    if (camera != null) {
        Camera.Parameters params = camera.getParameters();
        camera.setParameters(params);
    }
    Camera.Parameters p = camera.getParameters();
    p.setFlashMode(Parameters.FLASH_MODE_TORCH);
    camera.setParameters(p);
}

set permission in Manifest:

<uses-permission
    android:name="android.permission.FLASHLIGHT"
    android:permissionGroup="android.permission-group.HARDWARE_CONTROLS"
    android:protectionLevel="normal" />

<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.flash" />

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionpgruetterView Question on Stackoverflow
Solution 1 - AndroidKevin TeslaCoilView Answer on Stackoverflow
Solution 2 - AndroidKonstantin PribludaView Answer on Stackoverflow
Solution 3 - AndroidSiddhpura AmitView Answer on Stackoverflow
Solution 4 - AndroidHoracemanView Answer on Stackoverflow
Solution 5 - AndroidtimoschloesserView Answer on Stackoverflow
Solution 6 - AndroidYogendraView Answer on Stackoverflow
Solution 7 - AndroidiKushalView Answer on Stackoverflow