LED flashlight on Galaxy Nexus controllable by what API? - android

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.

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!

Related

AutoExposureLock resetting after calling takePicture()

I'm having a problem with the exposure lock in the Android Camera.Parameters class. I'm able to lock the exposure before taking a picture, but upon calling camera.takePicture(shutterCallback, rawCallback, jpegCallback) the exposure starts auto-adjusting again.
Also, getAutoExposureLock() still returns true even though the preview and the final saved images show adjusted exposure.
The Android documentation says the exposure lock won't be changed by taking a picture: http://developer.android.com/reference/android/hardware/Camera.Parameters.html#setAutoExposureLock(boolean)
What am I missing?
I managed to lock exposure compensation on my Galaxy S4
Camera.Parameters parameters = mCamera.getParameters();
parameters.setAutoExposureLock(true);
mCamera.setParameters(parameters);
mCamera.startPreview();
Then in each takePicture callback I basically reset the lock to true
Camera.Parameters parameters = mCamera.getParameters();
parameters.setAutoExposureLock(true);
mCamera.setParameters(parameters);
This manages to do something. All images captured are almost equally bright. Changing exposureCompensation has no effect, but when changing ISO the exposure time is automagically adjusted.
I'll dig some more into this and update this post accordingly.
I have the same problem. That's because camera.takePicture(shutterCallback, rawCallback, jpegCallback) stops the preview; you must call camera.startPreview(); to continue previewing.
I've come accross this myself, I'm assuming its an API error as it works the same for me as for you. Unless you have managed to fix it in the meantime? Let me know!
Resetting the lock to true in takePicture callback doesn't work well on my Samsung Galaxy Note 3. It makes situation a bit better, but still produces images with quite different brightness. Exif inside those jepgs confirm that exposure time varies from 1/120 sec to 1/400 sec.
I also noticed that some jpegs have similar exposure time (1/120 sec) but different brightness value saved in exif. So, my was guess that the image post-processor is the game breaker.
I've dumped all camera parameters via native_getParameters, found image correction parameters and set them all to 5. Those parameters are:
set("min-brightness", 5);
set("max-brightness", 5);
set("contrast", 5);
set("min-contrast", 5);
set("max-contrast", 5);
set("max-saturation", 5);
set("min-saturation", 5);
set("saturation", 5);
Now output is much better. Images almost equally bright. All of 500 test images have exposure time = 1/120 ± 1 (rarely 1/125) and brightness = 5 ± 0.1.
I had the same issue on S3. I ended putting those line at the begining of the callback:
public void onPictureTaken(byte[] data, Camera camera) {
//Relock the camera for S3 device
camera.startPreview();
UnLockCamera(camera);
LockCamera(camera);
// your code
With the two functions below
public void LockCamera(Camera camera){
//stop auto white balance and auto exposure lock
Camera.Parameters params = camera.getParameters();
if (params.isAutoExposureLockSupported()) {
params.setAutoExposureLock (true);
}
if (params.isAutoWhiteBalanceLockSupported()) {
params.setAutoWhiteBalanceLock(true);
}
camera.setParameters(params);
}
public void UnLockCamera(Camera camera){
//stop auto white balance and auto exposure lock
Camera.Parameters params = camera.getParameters();
if (params.isAutoExposureLockSupported()) {
params.setAutoExposureLock (false);
}
if (params.isAutoWhiteBalanceLockSupported()) {
params.setAutoWhiteBalanceLock(false);
}
camera.setParameters(params);
}

Android camera changes dimensions when rotating phone

I'm developing an android application which uses the camera. I got a problem with surfaceChanged() method. Here is my code.
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
Log.e(TAG, "surfaceChanged");
if (mPreviewRunning) {
mCamera.stopPreview();
}
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewSize(w, h);
mCamera.setParameters(parameters);
try {
mCamera.setPreviewDisplay(holder);
} catch (IOException e) {
e.printStackTrace();
}
mCamera.startPreview();
mPreviewRunning = true;
}
the variable mPreviewRunning is initialized as false at the beginning. program runs just fine with horizontal orientation. but when I rotates the phone to the vertical orientation the screen is rotated and is stretched. I can't understand why it's happened. Please help me to solve this problem.
Camera does not change orientation at all - CCD is soldered to motherboard , and delivers pixels as if it were in landscape mode ( most probably ) however, your activity could be restarted by OS on orientation change, unless you disable it in manifest.
( and your surface view is recreated on this restart )
Look in this project for android demos handling camera management:
https://sourceforge.net/p/javaocr/source/ci/5cb9b4176f40ada57296cce79addd205e4c1405c/tree/demos/camera-utils/src/main/java/net/sf/javaocr/demos/android/utils/camera/CameraManager.java#l85
Your mistake is to set preview size from surface size - do not do this. Camera provides limited set of acceptable preview sizes and is free to ignore other settings ( exact behaviour is device depending)
Preview size means used CCD resolution, and camera software will render it on your surface view in size of the surface view doung scaling as necessary.

ColorEffect not visible on camera preview

I am trying to get a camera preview with a color effect applied to it, such as for example the NEGATIVE effect. There are no errors, and the preview is visible without problems, but independent of the ColorEffect I set - the camera preview remains unchanged. I tested if the effects I am trying to use are available to my phone by running params.getSupportedColorEffects() (also these effects also work in the built in photo app).
I have no idea what is wrong with the code - I am posting it below. Perhaps someone here has an idea what could make this work? Thanks in advance.
public class CustomCameraView extends SurfaceView{
Camera mCamera;
SurfaceHolder mHolder;
public CustomCameraView(Context context){
super(context);
mHolder = this.getHolder();
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
mHolder.addCallback(mSurfaceHolderListener);
}
SurfaceHolder.Callback mSurfaceHolderListener = new SurfaceHolder.Callback() {
public void surfaceCreated(SurfaceHolder holder) {
mCamera=Camera.open();
try {
mCamera.setPreviewDisplay(mHolder);
}
catch (Exception e){ }
}
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height)
{
Camera.Parameters params = mCamera.getParameters();
params.setColorEffect(Camera.Parameters.EFFECT_NEGATIVE);
mCamera.setParameters(params);
mCamera.startPreview();
}
public void surfaceDestroyed(SurfaceHolder arg0)
{
mCamera.stopPreview();
mCamera.release();
}
};
}
After some testing it turned out the problem could be related to the HTC Desire I was testing on (or maybe its OS version). The code works correctly on some other Samsung phones. I haven't figured out what could be the problem on the HTC.
UPDATE:
I have managed to get the effects working, but truly by accident, and I still don't understand why. But I will give the answer here - perhaps someone will find it useful, or maybe will be able to explain why it happens this way:
I added the following line to the surfaceChanged method because I was trying to decrease the size of the preview:
previewHolder.setFixedSize(width, height-1);
This had the result of making the selected effect visible.
When I changed this line to:
previewHolder.setFixedSize(width, height);
the effect was not visible any more once again. So odd.... it works for set height being anything less than the received height parameter.
I have been struggling with this as well. I found out that the HTC Desire its camera needs a strange order of executing the setParameters, setPreviewDisplay and startPreview for the color effect to work. The order is:
Camera.Parameters parameters = camera.getParameters();
//set the parameters
camera.setParameters(parameters);
camera.startPreview();
camera.setParameters(parameters);
camera.setPreviewDisplay(surfaceHolder);
Calling startPreview before setPreviewDisplay is documented in the Android SDK as a way of initializing the camera and the surfaceView in parallel.
Regarding your update about getting the effects to work by accident, the same happend to me! I assume for the same reason, some of my code got called twice in quick succesion (in my case due to a changing database object). This caused the method to (re)set the parameters and (re)start the preview to be called twice producing the desired result. After realising this and some more experimenting the above order seemed to work on both my HTC Desire and Acer Iconia A500 and I was quite happy with it.
However I have just received a comment for my application saying it produces corrupted images on the HTC Desire HD so I would recommend not using this order of camera initialization as a default but rather as a fix for the HTC Desire.
After setting new parameters to camera and starting preview invalidate() are calling on your SurfaceView . But it only Invalidate the whole view. If the view is visible, onDraw(android.graphics.Canvas) will be called at some point in the future. So there is no guarantees that onDraw() will be called immediately. But onDraw() are always invoking after calling onMeasure() with size differs from current. So it can be a reason of this odd behavior.
Simple answers use following type :
Camera camera = null;
camera = Camera.open();
if (camera != null) {
try {
Camera.Parameters parameters = camera.getParameters();
// Set all kind of stuffs here..
parameters.setSceneMode(Camera.Parameters.FLASH_MODE_AUTO);
parameters.setColorEffect(Camera.Parameters.EFFECT_SEPIA); // whatever effect you want
camera.setParameters(parameters);
camera.setPreviewDisplay(surface_holder);
camera.startPreview();
} catch (IOException exception) {
camera.release();
camera = null;
}
}

