I have been working in one of my android project in which I need to integrate Zbar scanner. I have integrated Zbar scanner in project. The problem I am facing is sometimes in Samsung Tab 3 has scanner area shows black screen. It is working perfectly in other devices. I have checked in nexus,canvas like devices and it shows perfect scanning screen. Is there any problem in my code? Here is my code.
private void initControls() {
try {
{
System.loadLibrary("iconv");
}
surfaceViewFlash = (SurfaceView) mView.findViewById(R.id.PREVIEW);
surfaceViewFlash.setVisibility(View.INVISIBLE);
surfaceViewFlash.setVisibility(View.VISIBLE);
mCameraScanner = getCameraInstance();
getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
previewingScanner = true;
autoFocusHandlerScanner = new Handler();
try {
// Instance barcode zBarScanner
zBarScanner = new ImageScanner();
zBarScanner.setConfig(0, Config.X_DENSITY, 3);
zBarScanner.setConfig(0, Config.Y_DENSITY, 3);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
mPreviewScanner = new CameraPreview(getActivity(), mCameraScanner, previewCb, autoFocusCB);
FrameLayout preview = (FrameLayout) mView.findViewById(R.id.cameraPreview);
preview.addView(mPreviewScanner);
if (barcodeScanned) {
barcodeScanned = false;
mCameraScanner.setPreviewCallback(previewCb);
mCameraScanner.startPreview();
previewingScanner = true;
Log.e("initControls", "initControls");
}
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* A safe way to get an instance of the Camera object.
*/
public Camera getCameraInstance() {
Camera c = null;
int frontId = 0, backId = 0;
try {
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
int numberOfCameras = Camera.getNumberOfCameras();
for (int i = 0; i < numberOfCameras; i++) {
Camera.getCameraInfo(i, cameraInfo);
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
frontId = i;
} else if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
backId = i;
}
}
c = Camera.open(backId);
} catch (Exception e) {
e.printStackTrace();
GeneralAlertDialog.createDialog(getActivity(), getString(R.string.app_name), "Camera is not working, Please try again.", new DialogDismiss() {
#Override
public void onDismiss() {
getCallBackForCloseScanner().OnCloseButtonClickOfScanner();
}
});
}
return c;
}
private void releaseCamera() {
if (mCameraScanner != null) {
mCameraScanner.cancelAutoFocus();
previewingScanner = false;
mCameraScanner.setPreviewCallback(null);
mPreviewScanner.getHolder().removeCallback(mPreviewScanner);
mCameraScanner.stopPreview();
mCameraScanner.release();
mCameraScanner = null;
mPreviewScanner = null;
}
}
Runnable doAutoFocus = new Runnable() {
public void run() {
try {
if (previewingScanner) {
if (mCameraScanner == null)
mCameraScanner = getCameraInstance();
Camera.Parameters parameters = null;
Log.e("mCameraScanner", mCameraScanner + "");
if (null != mCameraScanner.getParameters()) {
parameters = mCameraScanner.getParameters();
}
List<String> focusModes = parameters.getSupportedFocusModes();
if (focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
mCameraScanner.setParameters(parameters);
mCameraScanner.autoFocus(autoFocusCB);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
};
Please help me out to solve the problem.
releaseCamera on pause and on destroyed. it happen when camera is not release by any resource and you are again starting it.hope this will help you.
It's late, but this finally helped me, after overlooking the obvious.
Make sure you have camera permission for your app. It must be enabled not only through the camera permission declaration in the manifest file, BUT you also have to make sure you grant your app access to your camera by Android OS. Go to Preferences -> Apps -> Your App -> Permissions -> Allow camera access.
Starting from Android 6.0 (API 23), users are not asked for permissions at the time of installation rather developers need to request the permissions at the run time. Only the permissions that are defined in the manifest file can be requested at run time.
Request camera permission like here!.
Related
I want to create an application, and it needs to know when the camera is turned on by other app, whether the camera application is open or if a third party app is using the camera
how can i detect that if other app is try to open the camera . if other app try to open the camera i want to receive any broadcast before open the camera how can i do this.
i have also try this.
public boolean isCameraUsebyApp() {
Camera camera = null;
try {
camera = Camera.open();
} catch (RuntimeException e) {
return true;
} finally {
if (camera != null) camera.release();
}
return false;
}
but its alwys return true.
There is no broadcast for camera open or not but Camera Avaiability Listener in Camera2 Api, use below code
CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
manager.registerAvailabilityCallback(new CameraManager.AvailabilityCallback() {
#Override
public void onCameraAvailable(String cameraId) {
super.onCameraAvailable(cameraId);
//Do your work
}
#Override
public void onCameraUnavailable(String cameraId) {
super.onCameraUnavailable(cameraId);
//Do your work
}
}, mHandler);
}
its only 21 and above
For below 21 you can use your code
public boolean isCameraInUse() {
Camera c = null;
try {
c = Camera.open();
} catch (RuntimeException e) {
return true;
} finally {
if (c != null) c.release();
}
return false;
}
I'm creating a custom camera capturing videos with the new camera2 API.
My code is strongly inspired from the code provided by Google here. My camera preview has a button to switch from back to front camera and then from front to back camera.
The "camera preview" activity is launched with the back camera by default.
For some reason, when I click on the "switch/swap camera" button for the first time, it brings be to the front camera as it should, BUT everytime I click again, the switch/swap doesn't work anymore: the preview (on the front camera) fades a little bit, like if something is happening, but it remains on the currently selected (front) camera.
Here is my code :
In a RecordVideoFragment, in the onViewCreated:
// Switch camera button
switchCameraButton = (ImageButton) view.findViewById(R.id.button_switch_camera);
// Listener for Switch cameras button
switchCameraButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
switchCameras();
}
});
And here is the switchCameras() function:
private void switchCameras() {
mCameraOpenCloseLock.release();
mCameraDevice.close();
CameraManager mCameraManager = (CameraManager) getActivity().getSystemService(Context.CAMERA_SERVICE);
try {
String mCameraId = mCameraManager.getCameraIdList()[0];
if (mCameraId.equals("0")) { // If currently on FRONT camera (0 = CameraCharacteristics.LENS_FACING_FRONT)
mCameraId = "1"; // switch to BACK camera (1 = CameraCharacteristics.LENS_FACING_BACK)
switchCameraButton.setImageResource(R.drawable.ic_camera_front);
} else { // If currently on BACK camera
mCameraId = "0"; // switch to front camera
switchCameraButton.setImageResource(R.drawable.ic_camera_back);
}
try {
if (ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.CAMERA)
== PackageManager.PERMISSION_GRANTED) {
mCameraManager.openCamera(mCameraId, mStateCallback, null);
} else {
requestVideoPermissions();
}
} catch (CameraAccessException e) {
e.printStackTrace();
}
} catch (CameraAccessException e) {
Toast.makeText(getActivity(), "Cannot access the camera.", Toast.LENGTH_SHORT).show();
getActivity().finish();
}
}
If you have any idea on what's happening that would save me. I have been bugging on this for days. Thank you very much
What you need to do is introduce new variables:
public static final String CAMERA_FRONT = "1";
public static final String CAMERA_BACK = "0";
private String cameraId = CAMERA_BACK;
remove cameraId local variable from openCamera method.
public void switchCamera() {
if (cameraId.equals(CAMERA_FRONT)) {
cameraId = CAMERA_BACK;
closeCamera();
reopenCamera();
switchCameraButton.setImageResource(R.drawable.ic_camera_front);
} else if (cameraId.equals(CAMERA_BACK)) {
cameraId = CAMERA_FRONT;
closeCamera();
reopenCamera();
switchCameraButton.setImageResource(R.drawable.ic_camera_back);
}
}
public void reopenCamera() {
if (mTextureView.isAvailable()) {
openCamera(mTextureView.getWidth(), mTextureView.getHeight());
} else {
mTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
}
}
After looking at MrOnyszko answer i followed a slightly different approach:
In the Camera2Basic Tutorial a lens facing direction is used to set up the right camera, so i changed this direction before closing and reopening the camera.
private void switchCamera() {
if (mCameraLensFacingDirection == CameraCharacteristics.LENS_FACING_BACK) {
mCameraLensFacingDirection = CameraCharacteristics.LENS_FACING_FRONT;
closeCamera();
reopenCamera();
} else if (mCameraLensFacingDirection == CameraCharacteristics.LENS_FACING_FRONT) {
mCameraLensFacingDirection = CameraCharacteristics.LENS_FACING_BACK;
closeCamera();
reopenCamera();
}
}
private void reopenCamera() {
if (mTextureView.isAvailable()) {
openCamera(mTextureView.getWidth(), mTextureView.getHeight());
} else {
mTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
}
}
private void setUpCameraOutputs(int width, int height) {
Activity activity = getActivity();
CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
try {
for (String cameraId : manager.getCameraIdList()) {
CameraCharacteristics characteristics
= manager.getCameraCharacteristics(cameraId);
Integer facing = characteristics.get(CameraCharacteristics.LENS_FACING);
if (facing != null && facing != mCameraLensFacingDirection) {
continue;
}
...
In a previous way, flashlight feature could be used by using Camera class. But now that the entire Camera and Camera-related classes in android.hardware packages are deprecated, I should alternatively use some other classes in the android.hardware.camera2 package.
Traditionally, I coded the flashlight part like this.
// getting camera parameters
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;
}
// play sound
playSound();
params = camera.getParameters();
params.setFlashMode(Parameters.FLASH_MODE_TORCH);
camera.setParameters(params);
camera.startPreview();
isFlashOn = true;
// changing button/switch image
toggleButtonImage();
}
}
But now with the new API I'm getting so confused how to use the new one. Can anybody explain?
for flashlight I advise using the Camera2 API only from Android 6 (api 23), my function for toggling the flashlight looks like
#TargetApi(Build.VERSION_CODES.M)
public void toggleMarshmallowFlashlight(boolean enable) {
try {
final CameraManager manager = (CameraManager) mContext.getSystemService(Context.CAMERA_SERVICE);
final String[] list = manager.getCameraIdList();
manager.setTorchMode(list[0], enable);
} catch (CameraAccessException e) {
}
}
I am using camera service in my application. Sometimes the camera service is running fine in the application and sometimes it gives a runtime exception.
I have put Camera.Open() in try block and i have catched the exception and its showing in log cat
03-12 13:52:42.211: D/crazy(12686): in catch1
03-12 13:52:42.211: D/crazy(12686): java.lang.RuntimeException: Fail to connect to camera service
The code that i done is...
TelephonyManager mgr = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
int callState = mgr.getCallState();
//state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
if(callState==TelephonyManager.CALL_STATE_RINGING) {
try {
cam = Camera.open();
p = cam.getParameters();
String myString = "0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101011";
long blinkDelay = 50;
for (int i = 0; i < myString.length(); i++) {
//state=intent.getStringExtra(TelephonyManager.EXTRA_STATE);
callState = mgr.getCallState();
if (callState==TelephonyManager.CALL_STATE_IDLE){
p.setFlashMode(Parameters.FLASH_MODE_OFF);
cam.release();
break;
}else if (callState==TelephonyManager.CALL_STATE_OFFHOOK){
p.setFlashMode(Parameters.FLASH_MODE_OFF);
cam.release();
break;
}
if (myString.charAt(i) == '0') {
p.setFlashMode(Parameters.FLASH_MODE_TORCH);
cam.setParameters(p);
} else {
p.setFlashMode(Parameters.FLASH_MODE_OFF);
cam.setParameters(p);
}
Thread.sleep(blinkDelay);
}
}catch (Exception e) {
// TODO: handle exception
Log.d(tag, "in catch1");
Log.d(tag, e.toString());
}
It's probably because it is already used.
The javadoc for open states :
If the same camera is opened by other applications, this will throw a RuntimeException.
You must call release() when you are done using the camera, otherwise it will remain locked and be unavailable to other applications.
Your application should only have one Camera object active at a time for a particular hardware camera.
Make sure you always release the camera (even in case of exception, use finally) and check if there is no other application using it.
This comes from the android docs here. So long as you remember to release the camera when you're done (at at least before you try to get a new instance) you should be fine. I recommend reading the rest of that document as well. It is very helpful.
private boolean safeCameraOpen(int id) {
boolean qOpened = false;
try {
releaseCameraAndPreview();
mCamera = Camera.open(id);
qOpened = (mCamera != null);
} catch (Exception e) {
Log.e(getString(R.string.app_name), "failed to open Camera");
e.printStackTrace();
}
return qOpened;
}
private void releaseCameraAndPreview() {
mPreview.setCamera(null);
if (mCamera != null) {
mCamera.release();
mCamera = null;
}
}
Im trying to power on the led flash, but the led flash powers on after a delay of a few seconds.
I have a built in torch in my phone, and when I click it it the flash turns on immediately.
Whats the problem here?
Heres my code:
private void processOnClick() {
if (manuName.contains("motorola")) {
DroidLED led;
try {
led = new DroidLED();
led.enable(true);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
if (mCamera == null) {
try {
mCamera = Camera.open();
} catch (Exception e) {
e.printStackTrace();
}
}
try {
mCamera = Camera.open();
} catch (Exception e) {
e.printStackTrace();
}
if (mCamera != null) {
final Parameters params = mCamera.getParameters();
List<String> flashModes = params.getSupportedFlashModes();
if (flashModes == null) {
return;
} else {
if (count == 0) {
params.setFlashMode(Parameters.FLASH_MODE_OFF);
mCamera.setParameters(params);
mCamera.startPreview();
}
String flashMode = params.getFlashMode();
if (!Parameters.FLASH_MODE_TORCH.equals(flashMode)) {
if (flashModes.contains(Parameters.FLASH_MODE_TORCH)) {
params.setFlashMode(Parameters.FLASH_MODE_TORCH);
mCamera.setParameters(params);
} else {
// Toast.makeText(this,
// "Flash mode (torch) not supported",Toast.LENGTH_LONG).show();
params.setFlashMode(Parameters.FLASH_MODE_ON);
mCamera.setParameters(params);
try {
mCamera.autoFocus(new AutoFocusCallback() {
public void onAutoFocus(boolean success, Camera camera) {
count = 1;
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
}
if (mCamera == null) {
return;
}
}
private void processOffClick() {
if (manuName.contains("motorola")) {
DroidLED led;
try {
led = new DroidLED();
led.enable(false);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
if (mCamera != null) {
mCamera.stopPreview();
mCamera.release();
}
}
}
DroidLED class:
import java.lang.reflect.Method;
import android.os.IBinder;
class DroidLED {
private Object svc = null;
private Method getFlashlightEnabled = null;
private Method setFlashlightEnabled = null;
#SuppressWarnings("unchecked")
public DroidLED() throws Exception {
try {
// call ServiceManager.getService("hardware") to get an IBinder for the service.
// this appears to be totally undocumented and not exposed in the SDK whatsoever.
Class sm = Class.forName("android.os.ServiceManager");
Object hwBinder = sm.getMethod("getService", String.class).invoke(null, "hardware");
// get the hardware service stub. this seems to just get us one step closer to the proxy
Class hwsstub = Class.forName("android.os.IHardwareService$Stub");
Method asInterface = hwsstub.getMethod("asInterface", android.os.IBinder.class);
svc = asInterface.invoke(null, (IBinder) hwBinder);
// grab the class (android.os.IHardwareService$Stub$Proxy) so we can reflect on its methods
Class proxy = svc.getClass();
// save methods
getFlashlightEnabled = proxy.getMethod("getFlashlightEnabled");
setFlashlightEnabled = proxy.getMethod("setFlashlightEnabled", boolean.class);
}
catch(Exception e) {
throw new Exception("LED could not be initialized");
}
}
public boolean isEnabled() {
try {
return getFlashlightEnabled.invoke(svc).equals(true);
}
catch(Exception e) {
return false;
}
}
public void enable(boolean tf) {
try {
setFlashlightEnabled.invoke(svc, tf);
}
catch(Exception e) {}
}
}
I took this code from some answer around stackoverflow.
Thanks for your assistance!
Do you get high latencies with the motorola?
It's just a guess, but the DroidLED constructor calls expensive system initializations.
Couldn't you do this?
public class MyWidgetClickHandler {
private DroidLED = null;
public MyWidgetClickHandler(string ManuName) {
// This is slow. It will run once at initialization.
if (ManuName != null && ManuName.toLowerCase().contains("motorola"))
DroidLED = new DroidLED();
}
public void processOnClick() {
if (DroidLED != null)
DroidLED.enable(true);
else
; // ... TODO
}
public void processOffClick() {
if (DroidLED != null)
DroidLED.enable(false);
else
; // ... TODO
}
}
There could be so much more. For example you could create a LED interface with enable and isEnabled, and have two implementations for it. One would be DroidLED and the other the CommonCameraLED.
With this it looks like this:
public class LEDFactory {
public static LED createLED(string ManuName) {
if (ManuName != null && ManuName.toLowerCase().contains("motorola"))
return new DroidLED();
else
return new CommonCameraLED();
}
}
public class MyWidgetClickHandler {
private LED myLed = null;
public MyWidgetClickHandler(string ManuName) {
myLed = LEDFactory.createLED(ManuName);
}
public void processOnClick() {
myLed.enable(true);
// NOTHING TO DO
}
public void processOffClick() {
myLed.enable(false);
// NOTHING TO DO
}
}
You could also create a Thread for initialization so that phone won't start slow.
I just came across the same problem and found a solution, but i made my tests using a Samsung Galaxy S2. This code should work on every device.
Profiling each one of the functions, i found that some calls necessary to setup the camera, sumed up to 500ms in delay, making a strobe effect impossible.
My solution was to move all those functions to a separate function i call when i want to get the camera, and reduce the "turn on" code just to the call to Camera.setParameters(). By doing this, the delay came down to only 4ms.
For example (reduced code just to to prove the point):
// First get the camera for your app (Keep this variables as class
members so the live between functions)
private void acquireCamera()
{
try
{
// Get camera
cam = Camera.open();
// This is not on your code but you should do it for compatibility
mSurfaceTexture = new SurfaceTexture(0);
cam.setPreviewTexture(mSurfaceTexture);
cam.startPreview();
camParams = cam.getParameters();
}
catch(IOException e)
{ /*...*/ }
}
// Then turn on / off as many times you want.
private void setTorch(boolean on)
{
camParams.setFlashMode(on? Camera.Parameters.FLASH_MODE_TORCH : Camera.Parameters.FLASH_MODE_OFF);
cam.setParameters(camParams);
}
// Finally release the camera when you`re done
private void releaseCamera
{
camParams = null;
cam.stopPreview();
mSurfaceTexture = null;
cam.release();
}