LED flashlight on Galaxy Nexus controllable by what API?

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.


Solution 1:

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!