25

So many LED flashlight API questions for Android. I'm afraid to ask yet another, but here goes..

Using the tried and true FLASH_MODE_TORCH I am able to achieve satisfaction with my Samsung Galaxy SII and get the LED flash turned on. On my friend's Galaxy Nexus, no such luck. Nor on my other friend's Droid X.

I'm noticing for a not insignificant number of devices specific native IOCTL calls seem to be required. Is this the case for the Galaxy Nexus? How do I find a reference to program it?

I am doing the standard FLASH_MODE_TORCH/"flash-mode"="torch", startPreview() chain.

Kind of disappointing that this seemingly standard API doesn't appear to be so universal after all.

Malachi
  • 2,022
  • 2
  • 24
  • 35

1 Answers1

48

What I found out is that some devices need a SurfaceView to turn on the LED.

SurfaceView preview = (SurfaceView) findViewById(R.id.PREVIEW);
SurfaceHolder mHolder = preview.getHolder();
mHolder.addCallback(this);
Camera mCamera = Camera.open();
mCamera.setPreviewDisplay(mHolder);

// Turn on LED  
Parameters params = mCamera.getParameters();
params.setFlashMode(Parameters.FLASH_MODE_TORCH);
mCamera.setParameters(params);      
mCamera.startPreview();

...

// Turn off LED
Parameters params = mCamera.getParameters();
params.setFlashMode(Parameters.FLASH_MODE_OFF);
mCamera.setParameters(params);
mCamera.stopPreview();
mCamera.release();

Your activity needs to implement SurfaceHolder.Callback:

public void surfaceChanged(SurfaceHolder holder, int format, int width,
        int height) {}

public void surfaceCreated(SurfaceHolder holder) {
    mHolder = holder;
    mCamera.setPreviewDisplay(mHolder);
}

public void surfaceDestroyed(SurfaceHolder holder) {
    mCamera.stopPreview();
    mHolder = null;
}

The surfaceview has to be visible, android:visibility="invisible" or a height and width of 0 won't work. Unfortunately I didn't find a good solution to hide it, so I just gave it a size of 1x1dip and positioned it underneath a button..

**(To expand on above paragraph [Don't have enough rep to reply, but felt it was useful]) Somewhere in the XML of your current Content View, you want:

<SurfaceView
    android:id="@+id/PREVIEW"
    android:layout_width="1dip"
    android:layout_height="1dip"/>

If you have it inside a RelativeLayout (preferred), you can also do alignParentLeft/Bottom to tuck it in a corner. This method works for my Galaxy Nexus, but it's a known problem (phone-side) for Droid X (with the .621 update, anyway), and doesn't work on mine. Great answer, timosch!

timoschloesser
  • 2,679
  • 4
  • 22
  • 32
  • I'm gonna give this a shot. Thanks-- – Malachi Feb 24 '12 at 08:17
  • 1
    yes it did, however I had to add mHolder.addCallback(this) after SurfaceHolder mHolder = preview.getHolder(); This might be helpful too http://stackoverflow.com/questions/10734858/opening-flashlight-of-galaxy-nexus – shiraz Sep 18 '12 at 13:06
  • And if I want to turn on flashlight from widget, How I must do in that case ? – Viktor Apoyan Dec 13 '12 at 19:47
  • You can set the Activity theme to `@android:style/Theme.Translucent.NoTitleBar` so the `SurfaceView` will not be displayed at all – Muzikant Oct 24 '13 at 14:19
  • One small notice. No need setPreviewDisplay after Camera.open. In documentation said - `Important: Pass a fully initialized SurfaceHolder to setPreviewDisplay(SurfaceHolder). Without a surface, the camera will be unable to start the preview. ` – w201 Feb 14 '19 at 11:52