Added CameraApi

pull/17/head
Florent CHAMPIGNY 8 years ago
parent c3b0214cd0
commit 1c219d40f0
  1. 4
      README.md
  2. 76
      app/src/main/java/com/github/florent37/camerafragment/sample/MainActivity.java
  3. 8
      app/src/main/res/layout/activity_fragment.xml
  4. 32
      camerafragment/src/main/java/com/github/florent37/camerafragment/CameraFragmentApi.java
  5. 5
      camerafragment/src/main/java/com/github/florent37/camerafragment/internal/controller/CameraController.java
  6. 20
      camerafragment/src/main/java/com/github/florent37/camerafragment/internal/controller/impl/Camera1Controller.java
  7. 20
      camerafragment/src/main/java/com/github/florent37/camerafragment/internal/controller/impl/Camera2Controller.java
  8. 6
      camerafragment/src/main/java/com/github/florent37/camerafragment/internal/controller/view/CameraView.java
  9. 5
      camerafragment/src/main/java/com/github/florent37/camerafragment/internal/manager/CameraManager.java
  10. 114
      camerafragment/src/main/java/com/github/florent37/camerafragment/internal/manager/impl/Camera1Manager.java
  11. 89
      camerafragment/src/main/java/com/github/florent37/camerafragment/internal/manager/impl/Camera2Manager.java
  12. 4
      camerafragment/src/main/java/com/github/florent37/camerafragment/internal/manager/listener/CameraPhotoListener.java
  13. 3
      camerafragment/src/main/java/com/github/florent37/camerafragment/internal/manager/listener/CameraVideoListener.java
  14. 124
      camerafragment/src/main/java/com/github/florent37/camerafragment/internal/ui/BaseAnncaFragment.java
  15. 19
      camerafragment/src/main/java/com/github/florent37/camerafragment/widgets/CameraSwitchView.java
  16. 19
      camerafragment/src/main/java/com/github/florent37/camerafragment/widgets/FlashSwitchView.java

