I am using OpenCV4Android in my project and i am using JavaCameraView. I tried to switch my phone flash light but failed. Here is my attempts.
public class Camera_View extends JavaCameraView {
private static final String TAG = "Camera View";
public boolean isFlashOn = false;
public Camera_View(Context context, AttributeSet attrs) {
super(context, attrs);
}
public List<String> getEffectList() {
return mCamera.getParameters().getSupportedColorEffects();
}
public boolean isEffectSupported() {
return (mCamera.getParameters().getColorEffect() != null);
}
public String getEffect() {
return mCamera.getParameters().getColorEffect();
}
public void setEffect(String effect) {
Camera.Parameters params = mCamera.getParameters();
params.setColorEffect(effect);
mCamera.setParameters(params);
}
public List<Size> getResolutionList() {
return mCamera.getParameters().getSupportedPreviewSizes();
}
public void setResolution(Size resolution) {
disconnectCamera();
mMaxHeight = resolution.height;
mMaxWidth = resolution.width;
connectCamera(getWidth(), getHeight());
}
public Size getResolution() {
return mCamera.getParameters().getPreviewSize();
}
public void switchFlash(boolean flash_on) {
Parameters p = mCamera.getParameters();
if (!flash_on)
p.setFlashMode(Parameters.FLASH_MODE_OFF);
else
p.setFlashMode(Parameters.FLASH_MODE_TORCH);
mCamera.setParameters(p);
}
public void switchFlash() {
Camera tcamera = null;
tcamera = Camera.open();
Parameters p = tcamera.getParameters();
if (isFlashOn)
p.setFlashMode(Parameters.FLASH_MODE_OFF);
else
p.setFlashMode(Parameters.FLASH_MODE_TORCH);
isFlashOn = !isFlashOn;
tcamera.setParameters(p);
}
public void setupCameraFlashLight(boolean flash_on) {
Camera camera = mCamera;
if (camera != null) {
Parameters params = camera.getParameters();
if (params != null) {
if (!flash_on) {
isFlashOn = false;
params.setFlashMode(Parameters.FLASH_MODE_OFF);
camera.setParameters(params);
camera.startPreview();
} else {
isFlashOn = true;
params.setFlashMode(Parameters.FLASH_MODE_TORCH);
camera.setParameters(params);
camera.startPreview();
}
}
}
}
I try to switch the flash light on or off using three method. But seem likes what i found online is for nativeCameraView but i am using JavaCameraView. When i try to run the coding, i got java.lang.NullPointerException.
Can anyone help me?
Related
I'm writing a code using opencv video streaming, and i want to open the camera flash when first opening the camera. i have implemented a new class that is extended from JavaCameraView but the app crashes when i cal this line:
mOpencvCameraView.setEffect(Camera.Parameters.FLASH_MODE_ON);
the Class is As the Following:
My Code
public class CameraCustomize extends JavaCameraView implements Camera.PictureCallback {
private String mPictureFileName;
public CameraCustomize(Context context, AttributeSet attrs) {
super(context, attrs);
}
public List<String> getEffectList() {
return mCamera.getParameters().getSupportedFlashModes();
}
public boolean isEffectSupported() {
return (mCamera.getParameters().getFlashMode() != null);
}
public String getEffect() {
return mCamera.getParameters().getFlashMode();
}
public void setEffect(String effect) {
mCamera.getParameters();// here where i get the Error
Camera.Parameters params = mCamera.getParameters();
params.setFlashMode(effect);
mCamera.setParameters(params);
}
public List<Camera.Size> getResolutionList() {
return mCamera.getParameters().getSupportedPreviewSizes();
}
public void setResolution(int w, int h) {
disconnectCamera();
mMaxHeight = h;
mMaxWidth = w;
connectCamera(getWidth(), getHeight());
}
public Camera.Size getResolution() {
return mCamera.getParameters().getPreviewSize();
}
public void takePicture(final String fileName) {
this.mPictureFileName = fileName;
// Postview and jpeg are sent in the same buffers if the queue is not empty when performing a capture.
// Clear up buffers to avoid mCamera.takePicture to be stuck because of a memory issue
mCamera.setPreviewCallback(null);
// PictureCallback is implemented by the current class
mCamera.takePicture(null, null, this);
}
#Override
public void onPictureTaken(byte[] data, Camera camera) {
// The camera preview was automatically stopped. Start it again.
mCamera.startPreview();
mCamera.setPreviewCallback(this);
// Write the image in a file (in jpeg format)
try {
FileOutputStream fos = new FileOutputStream(mPictureFileName);
fos.write(data);
fos.close();
} catch (java.io.IOException e) {
Log.e("PictureDemo", "Exception in photoCallback", e);
}
}
public void cameraRelease() {
if(mCamera != null){
mCamera.release();
}
}
}
Please any one can help me, or suggest another way to start the Camera Flash.
Thank you in Advanced.
I found the solution by applying this class from this link Using Camera LED Flash with OpenCV on Android
it's just worked perfectly :)
Here is the Class that i've implemented:
private static final String TAG = "Sample::Tutorial2View";
private Context my reference;
private static boolean isFlashLightON = false;
public Tutorial2View(Context context, AttributeSet attrs) {
super(context, attrs);
this.myreference = context;
}
public List<String> getEffectList() {
return mCamera.getParameters().getSupportedColorEffects();
}
public boolean isEffectSupported() {
return (mCamera.getParameters().getColorEffect() != null);
}
public String getEffect() {
return mCamera.getParameters().getColorEffect();
}
public void setEffect(String effect) {
Camera.Parameters params = mCamera.getParameters();
params.setColorEffect(effect);
mCamera.setParameters(params);
}
public List<Size> getResolutionList() {
return mCamera.getParameters().getSupportedPreviewSizes();
}
public void setResolution(Size resolution) {
disconnectCamera();
mMaxHeight = resolution.height;
mMaxWidth = resolution.width;
connectCamera(getWidth(), getHeight());
}
public Size getResolution() {
return mCamera.getParameters().getPreviewSize();
}
// Setup the camera
public void setupCameraFlashLight() {
Camera camera = mCamera;
if (camera != null) {
Parameters params = camera.getParameters();
if (params != null) {
if (isFlashLightON) {
isFlashLightON = false;
params.setFlashMode(Parameters.FLASH_MODE_OFF);
camera.setParameters(params);
camera.startPreview();
} else {
isFlashLightON = true;
params.setFlashMode(Parameters.FLASH_MODE_TORCH);
camera.setParameters(params);
camera.startPreview();
}
}
}
}
I want to make the camera light flash. My code will make it flash just fine of a single button press but if I hit the button again before it has finished flashing it will crash my app. I believe I need to somehow check to see if it is still flashing before I try to start the flash again.
public class BlinkBack {
public static void blink(MainActivity ma){
if (ma.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH)){
final Camera mCamera = Camera.open();
new CountDownTimer(5000, 100) {
int counter = 0;
public void onTick(long millisUntilFinished) {
if (counter % 2 == 0) {
Camera.Parameters params = mCamera.getParameters();
params.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
mCamera.setParameters(params);
mCamera.startPreview();
}
else {
Camera.Parameters params = mCamera.getParameters();
params.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
mCamera.setParameters(params);
mCamera.stopPreview();
}
counter++;
}
public void onFinish() {
Camera.Parameters params = mCamera.getParameters();
params.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
mCamera.setParameters(params);
mCamera.stopPreview();
mCamera.release();
}
}.start();
}
}
}
I found my own answer. final Camera mCamera = Camera.open(); has an unchecked RunTimeException so I just ate that exception with a try catch and it fixed it
public class BlinkBack {
public static void blink(MainActivity ma){
if (ma.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH)){
try {
final Camera mCamera = Camera.open();
new CountDownTimer(5000, 100) {
int counter = 0;
public void onTick(long millisUntilFinished) {
if (counter % 2 == 0) {
Camera.Parameters params = mCamera.getParameters();
params.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
mCamera.setParameters(params);
mCamera.startPreview();
}
else {
Camera.Parameters params = mCamera.getParameters();
params.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
mCamera.setParameters(params);
mCamera.stopPreview();
}
counter++;
}
public void onFinish() {
Camera.Parameters params = mCamera.getParameters();
params.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
mCamera.setParameters(params);
mCamera.stopPreview();
mCamera.release();
}
}.start();
}
catch (Exception e) {
e.printStackTrace();
}
}
}
}
How I can turn on and turn off camera light on ImageButton..
This is my code
public void liBtn(View v)
{
int tur=0;
if (tur==0)
{
Camera.Parameters p = camera.getParameters();
p.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
camera.setParameters(p);
camera.startPreview();
int tur=1;
}
if (tur==1)
{
Camera.Parameters p = camera.getParameters();
p.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
camera.setParameters(p);
camera.startPreview();
int tur=0;
}
}
Any ideas?
// Create a class member variable
private boolean isOn = false;
// And use it in your method
public void liBtn(View v) {
Camera.Parameters p = camera.getParameters();
if (!isOn) {
p.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
} else {
p.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
}
camera.setParameters(p);
camera.startPreview();
isOn = !isOn;
}
put int tur=0; outside your method.
create a global boolean variable isFlashOn and do some thing like this
public void liBtn(View v){
if (!isFlashOn)
{
Camera.Parameters p = camera.getParameters();
p.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
camera.setParameters(p);
camera.startPreview();
isFlashOn =true;
}else{
Camera.Parameters p = camera.getParameters();
p.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
camera.setParameters(p);
camera.startPreview();
isFlashOn =false;
}
}
I'm getting an OutOfMemoryError while creating a Bitmap from a picture taken from the Camera. My code works fine a couple times until I get the exception, so I spent several hours looking for memory leaks.
The weird thing is, I traced the code up to my PictureCallback just to check the byte array size: it's about 280k when no exception is thrown, but eventually, I receive a byte array of more than 1.2M, and that's when decodeByteArray crashes.
I'm using a custom CameraActivity. The code to init the Camera looks like this
camera = Camera.open();
camera.setDisplayOrientation(cameraOrientation);
Camera.Parameters params = camera.getParameters();
Size size = getPreferredPictureSize();
params.setPictureSize(size.width, size.height);
params.setJpegQuality(JPEG_QUALITY);
params.setPictureFormat(ImageFormat.JPEG);
camera.stopPreview();
camera.setParameters(params);
camera.startPreview();
When my CameraActivity is paused I release de Camera like this
if (camera != null) {
camera.stopPreview();
camera.release();
camera = null;
}
Why the returned picture can have so different sizes given the same initialization? May I missing some way to totally release the Camera stuff? Any clue is appreciated :)
I actually found several issues here, but I managed to stop receiving different sized arrays by resetting my camera parameters every time I take a picture. Here it is my CameraUtils implementation, just in case someone find it useful.
import java.util.List;
import android.content.pm.PackageManager;
import android.graphics.ImageFormat;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.Size;
public class CameraUtils implements Camera.AutoFocusCallback {
private static CameraUtils singleton = null;
private Camera camera = null;
private boolean isFocusing;
private PictureCallback pictureCallback;
private int cameraOrientation = 90;
private Size pictureSize;
private final String CAMERA_FLASH_MODE_ON = "on";
private final String CAMERA_FLASH_MODE_OFF = "off";
private final int PHOTO_HEIGHT_THRESHOLD = 960;
private final int JPEG_QUALITY = 90;
private String cameraFlashMode;
private float defaultCameraRatio;
private CameraUtils() {
}
public static CameraUtils getInstance() {
if (singleton == null) {
singleton = new CameraUtils();
}
return singleton;
}
#Override
public void onAutoFocus(boolean success, Camera camera) {
isFocusing = false;
if (CAMERA_FLASH_MODE_ON.equals(cameraFlashMode)) {
setFlashEnabled(true);
}
if (pictureCallback != null) {
setupParameters();
Application.getInstance().getCurrentActivity().showLoading();
camera.takePicture(null, null, pictureCallback);
}
}
public boolean checkCameraHardware() {
if (Application.getContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
return true;
} else {
return false;
}
}
public Camera getCamera() throws Exception {
if (camera == null) {
isFocusing = false;
pictureCallback = null;
camera = Camera.open();
camera.setDisplayOrientation(cameraOrientation);
setupParameters();
}
return camera;
}
public void setupParameters() {
Camera.Parameters params = camera.getParameters();
defaultCameraRatio = (float) params.getPictureSize().width / (float) params.getPictureSize().height;
Size size = getPreferredPictureSize();
params.setPictureSize(size.width, size.height);
params.setJpegQuality(JPEG_QUALITY);
params.setPictureFormat(ImageFormat.JPEG);
camera.stopPreview();
camera.setParameters(params);
camera.startPreview();
pictureSize = size;
}
public void autofocus(boolean forceAutofocus) {
if (camera != null && (!isFocusing || forceAutofocus)) {
camera.cancelAutoFocus();
disableFlash();
isFocusing = true;
camera.autoFocus(this);
}
}
public void releaseCamera() {
if (camera != null) {
camera.stopPreview();
camera.release();
camera = null;
}
}
public void setFlashEnabled(boolean enabled) {
if (camera != null) {
if (enabled) {
if (camera.getParameters().getSupportedFlashModes().contains(CAMERA_FLASH_MODE_ON)) {
Camera.Parameters params = camera.getParameters();
params.setFlashMode(CAMERA_FLASH_MODE_ON);
camera.setParameters(params);
cameraFlashMode = CAMERA_FLASH_MODE_ON;
}
} else {
if (camera.getParameters().getSupportedFlashModes().contains(CAMERA_FLASH_MODE_OFF)) {
Camera.Parameters params = camera.getParameters();
params.setFlashMode(CAMERA_FLASH_MODE_OFF);
camera.setParameters(params);
cameraFlashMode = CAMERA_FLASH_MODE_OFF;
}
}
}
}
public void disableFlash() {
Camera.Parameters params = camera.getParameters();
params.setFlashMode(CAMERA_FLASH_MODE_OFF);
camera.setParameters(params);
}
public void takePhoto(PictureCallback pictureCallback) throws Exception {
this.pictureCallback = pictureCallback;
autofocus(true);
}
private Size getPreferredPictureSize() {
Size res = null;
List<Size> sizes = camera.getParameters().getSupportedPictureSizes();
for (Size s : sizes) {
float ratio = (float) s.width / (float) s.height;
if (ratio == defaultCameraRatio && s.height <= PHOTO_HEIGHT_THRESHOLD) {
res = s;
break;
}
}
return res;
}
public Size getPictureSize() {
return pictureSize;
}
}
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(); }