I am facing a problem in a custom camera application. With the flash function turned ON, the phone takes the 1st photo with flash, but on the 2nd photo it doesn't use the flash.
flashCameraButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (isPressed) {
flashCameraButton.setBackgroundDrawable(getResources().getDrawable(R.drawable.onflash));
flashOnButton();
} else if (isPressed) {
flashCameraButton.setBackgroundDrawable(getResources().getDrawable(R.drawable.offflash));
isPressed = !isPressed;
flashOffButton();
} else
flashCameraButton.setBackgroundDrawable(getResources().getDrawable(R.drawable.onflash));
flashOnButton();
}
});
private void flashOnButton() {
if (camera != null) {
try {
Camera.Parameters param = camera.getParameters();
param.setFlashMode(!flashmode ? Camera.Parameters.FLASH_MODE_ON
: Camera.Parameters.FLASH_MODE_ON);
camera.setParameters(param);
flashmode = !flashmode;
} catch (Exception e) {
// TODO: handle exception
}
}
}
private void flashOffButton() {
if (camera != null) {
try {
Camera.Parameters param = camera.getParameters();
param.setFlashMode(!flashmode ? Camera.Parameters.FLASH_MODE_OFF
: Camera.Parameters.FLASH_MODE_OFF);
camera.setParameters(param);
flashmode = !flashmode;
} catch (Exception e) {
// TODO: handle exception
}
}
}
Take a look at the code below. You can do something similar to it:
btnSwitch.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (isFlashOn) {
// turn off flash
//change the picture
turnOffFlash();
} else {
// turn on flash
//change the picture
turnOnFlash();
}
}
});
}
// Get the camera
private void getCamera() {
if (camera == null) {
try {
camera = Camera.open();
params = camera.getParameters();
} catch (RuntimeException e) {
Log.e("Camera Error. Failed to Open. Error: ", e.getMessage());
}
}
}
// Turning On flash
private void turnOnFlash() {
if (!isFlashOn) {
if (camera == null || params == null) {
return;
}
params = camera.getParameters();
params.setFlashMode(Parameters.FLASH_MODE_TORCH);
camera.setParameters(params);
camera.startPreview();
isFlashOn = true;
}
}
// Turning Off flash
private void turnOffFlash() {
if (isFlashOn) {
if (camera == null || params == null) {
return;
}
params = camera.getParameters();
params.setFlashMode(Parameters.FLASH_MODE_OFF);
camera.setParameters(params);
camera.stopPreview();
isFlashOn = false;
}
}
What we are doing here is checking if the Flash is ON or OFF, if it is ON, we call the method turnOffFlash() to turn it off and if it is OFF we call the method turnOnFlash() to turn it on.
Related
I want to capture image previewed in surfaceView.Capturing time is every 42 millisecond.While capturing I want to send these images to the server as byteArray at this moment.For security reason, photo cant is saved to sd.I must use this for making a video call.Can anyone help me?Pls
Button take;
Camera camera;
SurfaceView surfaceView;
SurfaceHolder surfaceHolder;
Camera.PictureCallback jpegCallback;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
checkPermission();
surfaceView = (SurfaceView) findViewById(R.id.surface);
surfaceHolder = surfaceView.getHolder();
take = (Button) findViewById(R.id.take);
take.setOnClickListener(this);
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
surfaceHolder.addCallback(this);
// deprecated setting, but required on Android versions prior to 3.0
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
jpegCallback = new Camera.PictureCallback() {
public void onPictureTaken(byte[] data, Camera camera) {
FileOutputStream outStream = null;
try {
outStream = new FileOutputStream(String.format("/sdcard/%d.jpg", System.currentTimeMillis()));
outStream.write(data);
outStream.close();
Log.d("Log", "onPictureTaken - wrote bytes: " + data.length);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
Toast.makeText(getApplicationContext(), "Picture Saved", Toast.LENGTH_SHORT).show();
refreshCamera();
}
};
}
public void captureImage() throws IOException {
//take the picture
camera.takePicture(null, null, jpegCallback);
}
#Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
try {
// open the camera
camera = Camera.open();
} catch (RuntimeException e) {
// check for exceptions
System.err.println(e);
return;
}
Camera.Parameters param;
param = camera.getParameters();
// modify parameter
List<Camera.Size> sizes = param.getSupportedPreviewSizes();
Camera.Size selected = sizes.get(0);
param.setPreviewSize(selected.width,selected.height);
camera.setParameters(param);
try {
// The Surface has been created, now tell the camera where to draw
// the preview.
camera.setDisplayOrientation(90);
camera.setPreviewDisplay(surfaceHolder);
camera.startPreview();
} catch (Exception e) {
// check for exceptions
System.err.println(e);
return;
}
}
#Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
// Now that the size is known, set up the camera parameters and begin
// the preview.
refreshCamera();
}
#Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
// stop preview and release camera
camera.stopPreview();
camera.release();
camera = null;
}
public void refreshCamera() {
if (surfaceHolder.getSurface() == null) {
// preview surface does not exist
return;
}
// set preview size and make any resize, rotate or
// reformatting changes here
// start preview with new settings
try {
camera.setPreviewDisplay(surfaceHolder);
camera.startPreview();
} catch (Exception e) {
}
}
private void requestPermission() {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, 1);
}
private boolean checkPermission() {
int result = ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA);
if (result == PackageManager.PERMISSION_GRANTED) {
return true;
} else {
return false;
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
switch (requestCode) {
case 1:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
} else {
}
break;
}
}
#Override
public void onPointerCaptureChanged(boolean hasCapture) {
}
#Override
public void onClick(View v) {
switch (v.getId()){
case R.id.take:{
try {
captureImage();
} catch (IOException e) {
e.printStackTrace();
}
break;
}
}
}
So while previewing in SurfaceView I must get every 42 millis photo as byteArray and send it
I found solution to my problem. I have fixed it through setPreviewCallbackWithBuffer an onPreviewFrame.There is no need neither handler nor timer...
private Camera camera;
private SurfaceView surfaceView;
private SurfaceHolder surfaceHolder;
private ImageView endCallBtn;
private ImageView micBtn;
private ImageView visibilityBtn;
private ImageView cameraBtn;
private Boolean clickedForMic = false;
private Boolean clickedForCamera = false;
private Boolean clickedForVisiblity = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_video_call);
surfaceView = (SurfaceView) findViewById(R.id.surfaceView);
surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(this);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_NORMAL);
if (Build.VERSION.SDK_INT >= 23) {
if (checkPermission()) {
Log.e("permission", "Permission already granted.");
} else {
requestPermission();
}
}
endCallBtn = (ImageView) findViewById(R.id.endCallBtn);
endCallBtn.setOnClickListener(this);
micBtn = (ImageView) findViewById(R.id.micBtn);
micBtn.setImageResource(R.drawable.ic_mic_white_48px);
micBtn.setOnClickListener(this);
visibilityBtn = (ImageView) findViewById(R.id.visibilityBtn);
visibilityBtn.setImageResource(R.drawable.ic_visibility_white_48px);
visibilityBtn.setOnClickListener(this);
cameraBtn = (ImageView) findViewById(R.id.cameraBtn);
cameraBtn.setImageResource(R.drawable.ic_camera_rear_white_48px);
cameraBtn.setOnClickListener(this);
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.cameraBtn: {
if (clickedForCamera == false) {
if (clickedForVisiblity == true) {
Toast.makeText(VideoCallActivity.this, "Видимость камеры заблокирована", Toast.LENGTH_SHORT).show();
} else {
stopCamera();
startCameraBack();
cameraBtn.setImageResource(R.drawable.ic_camera_front_white_48px);
clickedForCamera = true;
}
} else {
if (clickedForVisiblity == true) {
Toast.makeText(VideoCallActivity.this, "Видимость камеры заблокирована", Toast.LENGTH_SHORT).show();
} else {
stopCamera();
startCameraFront();
cameraBtn.setImageResource(R.drawable.ic_camera_rear_white_48px);
clickedForCamera = false;
}
}
break;
}
case R.id.micBtn: {
if (clickedForMic == false) {
micBtn.setImageResource(R.drawable.ic_mic_off_white_48px);
micBtn.setColorFilter(Color.parseColor("#00897B"));
clickedForMic = true;
} else {
micBtn.setImageResource(R.drawable.ic_mic_white_48px);
micBtn.setColorFilter(Color.parseColor("#ffffff"));
clickedForMic = false;
}
break;
}
case R.id.endCallBtn: {
stopCamera();
finish();
overridePendingTransition(R.anim.window3, R.anim.window4);
break;
}
case R.id.visibilityBtn: {
if (clickedForVisiblity == false) {
camera.stopPreview();
visibilityBtn.setImageResource(R.drawable.ic_visibility_off_white_48px);
visibilityBtn.setColorFilter(Color.parseColor("#00897B"));
clickedForVisiblity = true;
} else {
camera.startPreview();
visibilityBtn.setImageResource(R.drawable.ic_visibility_white_48px);
visibilityBtn.setColorFilter(Color.parseColor("#ffffff"));
clickedForVisiblity = false;
}
break;
}
}
}
private void requestPermission() {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, 1);
}
private boolean checkPermission() {
int result = ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA);
if (result == PackageManager.PERMISSION_GRANTED) {
return true;
} else {
return false;
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
switch (requestCode) {
case 1:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
} else {
}
break;
}
}
private void stopCamera() {
camera.stopPreview();
camera.release();
}
private void startCameraFront() {
if (checkPermission()) {
try {
camera = Camera.open(Camera.CameraInfo.CAMERA_FACING_FRONT);
} catch (Exception e) {
return;
}
Camera.Parameters param;
camera.setDisplayOrientation(90);
param = camera.getParameters();
param.setPreviewFrameRate(24);
param.setPreviewFpsRange(22000, 30000);
camera.setParameters(param);
try {
camera.setPreviewDisplay(surfaceHolder);
} catch (Exception e) {
return;
}
Log.v("CameraTest", "Camera PreviewFrameRate = " + camera.getParameters().getPreviewFrameRate());
Camera.Size previewSize = camera.getParameters().getPreviewSize();
int dataBufferSize = (int) (previewSize.height * previewSize.width *
(ImageFormat.getBitsPerPixel(camera.getParameters().getPreviewFormat()) / 8.0));
camera.addCallbackBuffer(new byte[dataBufferSize]);
camera.addCallbackBuffer(new byte[dataBufferSize]);
camera.addCallbackBuffer(new byte[dataBufferSize]);
camera.setPreviewCallbackWithBuffer(new Camera.PreviewCallback() {
private long timestamp = 0;
public synchronized void onPreviewFrame(byte[] data, Camera camera) {
//Log.v("CameraTest", "Time Gap = " + (System.currentTimeMillis() - timestamp));
Log.v("CameraTest", " data: " + String.valueOf(data.length));
timestamp = System.currentTimeMillis();
try {
camera.addCallbackBuffer(data);
} catch (Exception e) {
Log.e("CameraTest", "addCallbackBuffer error");
return;
}
return;
}
});
camera.startPreview();
}
}
private void startCameraBack() {
if (checkPermission()) {
try {
camera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);
} catch (Exception e) {
return;
}
Camera.Parameters param;
camera.setDisplayOrientation(90);
param = camera.getParameters();
//modify parameter
param.setPreviewFrameRate(30);
camera.setParameters(param);
try {
camera.setPreviewDisplay(surfaceHolder);
camera.startPreview();
} catch (Exception e) {
Log.d("Problema", e.toString());
return;
}
}
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
startCameraFront();
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
I am fairly new to android and I am trying to make flash light blink when the button is pressed. The code i am using is for simply switching on and off the flashlight. I am trying to add another button which will make the flashlight blink in a certain pattern. Is it possible that we set the pattern parameters just like we do in vibrating in a pattern
My code is as below:
public class MainActivity extends Activity {
private InterstitialAd interstitial;
private Camera camera;
ImageButton flashLightSwitchImage;
private boolean isFlashlightOn;
Parameters params;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
flashLightSwitchImage = (ImageButton) findViewById(R.id.flashlight_switch);
boolean isCameraFlash = getApplicationContext().getPackageManager()
.hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH);
if (!isCameraFlash) {
showCameraAlert();
} else {
camera = Camera.open();
params = camera.getParameters();
}
flashLightSwitchImage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
if (isFlashlightOn) {
setFlashLightOff();
} else {
setFlashLightOn();
}
}
});
}
private void showCameraAlert() {
new AlertDialog.Builder(this)
.setTitle("Error loadin Flash!")
.setMessage("Flash Not Available in this Device")
.setPositiveButton(android.R.string.yes,
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog,
int which) {
// TODO Auto-generated method stub
finish();
}
}).setIcon(android.R.drawable.ic_dialog_alert).show();
}}}}
This code right here is working fine but it simply switches on and off the flashlight.
I want to introduce another button which makes the flash light blink in a pattern.
Try this code for blinking the flash. You can edit this to support your required pattern
String myString = "01010101010101";
long blinkDelay 50; //Delay in ms
for (int i = 0; i < myString.length(); i++) {
if (myString.charAt(i) == '0') {
params.setFlashMode(Parameters.FLASH_MODE_ON);
} else {
params.setFlashMode(Parameters.FLASH_MODE_OFF);
} try {
Thread.sleep(blinkDelay);
} catch (InterruptedException e) {
e.printStackTrace();
} }
use this code on the listener of your button
getCamera();
Toast.makeText(context, "Ringing", Toast.LENGTH_SHORT).show();
String myString = "01010101010010101010101";
long blinkDelay =500;
for (int i = 0; i < myString.length(); i++) {
if (myString.charAt(i) == '0') {
//params.setFlashMode(Camera.Parameters.FLASH_MODE_ON);
turnOnFlash();
} else {
// params.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
turnOffFlash();
}
try {
Thread.sleep(blinkDelay);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
and define this code outside on create method
private void getCamera() {
if (camera == null) {
try {
camera = Camera.open();
params = camera.getParameters();
} catch (RuntimeException e) {
// Log.d("Camera Error. Failed to Open. Error: ", e.getMessage());
}
}
}
/*
* Turning On flash
*/
private void turnOnFlash() {
if (!isFlashOn) {
if (camera == null || params == null) {
return;
}
// play sound
// playSound();
params = camera.getParameters();
params.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
camera.setParameters(params);
camera.startPreview();
isFlashOn = true;
// changing button/switch image
// toggleButtonImage();
}
}
/*
* Turning Off flash
*/
private void turnOffFlash() {
if (isFlashOn) {
if (camera == null || params == null) {
return;
}
// play sound
//playSound();
params = camera.getParameters();
params.setFlashMode(android.hardware.Camera.Parameters.FLASH_MODE_OFF);
camera.setParameters(params);
camera.stopPreview();
isFlashOn = false;
// changing button/switch image
// toggleButtonImage();
}}
Update
Check out my answer
Original
I'm trying to turn on the camera flashlight on the LG Revolution within my program. I use the torch mode method which works on most phones but not on LG phone. Does anyone know how to get it to work on LG's or specifically the Revolution?
Here's my manifest:
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-permission android:name="android.permission.FLASHLIGHT"/>
Here's my current code:
public Camera camera = Camera.open();
public Camera.Parameters Flash = camera.getParameters();
With my on create:
Flash.setFlashMode("torch");
Parameters p = camera.getParameters();
camera.setParameters(Flash);
camera.startPreview();
I've seen people use an auto focus but i don't know if that would work.
I thought I would update this with some bullet prof code that works on almost all 4.0+ devices.
public void turnOn() {
camera = Camera.open();
try {
Parameters parameters = camera.getParameters();
parameters.setFlashMode(getFlashOnParameter());
camera.setParameters(parameters);
camera.setPreviewTexture(new SurfaceTexture(0));
camera.startPreview();
camera.autoFocus(this);
} catch (Exception e) {
// We are expecting this to happen on devices that don't support autofocus.
}
}
private String getFlashOnParameter() {
List<String> flashModes = camera.getParameters().getSupportedFlashModes();
if (flashModes.contains(FLASH_MODE_TORCH)) {
return FLASH_MODE_TORCH;
} else if (flashModes.contains(FLASH_MODE_ON)) {
return FLASH_MODE_ON;
} else if (flashModes.contains(FLASH_MODE_AUTO)) {
return FLASH_MODE_AUTO;
}
throw new RuntimeException();
}
The real key is setting that fake SurfaceTexture so that the preview will actually start. Turning it off is very easy as well
public void turnOff() {
try {
camera.stopPreview();
camera.release();
camera = null;
} catch (Exception e) {
// This will happen if the camera fails to turn on.
}
}
It seems like the developer of the Tiny Flashlight + LED app on the Android Market figured out how to make the flashlight work on LG Revolution.
Maybe you can contact him and ask?
You can also check the permissions he is using in his app to try to make your app work!
Good luck!
Test this :
if(camera == null){
camera = Camera.open();
parameters = camera.getParameters();
List<String> flashModes = parameters.getSupportedFlashModes();
if(flashModes != null && flashModes.contains(Parameters.FLASH_MODE_TORCH)){
//appareil supportant le mode torch
parameters.setFlashMode(Parameters.FLASH_MODE_TORCH);
camera.setParameters(parameters);
} else if (flashModes != null && flashModes.contains(Parameters.FLASH_MODE_ON)){
//spécial samsung
parameters.setFlashMode(Parameters.FLASH_MODE_ON);
camera.setParameters(parameters);
camera.startPreview();
camera.autoFocus(new AutoFocusCallback() {
public void onAutoFocus(boolean success, Camera camera) { }
});
} else {
parameters.setFlashMode(Parameters.FLASH_MODE_OFF);
camera.setParameters(parameters);
}
parameters.setFlashMode( Parameters.FLASH_MODE_OFF );
camera.setParameters(parameters);
camera.release();
camera = null;
} catch (RuntimeException e) {}
}//if
This worked well for LG Nexus:
camera = Camera.open();
camera.setPreviewTexture(new SurfaceTexture(0));
camera.setParameters(p);
camera.startPreview();
/*TESTED LG G4 */
public void flashOnOff(){
List<String> flashModes = parameter001.getSupportedFlashModes();
if(flashModes != null && flashModes.contains(Parameters.FLASH_MODE_TORCH)){
//appareil supportant le mode torch
parameter001.setFlashMode(Parameters.FLASH_MODE_TORCH);
mCamera.setParameters(parameter001);
} else if (flashModes != null && flashModes.contains(Parameters.FLASH_MODE_ON)){
//spécial samsung
parameter001.setFlashMode(Parameters.FLASH_MODE_ON);
mCamera.setParameters(parameter001);
mCamera.autoFocus(new AutoFocusCallback() {
public void onAutoFocus(boolean success, Camera camera) { }
});
} else {
parameter001.setFlashMode(Parameters.FLASH_MODE_OFF);
mCamera.setParameters(parameter001);
}
if (!isFlashOn) {
if (mCamera == null || parameter001 == null) {
return;
}
parameter001 = mCamera.getParameters();
parameter001.setFlashMode(Parameters.FLASH_MODE_TORCH);
mCamera.setParameters(parameter001);
try {
mCamera.setPreviewTexture(new SurfaceTexture(0));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mCamera.startPreview();
isFlashOn = true;
// changing button/switch image
}else if (isFlashOn) {
if (mCamera == null || parameter001 == null) {
return;
}
parameter001 = mCamera.getParameters();
parameter001.setFlashMode(Parameters.FLASH_MODE_OFF);
mCamera.setParameters(parameter001);
mCamera.stopPreview();
isFlashOn = false;
}
}
I've run into such a problem. The problem is that when I use onPictureTaken function the light is automatically go down. What should I do with it? I want the light not to turn off.
Photo :
if (v == shot)
{
camera.takePicture (null, null, null, this);
}
flashlight:
if (prefs.getBoolean (getString (R.string.torch), false))
{
Parameters params = camera.getParameters ();
params.setFlashMode (Parameters.FLASH_MODE_TORCH);
camera.setParameters (params);
}
#Override
public void surfaceCreated(SurfaceHolder holder)
{
try
{
camera.setPreviewCallback(this);
camera.setPreviewDisplay(holder);
Camera.Parameters p = camera.getParameters();
p.setPictureSize(1024, 768);
p.setPictureFormat (PixelFormat.RGB_565);
camera.setParameters(p);
}
catch (IOException e)
{
e.printStackTrace();
}
LayoutParams lp = preview.getLayoutParams();
if (this.getResources().getConfiguration().orientation != Configuration.UI_MODE_TYPE_CAR)
{
camera.setDisplayOrientation(90);
}
else
{
camera.setDisplayOrientation(0);
}
preview.setLayoutParams(lp);
camera.startPreview();
return;
}
#Override
protected void onPause()
{
if (camera != null)
{
camera.setPreviewCallback(null);
camera.stopPreview();
camera.release();
camera = null;
}
super.onPause();
return ;
}
protected void onResume()
{
super.onResume();
camera = Camera.open();
}
If I use only CAMERA_FACING_BACK or CAMERA_FACING_FRONT all works fine.
I have trouble with switch from CAMERA_FACING_BACK to CAMERA_FACING_FRONT.
My code snippet:
public class PhotoCameraActivity extends Activity implements OnClickListener {
private SurfaceView cameraView;
private Button turnButton;
private Camera camera = null;
private Callback listener;
private static int camId = Camera.CameraInfo.CAMERA_FACING_BACK;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.photo_camera_main);
prepareActivity();
}
private void prepareActivity() {
cameraView = (SurfaceView) findViewById(R.id.photo_camera_surface_view);
turnButton = (ImageButton) findViewById(R.id.turn_button);
turnButton.setOnClickListener(this);
}
#Override
public void onClick(View v) {
if (v.equals(turnButton)) {
if (Camera.getNumberOfCameras() > 1 && camId < Camera.getNumberOfCameras() - 1) {
startCamera(camId + 1);
} else {
startCamera(Camera.CameraInfo.CAMERA_FACING_BACK);
}
}
}
#Override
protected void onResume() {
startCamera(camId);
super.onResume();
}
#Override
protected void onPause() {
stopCamera();
super.onPause();
}
private void startCamera(int cameraId) {
if (camera != null) {
stopCamera();
}
holder = cameraView.getHolder();
listener = new Callback() {
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
try {
camera.setPreviewDisplay(holder);
camera.startPreview();
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}
};
holder.addCallback(listener);
camId = cameraId;
camera = Camera.open(cameraId);
Camera.Parameters params = camera.getParameters();
if (cameraId == Camera.CameraInfo.CAMERA_FACING_BACK) {
params.setPreviewSize(1280, 800);
} else {
params.setPreviewSize(640, 480);
}
camera.setParameters(params);
}
private void stopCamera(){
System.out.println("stopCamera method");
if (camera != null){
camera.stopPreview();
camera.setPreviewCallback(null);
camera.release();
camera = null;
holder.removeCallback(listener);
holder = null;
}
}
}
In onCreate() of my activity I add the following onClick listener to a button overlayed on my Preview SurfaceView (there are numerous example on the web for previewing):
ImageButton useOtherCamera = (ImageButton) findViewById(R.id.useOtherCamera);
//if phone has only one camera, hide "switch camera" button
if(Camera.getNumberOfCameras() == 1){
useOtherCamera.setVisibility(View.INVISIBLE);
}
else {
useOtherCamera.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (inPreview) {
camera.stopPreview();
}
//NB: if you don't release the current camera before switching, you app will crash
camera.release();
//swap the id of the camera to be used
if(currentCameraId == Camera.CameraInfo.CAMERA_FACING_BACK){
currentCameraId = Camera.CameraInfo.CAMERA_FACING_FRONT;
}
else {
currentCameraId = Camera.CameraInfo.CAMERA_FACING_BACK;
}
camera = Camera.open(currentCameraId);
//Code snippet for this method from somewhere on android developers, i forget where
setCameraDisplayOrientation(CameraActivity.this, currentCameraId, camera);
try {
//this step is critical or preview on new camera will no know where to render to
camera.setPreviewDisplay(previewHolder);
} catch (IOException e) {
e.printStackTrace();
}
camera.startPreview();
}
On my test device the back camera has an ID of 0 and the front has an id of 1. I suggest using Camera.CameraInfo static variables for your camera id's rather than hard-coding values. I am sure that will only cause issues on other devices.
I restart Activity with cameraId = 2 and this is working.
I removed and re-added SurfaceView in my layout and so it worked.
public void switchCamera(int cameraType)
{
if(context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT))
{
if(Camera.getNumberOfCameras() > cameraType)
{
// Set selected camera
this.cameraType = cameraType;
}
else
{
// Set default camera (Rear)
this.cameraType = Camera.CameraInfo.CAMERA_FACING_BACK;
}
if(mCamera != null)
{
// Destroy previuos Holder
surfaceDestroyed(holder);
holder.removeCallback(this);
// Remove and re-Add SurfaceView
ViewGroup rootLayout = (ViewGroup) surface.getParent();
rootLayout.removeView(surface);
surface = new SurfaceView(context);
holder = surface.getHolder();
holder.addCallback(this);
rootLayout.addView(surface, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
}
}
}
I have to remove the surface preview before adding a new one:
if (mPreview != null) {
mPreview.surfaceDestroyed(mPreview.getHolder());
mPreview.getHolder().removeCallback(mPreview);
mPreview.destroyDrawingCache();
FrameLayout preview = (FrameLayout) view.findViewById(R.id.camera_frame);
preview.removeView(mPreview);
mPreview.mCamera = null;
mPreview = null;
}
//then add your preview
Use this code:
if (mCamera != null) {
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
//swap the id of the camera to be used
if (currentCameraId == Camera.CameraInfo.CAMERA_FACING_BACK)
currentCameraId = Camera.CameraInfo.CAMERA_FACING_FRONT;
else
currentCameraId = Camera.CameraInfo.CAMERA_FACING_BACK;
try {
mCamera = Camera.open(currentCameraId);
mCamera.setDisplayOrientation(90);
mCamera.setPreviewDisplay(surfaceHolder);
mCamera.startPreview();
}
catch (Exception e) { e.printStackTrace(); }
try using this:
camera.stopPreview();
if(camera != null)
camera.release();
try {
camera = Camera.open(/*new id*/);
camera.setPreviewDisplay(holder);
camera.startPreview();
} catch (Exception ex) { ex.printStackTrace(); }