Skip to content
Snippets Groups Projects
Commit 06fd1374 authored by Adrien Béraud's avatar Adrien Béraud
Browse files

CameraActivity: make saving picture async, don't reencode

Change-Id: I11a5c6ce5ccdc16ae44cb768c61df75d3b6e0002
parent a36c22f2
No related branches found
No related tags found
No related merge requests found
......@@ -24,21 +24,31 @@ import android.hardware.Camera;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import androidx.annotation.NonNull;
import java.io.IOException;
public class CameraPreview extends SurfaceView implements
SurfaceHolder.Callback {
private SurfaceHolder mSurfaceHolder;
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private Camera mCamera;
// Constructor that obtains context and camera
@SuppressWarnings("deprecation")
public CameraPreview(Context context, Camera camera) {
public CameraPreview(Context context, @NonNull Camera camera) {
super(context);
this.mCamera = camera;
this.mSurfaceHolder = this.getHolder();
this.mSurfaceHolder.addCallback(this);
this.mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
mCamera = camera;
getHolder().addCallback(this);
}
public void stop() {
if (mCamera == null)
return;
try {
mCamera.stopPreview();
} catch (Exception e) {
// intentionally left blank
}
mCamera.release();
mCamera = null;
}
@Override
......@@ -48,22 +58,18 @@ public class CameraPreview extends SurfaceView implements
try {
mCamera.setPreviewDisplay(surfaceHolder);
mCamera.startPreview();
} catch (IOException e) {
} catch (Exception e) {
// left blank for now
}
}
@Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
if (mCamera == null)
return;
mCamera.stopPreview();
mCamera.release();
stop();
}
@Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int format,
int width, int height) {
public void surfaceChanged(SurfaceHolder surfaceHolder, int format, int width, int height) {
if (mCamera == null)
return;
try {
......
......@@ -25,17 +25,15 @@ package cx.ring.tv.camera;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.hardware.Camera;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraManager;
import android.media.CamcorderProfile;
import android.media.MediaRecorder;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.Toast;
......@@ -53,14 +51,18 @@ import butterknife.OnClick;
import cx.ring.R;
import cx.ring.utils.AndroidFileUtils;
import cx.ring.utils.ContentUriHandler;
import io.reactivex.Single;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
public class CustomCameraActivity extends Activity {
public static final String TYPE_IMAGE = "image/png";
private static final String TAG = "CustomCameraActivity";
public static final String TYPE_IMAGE = "image/jpeg";
public static final String TYPE_VIDEO = "video";
int cameraFront = -1;
int cameraBack = -1;
int currentCamera = 0;
private int cameraFront = -1;
private int cameraBack = -1;
private int currentCamera = 0;
private MediaRecorder recorder;
private boolean mRecording = false;
......@@ -75,53 +77,52 @@ public class CustomCameraActivity extends Activity {
private Camera mCamera;
private CameraPreview mCameraPreview;
private final Camera.PictureCallback mPicture = (input, camera) -> {
if (mRecording) {
releaseMediaRecorder();
}
Intent intent = new Intent();
int result = RESULT_OK;
Bitmap photo = BitmapFactory.decodeByteArray(input, 0, input.length);
try {
File tempFile = AndroidFileUtils.createImageFile(this);
try (OutputStream outStream = new FileOutputStream(tempFile)) {
photo.compress(Bitmap.CompressFormat.PNG, 100, outStream);
outStream.flush();
private final Camera.PictureCallback mPicture = (input, camera) -> Single.fromCallable(() -> {
mCameraPreview.stop();
File file = AndroidFileUtils.createImageFile(this);
try (OutputStream out = new FileOutputStream(file)) {
out.write(input);
out.flush();
}
intent.putExtra(MediaStore.EXTRA_OUTPUT, ContentUriHandler.getUriForFile(this, ContentUriHandler.AUTHORITY_FILES, tempFile));
intent.setType(TYPE_IMAGE);
} catch (IOException e) {
e.printStackTrace();
result = RESULT_CANCELED;
}
if (getParent() == null) {
setResult(result, intent);
} else {
getParent().setResult(result, intent);
}
finish();
};
return ContentUriHandler.getUriForFile(this, ContentUriHandler.AUTHORITY_FILES, file);
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(uri -> {
setResult(RESULT_OK, new Intent()
.putExtra(MediaStore.EXTRA_OUTPUT, uri)
.setType(TYPE_IMAGE));
finish();
}, e -> {
Log.e(TAG, "Error saving picture", e);
setResult(RESULT_CANCELED);
finish();
});
@OnClick(R.id.button_picture)
public void takePicture() {
if (mRecording)
releaseMediaRecorder();
if (mCamera != null) {
mCamera.takePicture(null, null, mPicture);
mButtonPicture.setEnabled(false);
mButtonVideo.setVisibility(View.GONE);
try {
mCamera.takePicture(null, null, mPicture);
} catch (Exception e) {
Log.w(TAG, "Error taking picture", e);
}
}
}
@OnClick(R.id.button_video)
public void takeVideo() {
if (mRecording){
if (mRecording) {
releaseMediaRecorder();
Intent intent = new Intent();
Uri uri = ContentUriHandler.getUriForFile(this, ContentUriHandler.AUTHORITY_FILES, mVideoFile);
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
intent.setType(TYPE_VIDEO);
if (getParent() == null) {
setResult(RESULT_OK, intent);
} else {
getParent().setResult(RESULT_OK, intent);
}
mCameraPreview.stop();
Intent intent = new Intent()
.putExtra(MediaStore.EXTRA_OUTPUT, ContentUriHandler.getUriForFile(this, ContentUriHandler.AUTHORITY_FILES, mVideoFile))
.setType(TYPE_VIDEO);
setResult(RESULT_OK, intent);
finish();
mButtonVideo.setImageResource(R.drawable.baseline_videocam_24);
return;
......@@ -155,7 +156,7 @@ public class CustomCameraActivity extends Activity {
}
mCameraPreview = new CameraPreview(this, mCamera);
FrameLayout preview = findViewById(R.id.camera_preview);
preview.addView(mCameraPreview);
preview.addView(mCameraPreview, 0);
if (mActionVideo) {
mButtonVideo.setVisibility(View.VISIBLE);
......
......@@ -187,8 +187,8 @@ public class TvConversationFragment extends BaseSupportFragment<TvConversationPr
ImageButton video = view.findViewById(R.id.button_video);
video.setOnClickListener(v -> {
Intent intent = new Intent(getActivity(), CustomCameraActivity.class);
intent.setAction(MediaStore.ACTION_VIDEO_CAPTURE);
Intent intent = new Intent(getActivity(), CustomCameraActivity.class)
.setAction(MediaStore.ACTION_VIDEO_CAPTURE);
startActivityForResult(intent, REQUEST_CODE_PHOTO);
});
......
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/camera_preview"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="@+id/camera_preview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<LinearLayout
android:layout_width="match_parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:gravity="center"
android:layout_gravity="bottom|center_horizontal"
android:orientation="horizontal">
<com.google.android.material.floatingactionbutton.FloatingActionButton
......@@ -33,12 +28,12 @@
android:layout_height="wrap_content"
android:contentDescription="@string/action_call_decline"
android:padding="16dp"
android:visibility="gone"
app:backgroundTint="@color/green_500"
app:rippleColor="@android:color/white"
app:srcCompat="@drawable/baseline_videocam_24"
app:useCompatPadding="true"
android:visibility="gone" />
app:useCompatPadding="true" />
</LinearLayout>
</RelativeLayout>
\ No newline at end of file
</FrameLayout>
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment