I just started to develop an Android app that needs to use camera features in order to capture images and I want to keep the Flash ALWAYS ON. The problem is that when I start the camera from app the flash only blinks once and stops.
I implemented the camera with Camera class and I used the CameraPreview that extends SurfaceView and implements SurfaceHolder exactly like the example from android developer page: Here
Then I used a FrameLayout to show the camera preview:
// Create an instance of Camera
mCamera = getCameraInstance();
Parameters p = mCamera.getParameters();
p.setFlashMode(Parameters.FLASH_MODE_TORCH);
mCamera.setParameters(p);
// Create our Preview view and set it as the content of our activity.
mPreview = new CameraPreview(this, mCamera);
FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
preview.addView(mPreview);
Everything works good excepting the flash that blinks once and stops.
I tested the app on a Samsung Galaxy S5 with KitKat.
Intent for camera don't fit my needs and Camera2 is excluded.
Thanks!
Found the solution:
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// If your preview can change or rotate, take care of those events here.
// Make sure to stop the preview before resizing or reformatting it.
if (mHolder.getSurface() == null){
// preview surface does not exist
return;
}
// stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception e){
// ignore: tried to stop a non-existent preview
}
// set preview size and make any resize, rotate or
// reformatting changes here
// start preview with new settings
try {
//Turn flash on
Camera.Parameters p = mCamera.getParameters();
p.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
mCamera.setParameters(p);
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e){
Log.d(TAG, "Error starting camera preview: " + e.getMessage());
}
}
Add the code to start the flash in the second try-catch of surfaceChanged method.
Related
So for my Android app, I have created a SurfaceView and assigned it as camera preview and start camera preview using the necessary API's. But now I want to turn the Flashlight ON (kind of act like a Torch) while the preview is working.
Please note that I have seen tons of examples online on how to turn flashlight on and it works as long as I don't call the open camera API. Below is the code -
try
{
CameraManager cameraManager = (CameraManager)context.GetSystemService(Context.CameraService);
if (cameraManager != null)
{
//for the sake of brevity, hardcoded the camera id. 0 is mostly back camera
cameraManager.SetTorchMode(0, true);
}
}
catch (CameraAccessException e)
{
LogUtil.Error("CameraInput", e.ToString());
}
Please note I am testing on Android N and hence the above code works flawlessly. But as soon as I call below line of code, the flash turns off.
Camera camera = Camera.Open(0);
// ...... some code ....//
camera.StartPreview();
When the above 2 lines execute, the flash goes off. Is this a know behaviour like where camera takes exclusive lock over flash hardware and resets it's value to default.
I tried reversing the above code i.e calling the Camera Open API being called first and then setting the flash. On that I get CameraAccessException , camera already in use.
What am i missing ?
Try this while previewing on SurfaceView
params = camera.getParameters();
params.setFlashMode(Parameters.FLASH_MODE_ON);
camera.setParameters(params);
Remember that If you want to use it as flashlight you can do:
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
If not, to turn flash on which will come out when you take the picture, you use:
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_ON);
Happy Coding!
Figured out how to torch on and off while camera is previewing. On button click to on/off the light, use this code:
//at some other function where camera is initialised and start preview
//...
Camera camera = Camera.open();
camera.startPreview();
//...
boolean lightOn = false;
//...
buttonLight.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Camera.Parameters p = camera.getParameters();
if (!lightOn) {
lightOn = true;
p.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
camera.setParameters(p);
} else {
lightOn = false;
p.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
camera.setParameters(p);
}
}
});
Happy Coding! :D
I've used the camera native app through my app for taking picture. I've used the below code for display the camera app in portrait mode only.
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(f));
takePictureIntent.putExtra(MediaStore.EXTRA_SCREEN_ORIENTATION,
ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
startActivityForResult(takePictureIntent, actionCode);
But, it's not working with the above code.
Any suggestions will be appreciated :-)
You can't control the orientation of an external application that you launch, so there is no way to do this.
But you could create your own camera activity.
considering your mCamera as your Camera, you can create your camera activity, set à cameraPReview and set the preview in protrait mode by adding mCamera.setDisplayOrientation(90); before starting preview
here is an example for camera preview in a FrameLayout in potrait mode:
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
public CameraPreview(Context context, Camera camera) {
super(context);
mCamera = camera;
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
// deprecated setting, but required on Android versions prior to 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, now tell the camera where to draw the preview.
try {
if(mCamera!=null){
mCamera.setPreviewDisplay(holder);
mCamera.setDisplayOrientation(90);
mCamera.startPreview();}
} catch (IOException e) {
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
// empty. Take care of releasing the Camera preview in your activity.
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// If your preview can change or rotate, take care of those events here.
// Make sure to stop the preview before resizing or reformatting it.
if (mHolder.getSurface() == null) {
// preview surface does not exist
return;
}
// stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception e) {
// ignore: tried to stop a non-existent preview
}
// set preview size and make any resize, rotate or
// reformatting changes here
// start preview with new settings
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e) {
}
}
and you set the preview from your MainActivity like below :
mPreview = new CameraPreview(getApplicationContext(), camera);
preview.addView(mPreview);
I have used zbar scanner for android and it captures the barcodes quite easily.
But the problem is that on phones which have autofocus, it captures the barcodes too quickly to detect it correctly.
If only it could wait for a few milliseconds more, it could then be able to capture more clearer image and thereby not show "not found" page.
How can I solve this problem?
Is there a provision to delay the focus on the barcode?
Maybe a delay in capturing the image?
Are you talking about the example code, CameraTestActivity.java?
Implement a counter that counts for similar scanning results. If the scanning result remains the same (e.g. for 10 times in a row), we can assume the result is quite reliable.
I really like #Juuso_Ohtonen's reply, and actually just used it in my own reader, however if you want an AutoFocus delay you can create a Camera.AutoFocusCallback object and implement its onAutoFocus method with a .postDelayed. This object is then used on your Camera camera.autoFocus() method.
// Mimic continuous auto-focusing
Camera.AutoFocusCallback autoFocusCB = new Camera.AutoFocusCallback() {
public void onAutoFocus(boolean success, Camera camera) {
autoFocusHandler.postDelayed(doAutoFocus, 1000);
}
};
This section is used in the class that extends SurfaceView, which then implements surfaceChanged();
public CameraPreview(Context context, Camera camera,
PreviewCallback previewCb,
AutoFocusCallback autoFocusCb) {
super(context);
mCamera = camera;
previewCallback = previewCb;
autoFocusCallback = autoFocusCb;
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
// deprecated setting, but required on Android versions prior to 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
/*
* If your preview can change or rotate, take care of those events here.
* Make sure to stop the preview before resizing or reformatting it.
*/
if (mHolder.getSurface() == null) {
// preview surface does not exist
return;
}
// stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception e) {
// ignore: tried to stop a non-existent preview
}
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.setPreviewCallback(previewCallback);
mCamera.startPreview();
mCamera.autoFocus(autoFocusCallback);
} catch (Exception e) {
Log.d("DBG", "Error starting camera preview: " + e.getMessage());
}
}
I've searched all over on the web and I can't find out what that 1001 error is. A few seconds after that I get the camera 100 error but I can't find out what the first error is. Does anyone have any ideas?
I encountered this error as well on my S3. I believe I tracked it down to how the camera preview surface was used by the MediaRecorder. In my case the preview display was getting reset when I was attempting to start recording. I solved it by cleaning out my code and just used the calls to set, start and stop the preview display in the SurfaceView implementation below (from the Android Camera developer guide):
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
public CameraPreview(Context context, Camera camera) {
super(context);
mCamera = camera;
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
// deprecated setting, but required on Android versions prior to 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, now tell the camera where to draw the preview.
try {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e) {
Log.d(TAG, "Error setting camera preview: " + e.getMessage());
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
// empty. Take care of releasing the Camera preview in your activity.
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// If your preview can change or rotate, take care of those events here.
// Make sure to stop the preview before resizing or reformatting it.
if (mHolder.getSurface() == null){
// preview surface does not exist
return;
}
// stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception e){
// ignore: tried to stop a non-existent preview
}
// set preview size and make any resize, rotate or
// reformatting changes here
// start preview with new settings
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e){
Log.d(TAG, "Error starting camera preview: " + e.getMessage());
}
}
}
Just thought I would add a post here for future reference. This issue bothered me for a long time.
It turns out that my problem was caused by an incorrect preview size, although the resolution set was obtained from the getSupportedPictureSize method.
So for example you can get the sizes as follows:
//first entry in list is 1392x1392 for front facing camera on an S3
List<Camera.Size> supportedPictureSizes = params.getSupportedPictureSizes();
Setting this resolution or neglecting to set a picture size alltogether will cause the dreaded error 1001.
If you encounter this on any other device I would recommend trying different picture sizes.
So there was another reason for why I got it on my Galaxy S3. I was using a TextureView to show my camera preview and got this dreaded error when pressing the home button after a successful preview and then entering the app again. In the onResume() function I started up the preview again and found that I had not released the SurfaceTexture instance variable in the onSurfaceTextureDestroyed() function.
I added the release line to this function and it now looks like this and works perfectly:
#Override public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
mSurfaceTexture = null; //This was the offending culprit.
releaseMediaPlayer();
releaseVideoRecorder();
releaseCamera();
return false;
}
In my case, in Samsung S3, the video-size parameter was not set and this led to the 1001 error. Setting the video size on the media recorder using preview size fixed the issue. However, this change may fail on other devices since the parameter may or may not be available/set in all devices. The following code addresses most of the devices:
if(params.get("video-size") != null && params.get("video-size").isEmpty()) {
int videoWidth = params.getPreviewSize().width;
int videoHeight = params.getPreviewSize().height;
mediaRecorder.setVideoSize(videoWidth, videoHeight);
} else {
mediaRecorder.setVideoSize(profile.videoFrameWidth, profile.videoFrameHeight);
}
I am developing on/for a Samsung Galaxy Tab (7inches). My application has to be in portrait mode only, i.e i have locked it to portrait mode in my application and in the device settings. The problem is when i try to rotate the camera preview, it is currently rotated 90 degrees in the wrong direction.
Right now this is my surfaceCreated
public void surfaceCreated(SurfaceHolder holder) {
camera = Camera.open();
try {
camera.setPreviewDisplay(holder);
Camera.Parameters parameters = camera.getParameters();
parameters.setPictureFormat(PixelFormat.JPEG);
parameters.set("orientation", "portrait");
//camera.setDisplayOrientation(90);
parameters.setRotation(90);
camera.setParameters(parameters);
}
catch (IOException exception) {
camera.release();
}
}
The camera.setDisplayOrientation(90) does not seem to be working (it does nothing, which is why i have commented it away). However the parameters.setRotation(90) DOES IN FACT GET THE JOB DONE! but it creates an ugly "stripe" of "flickering colors" along the side of the application. setDisplayOrientation() should work for me, since i am running android api 8 (Froyo 2.2)!!
There is a thread on google about problems pertaining to rotational issues http://code.google.com/p/android/issues/detail?id=1193#c26, but to the best of my knowledge it does not suggest anything for my problem.
Any and all solutions pertaining to this problem will be greatly appreciated! thanks!
This worked for me in Samsung Galaxy tab:
public void surfaceCreated(SurfaceHolder holder)
{
// The Surface has been created, acquire the camera and tell it where to draw.
mCamera = Camera.open();
Parameters params = mCamera.getParameters();
if (this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE)
{
params.set("orientation", "portrait");
mCamera.setDisplayOrientation(90);
}
try
{
mCamera.setPreviewDisplay(holder);
}
catch (IOException exception)
{
mCamera.release();
mCamera = null;
}
}
If your application is designed to only take Portrait photos, then the simplest thing to do is to just rotate the image data after you've taken the photo, and not worry about the camera settings. I'm not sure if the Tab is buggy (I've never tried to rotate the camera preview) but rotating the image after you've taken the shot is very simple... the problem is only if you need to know which way the device was being held when the picture was taken. If that's not a concern for you, then don't fret over it :)
try this. I make this code and test on Galaxy Tab. The code works well
public void surfaceCreated(SurfaceHolder holder) {
camera = Camera.open();
try {
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO)
{
camera.setDisplayOrientation(90);
} else {
Parameters parameters = camera.getParameters();
parameters.setRotation(90);
camera.setParameters(parameters);
}
camera.setPreviewDisplay(holder);
} catch (IOException exception) {
camera.release();
}
}