Reputation: 465
I'm working on app based on Camera2 API. And I want to add feature of enabling/disabling flash light in this app.
There are some problems. I use 3 different threads for rendering and so one and communicate between this threads via Handlers. When user pree flash light button I want to enable it, and I can do it like this:
mPreviewBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_SINGLE);
mPreviewSession.setRepeatingRequest(mPreviewBuilder.build(), null, null);
But , as I understand creating new prewiew session is expensive procedure, and I also don't want to loose any frames from camera.
Is there any way of enabling flash light without building new session? Or I'm wrong and it doesn't take a lot of resources at all?
I also wonder how it's implemented in standart camera applications. Maybe there is any open source code?
Thanks everyone for answers in advance!
Upvotes: 0
Views: 2704
Reputation: 18137
Changing the repeating request of a session is not expensive at all. It doesn't re-create the session (that would only happen if you call CameraDevice.createCaptureSession again), and there won't generally be any glitches from changing a setting like this. Changing the repeating request is exactly how you should be turning on the flashlight when you have an open camera device.
Note that setting the flash mode to SINGLE in a repeating request is probably not what you want; you probably want flash mode of TORCH (For continuous smooth flashlight, not strobing main flash firing), and you'll also need to make sure you CONTROL_AE_MODE setting is not one of the AE_MODE_ON_FLASH* modes; otherwise the camera device's autoexposure routine is in control of the flash and the FLASH_MODE setting is ignored.
Upvotes: 2
Reputation: 4304
You only need to create one CameraCaptureSession
, and just call its capture()
or setRepeatingRequest()
methods to send CaptureRequest
s to it, so it's not an expensive procedure at all, the only CameraCaptureSession
is created when you have opened the CameraDevice
and started your preview, the CameraCaptureSession
will take care of all the CaptureRequest
s you send and do it's best to not cause any frames lost.
See the code from google/cameraview:
void setFlash(int flash) {
if (mFlash == flash) {
return;
}
int saved = mFlash;
mFlash = flash;
if (mPreviewRequestBuilder != null) {
updateFlash(); // Set the new flash settings
if (mCaptureSession != null) {
try {
mCaptureSession.setRepeatingRequest(mPreviewRequestBuilder.build(),
mCaptureCallback, null);
} catch (CameraAccessException e) {
mFlash = saved; // Revert
}
}
}
}
void updateFlash() {
switch (mFlash) {
case Constants.FLASH_OFF:
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE,
CaptureRequest.CONTROL_AE_MODE_ON);
mPreviewRequestBuilder.set(CaptureRequest.FLASH_MODE,
CaptureRequest.FLASH_MODE_OFF);
break;
case Constants.FLASH_ON:
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE,
CaptureRequest.CONTROL_AE_MODE_ON_ALWAYS_FLASH);
mPreviewRequestBuilder.set(CaptureRequest.FLASH_MODE,
CaptureRequest.FLASH_MODE_OFF);
break;
case Constants.FLASH_TORCH:
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE,
CaptureRequest.CONTROL_AE_MODE_ON);
mPreviewRequestBuilder.set(CaptureRequest.FLASH_MODE,
CaptureRequest.FLASH_MODE_TORCH);
break;
case Constants.FLASH_AUTO:
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE,
CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
mPreviewRequestBuilder.set(CaptureRequest.FLASH_MODE,
CaptureRequest.FLASH_MODE_OFF);
break;
case Constants.FLASH_RED_EYE:
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE,
CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE);
mPreviewRequestBuilder.set(CaptureRequest.FLASH_MODE,
CaptureRequest.FLASH_MODE_OFF);
break;
}
}
Upvotes: 2
Reputation: 11477
Try this , Full code for taking picture using camera2 API , Fragment_Camera4
public class Fragment_Camera4 extends Fragment implements
AspectRatioFragment.Listener {
private View view;
private static final String TAG = "MainActivity";
private static final int REQUEST_CAMERA_PERMISSION = 1;
private static final String FRAGMENT_DIALOG = "dialog";
private static final int[] FLASH_OPTIONS = {
CameraView.FLASH_OFF,
CameraView.FLASH_ON,
};
private static final int[] FLASH_ICONS = {
R.drawable.ic_flash_off,
R.drawable.ic_flash_on,
};
private static final int[] FLASH_TITLES = {
R.string.flash_auto,
R.string.flash_off,
R.string.flash_on,
};
private int mCurrentFlash;
private CameraView mCameraView;
private Handler mBackgroundHandler;
private View.OnClickListener mOnClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.take_picture:
if (mCameraView != null) {
mCameraView.takePicture();
}
break;
case R.id.btn_switch_camera:
if (mCameraView != null) {
int facing = mCameraView.getFacing();
mCameraView.setFacing(facing == CameraView.FACING_FRONT ?
CameraView.FACING_BACK : CameraView.FACING_FRONT);
if (facing == CameraView.FACING_FRONT) {
btn_flash_onOff.setVisibility(View.VISIBLE);
} else {
btn_flash_onOff.setVisibility(View.GONE);
}
}
break;
case R.id.btn_flash_onOff:
if (mCameraView != null) {
mCurrentFlash = (mCurrentFlash + 1) % FLASH_OPTIONS.length;
btn_flash_onOff.setImageResource(FLASH_ICONS[mCurrentFlash]);
mCameraView.setFlash(FLASH_OPTIONS[mCurrentFlash]);
}
break;
}
}
};
ImageButton btn_flash_onOff;
public Fragment_Camera4() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
view = inflater.inflate(R.layout.fragment_fragment__camera4, container, false);
mCameraView = (CameraView) view.findViewById(R.id.camera);
if (mCameraView != null) {
mCameraView.addCallback(mCallback);
}
ImageButton fab = (ImageButton) view.findViewById(R.id.take_picture);
ImageButton btn_switch_camera = (ImageButton) view.findViewById(R.id.btn_switch_camera);
btn_flash_onOff = (ImageButton) view.findViewById(R.id.btn_flash_onOff);
if (fab != null) {
fab.setOnClickListener(mOnClickListener);
btn_switch_camera.setOnClickListener(mOnClickListener);
btn_flash_onOff.setOnClickListener(mOnClickListener);
}
return view;
}
@Override
public void onResume() {
super.onResume();
mCameraView.start();
}
@Override
public void onPause() {
mCameraView.stop();
super.onPause();
}
@Override
public void onDestroy() {
super.onDestroy();
if (mBackgroundHandler != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
mBackgroundHandler.getLooper().quitSafely();
} else {
mBackgroundHandler.getLooper().quit();
}
mBackgroundHandler = null;
}
}
@Override
public void onAspectRatioSelected(@NonNull AspectRatio ratio) {
if (mCameraView != null) {
Toast.makeText(getActivity(), ratio.toString(), Toast.LENGTH_SHORT).show();
mCameraView.setAspectRatio(ratio);
}
}
private Handler getBackgroundHandler() {
if (mBackgroundHandler == null) {
HandlerThread thread = new HandlerThread("background");
thread.start();
mBackgroundHandler = new Handler(thread.getLooper());
}
return mBackgroundHandler;
}
private CameraView.Callback mCallback
= new CameraView.Callback() {
@Override
public void onCameraOpened(CameraView cameraView) {
Log.d(TAG, "onCameraOpened");
}
@Override
public void onCameraClosed(CameraView cameraView) {
Log.d(TAG, "onCameraClosed");
}
@Override
public void onPictureTaken(CameraView cameraView, final byte[] data) {
Log.d(TAG, "onPictureTaken " + data.length);
Toast.makeText(cameraView.getContext(), R.string.picture_taken, Toast.LENGTH_SHORT)
.show();
}
};
}
Then Cameraview file is here from this github link of mine https://github.com/quicklearner4991/Camera2/blob/master/CameraView get the resources from this link , i cant post that much long answer here , I have edited my code for camera2 with flash options which is not available easily . Link to download resources using this repo
https://github.com/googlesamples/android-Camera2Basic and xml for the views
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorgrey">
<com.google.android.cameraview.CameraView
android:id="@+id/camera"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:adjustViewBounds="true"
android:background="@android:color/black" />
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true" />
<ImageButton
android:id="@+id/take_picture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="20dp"
android:background="#0000"
app:srcCompat="@drawable/ic_take_pic" />
<ImageButton
android:id="@+id/btn_switch_camera"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_margin="20dp"
android:background="#0000"
app:srcCompat="@drawable/ic_reset_camera" />
<ImageButton
android:id="@+id/btn_flash_onOff"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_margin="20dp"
android:background="#0000"
app:srcCompat="@drawable/ic_flash_off" />
</RelativeLayout>
Upvotes: -1