@ -15,7 +15,7 @@ getSupportFragmentManager().beginTransaction()
You can directly take a photo / video with
```java
cameraFragment.takePhotoOrCaptureVideo();
cameraFragment.takePhotoOrCaptureVideo(callback);
```
[![gif](https://raw.githubusercontent.com/florent37/CameraFragment/master/media/take_photo.gif)](https://github.com/florent37/CameraFragment)
@ -39,7 +39,7 @@ cameraFragment.switchCameraType();
Camera action ( `PHOTO` / `VIDEO` ) can be modified with
```java
cameraFragment.switchAction();
cameraFragment.switchActionPhotoVideo();
```
[![gif](https://raw.githubusercontent.com/florent37/CameraFragment/master/media/switch_action.gif)](https://github.com/florent37/CameraFragment)

@ -21,6 +21,7 @@ import butterknife.Bind;
import butterknife.ButterKnife;
import butterknife.OnClick;
import com.github.florent37.camerafragment.CameraFragment;
import com.github.florent37.camerafragment.CameraFragmentApi;
import com.github.florent37.camerafragment.configuration.Configuration;
import com.github.florent37.camerafragment.PreviewActivity;
import com.github.florent37.camerafragment.listeners.CameraFragmentStateListener;
@ -57,74 +58,56 @@ public class MainActivity extends AppCompatActivity {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fragment);
ButterKnife.bind(this);
recordButton.setVisibility(View.GONE);
settingsView.setVisibility(View.GONE);
flashSwitchView.setVisibility(View.GONE);
cameraSwitchView.setVisibility(View.GONE);
mediaActionSwitchView.setVisibility(View.GONE);
setupViewListeners();
}
@OnClick(R.id.take_photo)
public void takePhotoClicked(){
final CameraFragment cameraFragment = getCameraFragment();
if (cameraFragment != null) {
cameraFragment.takePhotoOrCaptureVideo();
}
}
private void setupViewListeners() {
flashSwitchView.setFlashSwitchListener(new FlashSwitchView.FlashModeSwitchListener() {
@Override
public void toggleFlashMode() {
final CameraFragment cameraFragment = getCameraFragment();
@OnClick(R.id.flash_switch_view)
public void onFlashSwitcClicked(){
final CameraFragmentApi cameraFragment = getCameraFragment();
if (cameraFragment != null) {
cameraFragment.toggleFlashMode();
}
}
});
cameraSwitchView.setOnCameraTypeChangeListener(new CameraSwitchView.OnCameraTypeChangeListener() {
@Override
public void switchCameraType() {
final CameraFragment cameraFragment = getCameraFragment();
@OnClick(R.id.front_back_camera_switcher)
public void onSwitchCameraClicked(){
final CameraFragmentApi cameraFragment = getCameraFragment();
if (cameraFragment != null) {
cameraFragment.switchCameraType();
}
}
});
recordButton.setRecordButtonListener(new RecordButton.RecordButtonListener() {
@Override
@OnClick(R.id.record_button)
public void onRecordButtonClicked(){
final CameraFragment cameraFragment = getCameraFragment();
final CameraFragmentApi cameraFragment = getCameraFragment();
if (cameraFragment != null) {
cameraFragment.takePhotoOrCaptureVideo();
}
cameraFragment.takePhotoOrCaptureVideo(new CameraFragmentResultListener() {
@Override
public void onVideoRecorded(String filePath) {
}
});
mediaActionSwitchView.setOnMediaActionStateChangeListener(new MediaActionSwitchView.OnMediaActionStateChangeListener() {
@Override
public void switchAction() {
final CameraFragment cameraFragment = getCameraFragment();
if (cameraFragment != null) {
cameraFragment.switchAction();
}
public void onPhotoTaken(byte[] bytes, String filePath) {
}
});
}
}
settingsView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
final CameraFragment cameraFragment = getCameraFragment();
@OnClick(R.id.settings_view)
public void onSettingsClicked(){
final CameraFragmentApi cameraFragment = getCameraFragment();
if (cameraFragment != null) {
cameraFragment.openSettingDialog();
}
}
});
@OnClick(R.id.settings_view)
public void onMediaActionSwitchClicked(){
final CameraFragmentApi cameraFragment = getCameraFragment();
if (cameraFragment != null) {
cameraFragment.switchActionPhotoVideo();
}
}
@OnClick(R.id.addCameraButton)
@ -169,7 +152,6 @@ public class MainActivity extends AppCompatActivity {
.commit();
if (cameraFragment != null) {
cameraFragment.setResultListener(new CameraFragmentResultListener() {
@Override
public void onVideoRecorded(String filePath) {
@ -327,7 +309,7 @@ public class MainActivity extends AppCompatActivity {
mediaActionSwitchView.displayActionWillSwitchVideo();
}
private CameraFragment getCameraFragment() {
return (CameraFragment) getSupportFragmentManager().findFragmentByTag(FRAGMENT_TAG);
private CameraFragmentApi getCameraFragment() {
return (CameraFragmentApi) getSupportFragmentManager().findFragmentByTag(FRAGMENT_TAG);
}
}

@ -73,18 +73,10 @@
android:id="@+id/record_button"
android:layout_width="75dp"
android:layout_height="75dp"
android:visibility="gone"
android:layout_centerInParent="true"
android:layout_marginLeft="50dp"
android:layout_marginRight="50dp" />
<Button
android:id="@+id/take_photo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="take photo"/>
<com.github.florent37.camerafragment.widgets.MediaActionSwitchView
android:id="@+id/photo_video_camera_switcher"
android:layout_width="40dp"

@ -0,0 +1,32 @@
package com.github.florent37.camerafragment;
import com.github.florent37.camerafragment.listeners.CameraFragmentControlsListener;
import com.github.florent37.camerafragment.listeners.CameraFragmentResultListener;
import com.github.florent37.camerafragment.listeners.CameraFragmentStateListener;
import com.github.florent37.camerafragment.listeners.CameraFragmentVideoRecordTextListener;
/**
* Created by florentchampigny on 16/01/2017.
*/
public interface CameraFragmentApi {
void takePhotoOrCaptureVideo(CameraFragmentResultListener resultListener);
void openSettingDialog();
void switchCameraType();
void switchActionPhotoVideo();
void toggleFlashMode();
void setStateListener(CameraFragmentStateListener cameraFragmentStateListener);
void setTextListener(CameraFragmentVideoRecordTextListener cameraFragmentVideoRecordTextListener);
void setControlsListener(CameraFragmentControlsListener cameraFragmentControlsListener);
void setResultListener(CameraFragmentResultListener cameraFragmentResultListener);
}

@ -6,6 +6,7 @@ import java.io.File;
import com.github.florent37.camerafragment.configuration.Configuration;
import com.github.florent37.camerafragment.internal.manager.CameraManager;
import com.github.florent37.camerafragment.listeners.CameraFragmentResultListener;
/**
* Created by memfis on 7/6/16.
@ -20,11 +21,11 @@ public interface CameraController<CameraId> {
void onDestroy();
void takePhoto();
void takePhoto(CameraFragmentResultListener resultListener);
void startVideoRecord();
void stopVideoRecord();
void stopVideoRecord(CameraFragmentResultListener callback);
boolean isVideoRecording();

@ -2,6 +2,7 @@ package com.github.florent37.camerafragment.internal.controller.impl;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.util.Log;
import android.view.SurfaceHolder;
@ -20,6 +21,7 @@ import com.github.florent37.camerafragment.internal.manager.listener.CameraVideo
import com.github.florent37.camerafragment.internal.ui.view.AutoFitSurfaceView;
import com.github.florent37.camerafragment.internal.utils.CameraHelper;
import com.github.florent37.camerafragment.internal.utils.Size;
import com.github.florent37.camerafragment.listeners.CameraFragmentResultListener;
/**
* Created by memfis on 7/7/16.
@ -48,7 +50,7 @@ public class Camera1Controller implements CameraController<Integer>,
@Override
public void onCreate(Bundle savedInstanceState) {
cameraManager = Camera1Manager.getInstance();
cameraManager = new Camera1Manager();
cameraManager.initializeCameraManager(configurationProvider, context);
setCurrentCameraId(cameraManager.getFaceBackCameraId());
}
@ -74,9 +76,9 @@ public class Camera1Controller implements CameraController<Integer>,
}
@Override
public void takePhoto() {
public void takePhoto(CameraFragmentResultListener callback) {
outputFile = CameraHelper.getOutputMediaFile(context, Configuration.MEDIA_ACTION_PHOTO);
cameraManager.takePhoto(outputFile, this);
cameraManager.takePhoto(outputFile, this, callback);
}
@Override
@ -86,8 +88,8 @@ public class Camera1Controller implements CameraController<Integer>,
}
@Override
public void stopVideoRecord() {
cameraManager.stopVideoRecord();
public void stopVideoRecord(CameraFragmentResultListener callback) {
cameraManager.stopVideoRecord(callback);
}
@Override
@ -154,8 +156,8 @@ public class Camera1Controller implements CameraController<Integer>,
}
@Override
public void onPhotoTaken(byte[] bytes, File photoFile) {
cameraView.onPhotoTaken(bytes);
public void onPhotoTaken(byte[] bytes, File photoFile, CameraFragmentResultListener callback) {
cameraView.onPhotoTaken(bytes, callback);
}
@Override
@ -168,8 +170,8 @@ public class Camera1Controller implements CameraController<Integer>,
}
@Override
public void onVideoRecordStopped(File videoFile) {
cameraView.onVideoRecordStop();
public void onVideoRecordStopped(File videoFile, @Nullable CameraFragmentResultListener callback) {
cameraView.onVideoRecordStop(callback);
}
@Override

@ -4,6 +4,7 @@ import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.util.Log;
import android.view.TextureView;
@ -22,6 +23,7 @@ import com.github.florent37.camerafragment.internal.manager.listener.CameraVideo
import com.github.florent37.camerafragment.internal.ui.view.AutoFitTextureView;
import com.github.florent37.camerafragment.internal.utils.CameraHelper;
import com.github.florent37.camerafragment.internal.utils.Size;
import com.github.florent37.camerafragment.listeners.CameraFragmentResultListener;
/**
* Created by memfis on 7/6/16.
@ -49,7 +51,7 @@ public class Camera2Controller implements CameraController<String>,
@Override
public void onCreate(Bundle savedInstanceState) {
camera2Manager = Camera2Manager.getInstance();
camera2Manager = new Camera2Manager();
camera2Manager.initializeCameraManager(configurationProvider, context);
setCurrentCameraId(camera2Manager.getFaceBackCameraId());
}
@ -71,9 +73,9 @@ public class Camera2Controller implements CameraController<String>,
}
@Override
public void takePhoto() {
public void takePhoto(CameraFragmentResultListener callback) {
outputFile = CameraHelper.getOutputMediaFile(context, Configuration.MEDIA_ACTION_PHOTO);
camera2Manager.takePhoto(outputFile, this);
camera2Manager.takePhoto(outputFile, this, callback);
}
@Override
@ -83,8 +85,8 @@ public class Camera2Controller implements CameraController<String>,
}
@Override
public void stopVideoRecord() {
camera2Manager.stopVideoRecord();
public void stopVideoRecord(CameraFragmentResultListener callback) {
camera2Manager.stopVideoRecord(callback);
}
@Override
@ -155,8 +157,8 @@ public class Camera2Controller implements CameraController<String>,
}
@Override
public void onPhotoTaken(byte[] bytes, File photoFile) {
cameraView.onPhotoTaken(bytes);
public void onPhotoTaken(byte[] bytes, File photoFile, CameraFragmentResultListener callback) {
cameraView.onPhotoTaken(bytes, callback);
}
@Override
@ -169,8 +171,8 @@ public class Camera2Controller implements CameraController<String>,
}
@Override
public void onVideoRecordStopped(File videoFile) {
cameraView.onVideoRecordStop();
public void onVideoRecordStopped(File videoFile, @Nullable CameraFragmentResultListener callback) {
cameraView.onVideoRecordStop(callback);
}
@Override

@ -1,9 +1,11 @@
package com.github.florent37.camerafragment.internal.controller.view;
import android.support.annotation.Nullable;
import android.view.View;
import com.github.florent37.camerafragment.configuration.Configuration;
import com.github.florent37.camerafragment.internal.utils.Size;
import com.github.florent37.camerafragment.listeners.CameraFragmentResultListener;
/**
* Created by memfis on 7/6/16.
@ -16,11 +18,11 @@ public interface CameraView {
void updateCameraSwitcher(int numberOfCameras);
void onPhotoTaken(byte[] bytes);
void onPhotoTaken(byte[] bytes, @Nullable CameraFragmentResultListener callback);
void onVideoRecordStart(int width, int height);
void onVideoRecordStop();
void onVideoRecordStop(@Nullable CameraFragmentResultListener callback);
void releaseCameraPreview();

@ -11,6 +11,7 @@ import com.github.florent37.camerafragment.internal.manager.listener.CameraOpenL
import com.github.florent37.camerafragment.internal.manager.listener.CameraPhotoListener;
import com.github.florent37.camerafragment.internal.manager.listener.CameraVideoListener;
import com.github.florent37.camerafragment.internal.utils.Size;
import com.github.florent37.camerafragment.listeners.CameraFragmentResultListener;
/**
* Created by memfis on 8/14/16.
@ -25,13 +26,13 @@ public interface CameraManager<CameraId, SurfaceListener> {
void setFlashMode(@Configuration.FlashMode int flashMode);
void takePhoto(File photoFile, CameraPhotoListener cameraPhotoListener);
void takePhoto(File photoFile, CameraPhotoListener cameraPhotoListener, CameraFragmentResultListener callback);
void startVideoRecord(File videoFile, CameraVideoListener cameraVideoListener);
Size getPhotoSizeForQuality(@Configuration.MediaQuality int mediaQuality);
void stopVideoRecord();
void stopVideoRecord(CameraFragmentResultListener callback);
void releaseCameraManager();

@ -7,6 +7,7 @@ import android.media.CamcorderProfile;
import android.media.ExifInterface;
import android.media.MediaRecorder;
import android.os.Build;
import android.support.annotation.Nullable;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceHolder;
@ -29,21 +30,19 @@ import com.github.florent37.camerafragment.internal.ui.model.PhotoQualityOption;
import com.github.florent37.camerafragment.internal.ui.model.VideoQualityOption;
import com.github.florent37.camerafragment.internal.utils.CameraHelper;
import com.github.florent37.camerafragment.internal.utils.Size;
import com.github.florent37.camerafragment.listeners.CameraFragmentResultListener;
/**
* Created by memfis on 8/14/16.
*/
@SuppressWarnings("deprecation")
public class Camera1Manager extends BaseCameraManager<Integer, SurfaceHolder.Callback>
implements SurfaceHolder.Callback, Camera.PictureCallback {
public class Camera1Manager extends BaseCameraManager<Integer, SurfaceHolder.Callback> {
private static final String TAG = "Camera1Manager";
private Camera camera;
private Surface surface;
private static Camera1Manager currentInstance;
private int orientation;
private int displayRotation = 0;
@ -51,15 +50,6 @@ public class Camera1Manager extends BaseCameraManager<Integer, SurfaceHolder.Cal
private CameraVideoListener videoListener;
private CameraPhotoListener photoListener;
private Camera1Manager() {
}
public static Camera1Manager getInstance() {
if (currentInstance == null) currentInstance = new Camera1Manager();
return currentInstance;
}
@Override
public void openCamera(final Integer cameraId,
final CameraOpenListener<Integer, SurfaceHolder.Callback> cameraOpenListener) {
@ -74,7 +64,44 @@ public class Camera1Manager extends BaseCameraManager<Integer, SurfaceHolder.Cal
uiHandler.post(new Runnable() {
@Override
public void run() {
cameraOpenListener.onCameraOpened(cameraId, previewSize, currentInstance);
cameraOpenListener.onCameraOpened(cameraId, previewSize, new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
if (surfaceHolder.getSurface() == null) {
return;
}
surface = surfaceHolder.getSurface();
try {
camera.stopPreview();
} catch (Exception ignore) {
}
startPreview(surfaceHolder);
}
@Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int format, int width, int height) {
if (surfaceHolder.getSurface() == null) {
return;
}
surface = surfaceHolder.getSurface();
try {
camera.stopPreview();
} catch (Exception ignore) {
}
startPreview(surfaceHolder);
}
@Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
}
});
}
});
}
@ -120,14 +147,19 @@ public class Camera1Manager extends BaseCameraManager<Integer, SurfaceHolder.Cal
}
@Override
public void takePhoto(File photoFile, CameraPhotoListener cameraPhotoListener) {
public void takePhoto(File photoFile, CameraPhotoListener cameraPhotoListener, final CameraFragmentResultListener callback) {
this.outputPath = photoFile;
this.photoListener = cameraPhotoListener;
backgroundHandler.post(new Runnable() {
@Override
public void run() {
setCameraPhotoQuality(camera);
camera.takePicture(null, null, currentInstance);
camera.takePicture(null, null, new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] bytes, Camera camera) {
Camera1Manager.this.onPictureTaken(bytes, camera, callback);
}
});
}
});
}
@ -158,7 +190,7 @@ public class Camera1Manager extends BaseCameraManager<Integer, SurfaceHolder.Cal
}
@Override
public void stopVideoRecord() {
public void stopVideoRecord(@Nullable final CameraFragmentResultListener callback) {
if (isVideoRecording)
backgroundHandler.post(new Runnable() {
@Override
@ -178,7 +210,7 @@ public class Camera1Manager extends BaseCameraManager<Integer, SurfaceHolder.Cal
uiHandler.post(new Runnable() {
@Override
public void run() {
videoListener.onVideoRecordStopped(outputPath);
videoListener.onVideoRecordStopped(outputPath, callback);
}
});
}
@ -306,12 +338,12 @@ public class Camera1Manager extends BaseCameraManager<Integer, SurfaceHolder.Cal
@Override
protected void onMaxDurationReached() {
stopVideoRecord();
stopVideoRecord(null);
}
@Override
protected void onMaxFileSizeReached() {
stopVideoRecord();
stopVideoRecord(null);
}
@Override
@ -511,45 +543,7 @@ public class Camera1Manager extends BaseCameraManager<Integer, SurfaceHolder.Cal
return rotate;
}
@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
if (surfaceHolder.getSurface() == null) {
return;
}
surface = surfaceHolder.getSurface();
try {
camera.stopPreview();
} catch (Exception ignore) {
}
startPreview(surfaceHolder);
}
@Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int format, int width, int height) {
if (surfaceHolder.getSurface() == null) {
return;
}
surface = surfaceHolder.getSurface();
try {
camera.stopPreview();
} catch (Exception ignore) {
}
startPreview(surfaceHolder);
}
@Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
}
@Override
public void onPictureTaken(final byte[] bytes, Camera camera) {
protected void onPictureTaken(final byte[] bytes, Camera camera, final CameraFragmentResultListener callback) {
File pictureFile = outputPath;
if (pictureFile == null) {
Log.d(TAG, "Error creating media file, check storage permissions.");
@ -577,7 +571,7 @@ public class Camera1Manager extends BaseCameraManager<Integer, SurfaceHolder.Cal
uiHandler.post(new Runnable() {
@Override
public void run() {
photoListener.onPhotoTaken(bytes, outputPath);
photoListener.onPhotoTaken(bytes, outputPath, callback);
}
});
}

@ -28,15 +28,6 @@ import android.view.Surface;
import android.view.TextureView;
import android.view.WindowManager;
import java.io.File;
import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import com.github.florent37.camerafragment.configuration.Configuration;
import com.github.florent37.camerafragment.configuration.ConfigurationProvider;
import com.github.florent37.camerafragment.internal.manager.listener.CameraCloseListener;
@ -48,6 +39,16 @@ import com.github.florent37.camerafragment.internal.ui.model.VideoQualityOption;
import com.github.florent37.camerafragment.internal.utils.CameraHelper;
import com.github.florent37.camerafragment.internal.utils.ImageSaver;
import com.github.florent37.camerafragment.internal.utils.Size;
import com.github.florent37.camerafragment.listeners.CameraFragmentResultListener;
import java.io.File;
import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
/**
* Created by memfis on 8/9/16.
@ -57,54 +58,39 @@ public final class Camera2Manager extends BaseCameraManager<String, TextureView.
implements ImageReader.OnImageAvailableListener, TextureView.SurfaceTextureListener {
private final static String TAG = "Camera2Manager";
private static Camera2Manager currentInstance;
private static final int STATE_PREVIEW = 0;
private static final int STATE_WAITING_LOCK = 1;
private static final int STATE_WAITING_PRE_CAPTURE = 2;
private static final int STATE_WAITING_NON_PRE_CAPTURE = 3;
private static final int STATE_PICTURE_TAKEN = 4;
private CameraOpenListener<String, TextureView.SurfaceTextureListener> cameraOpenListener;
private CameraPhotoListener cameraPhotoListener;
private CameraVideoListener cameraVideoListener;
private File outputPath;
@CameraPreviewState
private int previewState = STATE_PREVIEW;
private static final int STATE_PREVIEW = 0;
private static final int STATE_WAITING_LOCK = 1;
private static final int STATE_WAITING_PRE_CAPTURE = 2;
private static final int STATE_WAITING_NON_PRE_CAPTURE = 3;
private static final int STATE_PICTURE_TAKEN = 4;
@IntDef({STATE_PREVIEW, STATE_WAITING_LOCK, STATE_WAITING_PRE_CAPTURE, STATE_WAITING_NON_PRE_CAPTURE, STATE_PICTURE_TAKEN})
@Retention(RetentionPolicy.SOURCE)
@interface CameraPreviewState {
}
private CameraManager manager;
private CameraDevice cameraDevice;
private CaptureRequest previewRequest;
private CaptureRequest.Builder previewRequestBuilder;
private CameraCaptureSession captureSession;
private CameraCharacteristics frontCameraCharacteristics;
private CameraCharacteristics backCameraCharacteristics;
private StreamConfigurationMap frontCameraStreamConfigurationMap;
private StreamConfigurationMap backCameraStreamConfigurationMap;
private SurfaceTexture texture;
private Surface workingSurface;
private ImageReader imageReader;
private CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {
@Override
public void onOpened(CameraDevice cameraDevice) {
currentInstance.cameraDevice = cameraDevice;
Camera2Manager.this.cameraDevice = cameraDevice;
if (cameraOpenListener != null) {
uiHandler.post(new Runnable() {
@Override
public void run() {
if (!TextUtils.isEmpty(currentCameraId) && previewSize != null && currentInstance != null)
cameraOpenListener.onCameraOpened(currentCameraId, previewSize, currentInstance);
if (!TextUtils.isEmpty(currentCameraId) && previewSize != null)
cameraOpenListener.onCameraOpened(currentCameraId, previewSize, Camera2Manager.this);
}
});
}
@ -113,7 +99,7 @@ public final class Camera2Manager extends BaseCameraManager<String, TextureView.
@Override
public void onDisconnected(CameraDevice cameraDevice) {
cameraDevice.close();
currentInstance.cameraDevice = null;
Camera2Manager.this.cameraDevice = null;
uiHandler.post(new Runnable() {
@Override
@ -126,7 +112,7 @@ public final class Camera2Manager extends BaseCameraManager<String, TextureView.
@Override
public void onError(CameraDevice cameraDevice, int error) {
cameraDevice.close();
currentInstance.cameraDevice = null;
Camera2Manager.this.cameraDevice = null;
uiHandler.post(new Runnable() {
@Override
@ -136,7 +122,6 @@ public final class Camera2Manager extends BaseCameraManager<String, TextureView.
});
}
};
private CameraCaptureSession.CaptureCallback captureCallback
= new CameraCaptureSession.CaptureCallback() {
@ -155,14 +140,7 @@ public final class Camera2Manager extends BaseCameraManager<String, TextureView.
}
};
private Camera2Manager() {
}
public static Camera2Manager getInstance() {
if (currentInstance == null) currentInstance = new Camera2Manager();
return currentInstance;
}
private CameraFragmentResultListener callback;
@Override
public void initializeCameraManager(ConfigurationProvider configurationProvider, Context context) {
@ -259,9 +237,10 @@ public final class Camera2Manager extends BaseCameraManager<String, TextureView.
}
@Override
public void takePhoto(File photoFile, CameraPhotoListener cameraPhotoListener) {
public void takePhoto(File photoFile, CameraPhotoListener cameraPhotoListener, CameraFragmentResultListener callback) {
this.outputPath = photoFile;
this.cameraPhotoListener = cameraPhotoListener;
this.callback = callback;
backgroundHandler.post(new Runnable() {
@Override
@ -292,7 +271,7 @@ public final class Camera2Manager extends BaseCameraManager<String, TextureView.
closePreviewSession();
if (prepareVideoRecorder()) {
SurfaceTexture texture = currentInstance.texture;
SurfaceTexture texture = Camera2Manager.this.texture;
texture.setDefaultBufferSize(videoSize.getWidth(), videoSize.getHeight());
try {
@ -348,7 +327,7 @@ public final class Camera2Manager extends BaseCameraManager<String, TextureView.
}
@Override
public void stopVideoRecord() {
public void stopVideoRecord(final CameraFragmentResultListener callback) {
if (isVideoRecording)
backgroundHandler.post(new Runnable() {
@Override
@ -368,7 +347,7 @@ public final class Camera2Manager extends BaseCameraManager<String, TextureView.
uiHandler.post(new Runnable() {
@Override
public void run() {
cameraVideoListener.onVideoRecordStopped(outputPath);
cameraVideoListener.onVideoRecordStopped(outputPath, callback);
}
});
}
@ -376,8 +355,6 @@ public final class Camera2Manager extends BaseCameraManager<String, TextureView.
});
}
//--------------------Internal methods------------------
private void startPreview(SurfaceTexture texture) {
try {
if (texture == null) return;
@ -410,14 +387,16 @@ public final class Camera2Manager extends BaseCameraManager<String, TextureView.
}
}
//--------------------Internal methods------------------
@Override
protected void onMaxDurationReached() {
stopVideoRecord();
stopVideoRecord(callback);
}
@Override
protected void onMaxFileSizeReached() {
stopVideoRecord();
stopVideoRecord(callback);
}
@Override
@ -762,7 +741,8 @@ public final class Camera2Manager extends BaseCameraManager<String, TextureView.
uiHandler.post(new Runnable() {
@Override
public void run() {
cameraPhotoListener.onPhotoTaken(bytes, outputPath);
cameraPhotoListener.onPhotoTaken(bytes, outputPath, callback);
callback = null;
}
});
}
@ -841,4 +821,9 @@ public final class Camera2Manager extends BaseCameraManager<String, TextureView.
return array;
}
@IntDef({STATE_PREVIEW, STATE_WAITING_LOCK, STATE_WAITING_PRE_CAPTURE, STATE_WAITING_NON_PRE_CAPTURE, STATE_PICTURE_TAKEN})
@Retention(RetentionPolicy.SOURCE)
@interface CameraPreviewState {
}
}

@ -1,12 +1,14 @@
package com.github.florent37.camerafragment.internal.manager.listener;
import com.github.florent37.camerafragment.listeners.CameraFragmentResultListener;
import java.io.File;
/**
* Created by memfis on 8/14/16.
*/
public interface CameraPhotoListener {
void onPhotoTaken(byte[] bytes, File photoFile);
void onPhotoTaken(byte[] bytes, File photoFile, CameraFragmentResultListener callback);
void onPhotoTakeError();
}

@ -3,6 +3,7 @@ package com.github.florent37.camerafragment.internal.manager.listener;
import java.io.File;
import com.github.florent37.camerafragment.internal.utils.Size;
import com.github.florent37.camerafragment.listeners.CameraFragmentResultListener;
/**
* Created by memfis on 8/14/16.
@ -10,7 +11,7 @@ import com.github.florent37.camerafragment.internal.utils.Size;
public interface CameraVideoListener {
void onVideoRecordStarted(Size videoSize);
void onVideoRecordStopped(File videoFile);
void onVideoRecordStopped(File videoFile, CameraFragmentResultListener callback);
void onVideoRecordError();
}

@ -22,6 +22,7 @@ import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import com.github.florent37.camerafragment.CameraFragmentApi;
import com.github.florent37.camerafragment.R;
import com.github.florent37.camerafragment.configuration.Configuration;
import com.github.florent37.camerafragment.configuration.ConfigurationProvider;
@ -55,7 +56,7 @@ import java.io.File;
* Updated by Florent37
*/
public abstract class BaseAnncaFragment<CameraId> extends Fragment {
public abstract class BaseAnncaFragment<CameraId> extends Fragment implements CameraFragmentApi {
public static final String ARG_CONFIGURATION = "configuration";
public static final int MIN_VERSION_ICECREAM = Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1;
@ -191,22 +192,25 @@ public abstract class BaseAnncaFragment<CameraId> extends Fragment {
}
@Override
public void onPhotoTaken(byte[] bytes) {
public void onPhotoTaken(byte[] bytes, CameraFragmentResultListener callback) {
if (cameraFragmentResultListener != null) {
final String filePath = getCameraController().getOutputFile().toString();
final String filePath = cameraController.getOutputFile().toString();
cameraFragmentResultListener.onPhotoTaken(bytes, filePath);
if (callback != null) {
callback.onPhotoTaken(bytes, filePath);
}
}
}
@Override
public void onVideoRecordStart(int width, int height) {
final File outputFile = getCameraController().getOutputFile();
final File outputFile = cameraController.getOutputFile();
onStartVideoRecord(outputFile);
}
@Override
public void onVideoRecordStop() {
BaseAnncaFragment.this.onStopVideoRecord();
public void onVideoRecordStop(@Nullable CameraFragmentResultListener callback) {
BaseAnncaFragment.this.onStopVideoRecord(callback);
}
@Override
@ -252,15 +256,16 @@ public abstract class BaseAnncaFragment<CameraId> extends Fragment {
}
public void takePhotoOrCaptureVideo() {
@Override
public void takePhotoOrCaptureVideo(final CameraFragmentResultListener resultListener) {
switch (currentMediaActionState) {
case MediaAction.ACTION_PHOTO:
takePhoto();
takePhoto(resultListener);
break;
case MediaAction.ACTION_VIDEO:
switch (currentRecordState) {
case Record.RECORD_IN_PROGRESS_STATE:
stopRecording();
stopRecording(resultListener);
break;
default:
startRecording();
@ -303,11 +308,11 @@ public abstract class BaseAnncaFragment<CameraId> extends Fragment {
cameraController.onDestroy();
}
public void setMaxVideoFileSize(long maxVideoFileSize) {
protected void setMaxVideoFileSize(long maxVideoFileSize) {
this.maxVideoFileSize = maxVideoFileSize;
}
public void setMaxVideoDuration(int maxVideoDurationInMillis) {
protected void setMaxVideoDuration(int maxVideoDurationInMillis) {
final TimerTaskBase.Callback callback = new TimerTaskBase.Callback() {
@Override
public void setText(String text) {
@ -331,19 +336,30 @@ public abstract class BaseAnncaFragment<CameraId> extends Fragment {
}
}
@Override
public void openSettingDialog() {
final Context context = getContext();
AlertDialog.Builder builder = new AlertDialog.Builder(context);
if (currentMediaActionState == MediaAction.ACTION_VIDEO) {
builder.setSingleChoiceItems(videoQualities, getVideoOptionCheckedIndex(), getVideoOptionSelectedListener());
builder.setSingleChoiceItems(videoQualities, getVideoOptionCheckedIndex(), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int index) {
newQuality = ((VideoQualityOption) videoQualities[index]).getMediaQuality();
}
});
if (configurationProvider.getVideoFileSize() > 0)
builder.setTitle(String.format(getString(R.string.settings_video_quality_title),
"(Max " + String.valueOf(configurationProvider.getVideoFileSize() / (1024 * 1024) + " MB)")));
else
builder.setTitle(String.format(getString(R.string.settings_video_quality_title), ""));
} else {
builder.setSingleChoiceItems(photoQualities, getPhotoOptionCheckedIndex(), getPhotoOptionSelectedListener());
builder.setSingleChoiceItems(photoQualities, getPhotoOptionCheckedIndex(), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int index) {
newQuality = ((PhotoQualityOption) photoQualities[index]).getMediaQuality();
}
});
builder.setTitle(R.string.settings_photo_quality_title);
}
@ -356,7 +372,7 @@ public abstract class BaseAnncaFragment<CameraId> extends Fragment {
if (cameraFragmentControlsListener != null) {
cameraFragmentControlsListener.lockControls();
}
getCameraController().switchQuality();
cameraController.switchQuality();
}
}
});
@ -375,6 +391,7 @@ public abstract class BaseAnncaFragment<CameraId> extends Fragment {
settingsDialog.getWindow().setAttributes(layoutParams);
}
@Override
public void switchCameraType() {
if (cameraFragmentControlsListener != null) {
cameraFragmentControlsListener.lockControls();
@ -399,10 +416,11 @@ public abstract class BaseAnncaFragment<CameraId> extends Fragment {
break;
}
getCameraController().switchCamera(cameraFace);
this.cameraController.switchCamera(cameraFace);
}
public void switchAction() {
@Override
public void switchActionPhotoVideo() {
switch (currentMediaActionState) {
case MediaAction.ACTION_PHOTO:
currentMediaActionState = MediaAction.ACTION_VIDEO;
@ -419,6 +437,7 @@ public abstract class BaseAnncaFragment<CameraId> extends Fragment {
}
}
@Override
public void toggleFlashMode() {
switch (currentFlashMode) {
case Flash.FLASH_AUTO:
@ -439,17 +458,17 @@ public abstract class BaseAnncaFragment<CameraId> extends Fragment {
case Flash.FLASH_AUTO:
if (cameraFragmentStateListener != null) cameraFragmentStateListener.onFlashAuto();
configurationProvider.setFlashMode(Configuration.FLASH_MODE_AUTO);
getCameraController().setFlashMode(Configuration.FLASH_MODE_AUTO);
this.cameraController.setFlashMode(Configuration.FLASH_MODE_AUTO);
break;
case Flash.FLASH_ON:
if (cameraFragmentStateListener != null) cameraFragmentStateListener.onFlashOn();
configurationProvider.setFlashMode(Configuration.FLASH_MODE_ON);
getCameraController().setFlashMode(Configuration.FLASH_MODE_ON);
this.cameraController.setFlashMode(Configuration.FLASH_MODE_ON);
break;
case Flash.FLASH_OFF:
if (cameraFragmentStateListener != null) cameraFragmentStateListener.onFlashOff();
configurationProvider.setFlashMode(Configuration.FLASH_MODE_OFF);
getCameraController().setFlashMode(Configuration.FLASH_MODE_OFF);
this.cameraController.setFlashMode(Configuration.FLASH_MODE_OFF);
break;
}
}
@ -461,12 +480,7 @@ public abstract class BaseAnncaFragment<CameraId> extends Fragment {
rotateSettingsDialog(degrees);
}
@Record.RecordState
public int getRecordState() {
return currentRecordState;
}
public void setRecordState(@Record.RecordState int recordState) {
protected void setRecordState(@Record.RecordState int recordState) {
this.currentRecordState = recordState;
}
@ -493,12 +507,12 @@ public abstract class BaseAnncaFragment<CameraId> extends Fragment {
// }
//}
public void setFlashMode(@Flash.FlashMode int mode) {
protected void setFlashMode(@Flash.FlashMode int mode) {
this.currentFlashMode = mode;
onFlashModeChanged();
}
private void rotateSettingsDialog(int degrees) {
protected void rotateSettingsDialog(int degrees) {
if (settingsDialog != null && settingsDialog.isShowing() && Build.VERSION.SDK_INT > 10) {
ViewGroup dialogView = (ViewGroup) settingsDialog.getWindow().getDecorView();
for (int i = 0; i < dialogView.getChildCount(); i++) {
@ -535,73 +549,51 @@ public abstract class BaseAnncaFragment<CameraId> extends Fragment {
return checkedIndex;
}
protected DialogInterface.OnClickListener getVideoOptionSelectedListener() {
return new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int index) {
newQuality = ((VideoQualityOption) videoQualities[index]).getMediaQuality();
}
};
}
protected DialogInterface.OnClickListener getPhotoOptionSelectedListener() {
return new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int index) {
newQuality = ((PhotoQualityOption) photoQualities[index]).getMediaQuality();
}
};
}
public void takePhoto() {
protected void takePhoto(CameraFragmentResultListener callback) {
if (Build.VERSION.SDK_INT > MIN_VERSION_ICECREAM) {
new MediaActionSound().play(MediaActionSound.SHUTTER_CLICK);
}
setRecordState(Record.TAKE_PHOTO_STATE);
getCameraController().takePhoto();
this.cameraController.takePhoto(callback);
if (cameraFragmentStateListener != null) {
cameraFragmentStateListener.onRecordStatePhoto();
}
}
public void startRecording() {
protected void startRecording() {
if (Build.VERSION.SDK_INT > MIN_VERSION_ICECREAM) {
new MediaActionSound().play(MediaActionSound.START_VIDEO_RECORDING);
}
setRecordState(Record.RECORD_IN_PROGRESS_STATE);
getCameraController().startVideoRecord();
this.cameraController.startVideoRecord();
if (cameraFragmentStateListener != null) {
cameraFragmentStateListener.onRecordStateVideoInProgress();
}
}
public void stopRecording() {
protected void stopRecording(CameraFragmentResultListener callback) {
if (Build.VERSION.SDK_INT > MIN_VERSION_ICECREAM) {
new MediaActionSound().play(MediaActionSound.STOP_VIDEO_RECORDING);
}
setRecordState(Record.READY_FOR_RECORD_STATE);
getCameraController().stopVideoRecord();
this.cameraController.stopVideoRecord(callback);
this.onStopVideoRecord();
this.onStopVideoRecord(callback);
if (cameraFragmentStateListener != null) {
cameraFragmentStateListener.onRecordStateVideoReadyForRecord();
}
}
public CameraController<CameraId> getCameraController() {
return cameraController;
}
public void clearCameraPreview() {
protected void clearCameraPreview() {
if (previewContainer != null)
previewContainer.removeAllViews();
}
public void setCameraPreview(View preview, Size previewSize) {
protected void setCameraPreview(View preview, Size previewSize) {
//onCameraControllerReady()
videoQualities = cameraController.getVideoQualityOptions();
photoQualities = cameraController.getPhotoQualityOptions();
@ -613,11 +605,11 @@ public abstract class BaseAnncaFragment<CameraId> extends Fragment {
previewContainer.setAspectRatio(previewSize.getHeight() / (double) previewSize.getWidth());
}
public void setMediaFilePath(final File mediaFile) {
protected void setMediaFilePath(final File mediaFile) {
this.mediaFilePath = mediaFile.toString();
}
public void onStartVideoRecord(final File mediaFile) {
protected void onStartVideoRecord(final File mediaFile) {
setMediaFilePath(mediaFile);
if (maxVideoFileSize > 0) {
@ -657,7 +649,7 @@ public abstract class BaseAnncaFragment<CameraId> extends Fragment {
}
}
public void onStopVideoRecord() {
protected void onStopVideoRecord(@Nullable CameraFragmentResultListener callback) {
if (cameraFragmentControlsListener != null) {
cameraFragmentControlsListener.allowRecord(false);
}
@ -679,24 +671,32 @@ public abstract class BaseAnncaFragment<CameraId> extends Fragment {
}
}
final String filePath = this.cameraController.getOutputFile().toString();
if (cameraFragmentResultListener != null) {
final String filePath = getCameraController().getOutputFile().toString();
cameraFragmentResultListener.onVideoRecorded(filePath);
}
if (callback != null) {
callback.onVideoRecorded(filePath);
}
}
@Override
public void setStateListener(CameraFragmentStateListener cameraFragmentStateListener) {
this.cameraFragmentStateListener = cameraFragmentStateListener;
}
@Override
public void setTextListener(CameraFragmentVideoRecordTextListener cameraFragmentVideoRecordTextListener) {
this.cameraFragmentVideoRecordTextListener = cameraFragmentVideoRecordTextListener;
}
@Override
public void setControlsListener(CameraFragmentControlsListener cameraFragmentControlsListener) {
this.cameraFragmentControlsListener = cameraFragmentControlsListener;
}
@Override
public void setResultListener(CameraFragmentResultListener cameraFragmentResultListener) {
this.cameraFragmentResultListener = cameraFragmentResultListener;
}

@ -18,13 +18,6 @@ import com.github.florent37.camerafragment.internal.utils.Utils;
*/
public class CameraSwitchView extends AppCompatImageButton {
@Nullable
private OnCameraTypeChangeListener onCameraTypeChangeListener;
public interface OnCameraTypeChangeListener {
void switchCameraType();
}
private Drawable frontCameraDrawable;
private Drawable rearCameraDrawable;
private int padding = 5;
@ -53,14 +46,6 @@ public class CameraSwitchView extends AppCompatImageButton {
DrawableCompat.setTintList(rearCameraDrawable.mutate(), ContextCompat.getColorStateList(context, R.drawable.switch_camera_mode_selector));
setBackgroundResource(R.drawable.circle_frame_background_dark);
setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
if (onCameraTypeChangeListener != null) {
onCameraTypeChangeListener.switchCameraType();
}
}
});
displayBackCamera();
padding = Utils.convertDipToPixels(context, padding);
@ -86,8 +71,4 @@ public class CameraSwitchView extends AppCompatImageButton {
}
}
}
public void setOnCameraTypeChangeListener(OnCameraTypeChangeListener listener) {
this.onCameraTypeChangeListener = listener;
}
}

@ -19,17 +19,10 @@ import com.github.florent37.camerafragment.R;
*/
public class FlashSwitchView extends ImageButton {
@Nullable
private FlashModeSwitchListener switchListener;
private Drawable flashOnDrawable;
private Drawable flashOffDrawable;
private Drawable flashAutoDrawable;
public interface FlashModeSwitchListener {
void toggleFlashMode();
}
public FlashSwitchView(@NonNull Context context) {
this(context, null);
}
@ -44,14 +37,6 @@ public class FlashSwitchView extends ImageButton {
private void init() {
setBackgroundColor(Color.TRANSPARENT);
setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
if (switchListener != null) {
switchListener.toggleFlashMode();
}
}
});
}
public void displayFlashOff() {
@ -66,10 +51,6 @@ public class FlashSwitchView extends ImageButton {
setImageDrawable(flashAutoDrawable);
}
public void setFlashSwitchListener(@NonNull FlashModeSwitchListener switchListener) {
this.switchListener = switchListener;
}
@Override
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);

Loading…
Cancel
Save