Setting Parameters.FLASH_MODE_TORCH doesn't work on Droid X 2.3

I am writing an app that sets the flash mode to torch. I have been testing the application on my Droid X, and the LED light does not come on. I tried it on a Droid Incredible and it worked fine. I can't figure out what the problem is. Here is part of my code for turning on torch mode.
Camera mCamera = Camera.open();
Camera.Parameters params = mCamera.getParameters();
if(params.getFlashMode() != null){
params.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
}
mCamera.setParameters(params);
I have added mCamera.startPreview(); because I read that should make a difference, but it doesn't. I also made a list of available flash modes and displayed them to the screen to make sure that my Droid X does have torch mode, and it was in the list. I even created a new application from code I found online that turns the LED flash on and off with a button. Again it worked fine on the Droid Incredible but not the Droid X. Is there something I am missing to get this to run on the Droid X, or could it be something with Gingerbread? The Droid X is running Gingerbread and the Droid Incredible is running FroYo.
There are quite a few quirks when setting FLASH_MODE_TORCH.
Often you need to start a camera preview:
Camera mCamera = Camera.open();
mCamera.startPreview();
Camera.Parameters params = mCamera.getParameters();
if(params.getFlashMode() != null){
params.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
}
mCamera.setParameters(params);
That may resolve it on some phones, other phones also require the preview to be drawn to a SurfaceView. This can be done by implementing SurfaceHolder.Callback interface in your activity.
See an example here.
It could be that the Droid X doesn't support Torch Mode. Try something like this:
List<String> pList = camera.getParameters().getSupportedFlashModes();
if (pList.contains(Parameters.FLASH_MODE_TORCH))
parameters.setFlashMode(Parameters.FLASH_MODE_TORCH);
camera.setParameters(parameters);
Refer to Issue 191453:
SurfaceTexture mDummy = new SurfaceTexture(1); // any int argument will do
camera.setPreviewTexture(mDummy);
camera.startPreview();
The only thing I found that works on the Droid X is the code presented by Siddhpura Amit part way down the page in this answer Use camera flashlight in Android. He checks the manufacturer and checks to see if it contains the string "motorola." If so, he has special code that can switch the camera Flash LED on or off. I can verify that it does work as I have a Motorola Droid X.

Camera display doesn't maintain aspect ratio/seems skewed

I'm running into an issue with camera input in Android. After searching over the internet for half a day I'm not getting any further.
Wat I want to achieve at this stage is correctly displaying the current camera input. Nothing more and nothing less for now. When holding the device in landscape mode, all seems fine. However as soon as I switch the device to portrait the display seems to be horizontally scaled in order to match the width of the screen on the device.
In order to clarify this issue a bit more, I've attached two photographs:
Landscape (looks correct)
Portrait (looks incorrect)
It seems like this issue also occurs with the camera example from the API examples, but it doesn't seem to occur when I use the camera application from my device. So clearly something else is happening there.
The code that I'm using is based on examples that can be found over the internet and has no modifications:
class Preview extends SurfaceView implements SurfaceHolder.Callback {
SurfaceHolder mHolder;
Camera mCamera;
Preview(Context context) {
super(context);
mHolder = getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder) {
mCamera = Camera.open();
try {
mCamera.setPreviewDisplay(holder);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
mCamera.stopPreview();
mCamera = null;
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewSize(w, h);
mCamera.setParameters(parameters);
mCamera.startPreview();
}
}
The API examples make use of a method "getOptimalPreviewSize(...)" which sounds like the method I need, but that does not change anything. I left it out here in order to be as brief as possible.
Am I missing something obvious or is this the expected behavior?
Hopefully someone can point me in the correct direction.
Thanks in advance!
Paul
Okay, I just found the answer to my own question.
The way I solved it was by going fullscreen with my application:
requestWindowFeature(Window.FEATURE_NO_TITLE);
This makes a little bit of sense, as I guess we can not use just any resolution as the preview size on the camera. I guess it will internally snap to the closest allowed resolution/aspect ratio and it doesn't do any smart things like cropping the image to match the requested resolution while maintaining aspect ratio. In my case I was displaying a title bar while the source image was fullscreen and then downsized to fit on the screen.
I think it is kind of stupid that the aspect ratio is not maintained and images are not cropped by default,

Categories

Resources