|
|
|
|
package com.xypower.mppreview.ui;
|
|
|
|
|
|
|
|
|
|
import static java.lang.System.loadLibrary;
|
|
|
|
|
|
|
|
|
|
import androidx.annotation.NonNull;
|
|
|
|
|
import androidx.appcompat.app.AppCompatActivity;
|
|
|
|
|
import androidx.camera.core.CameraInfo;
|
|
|
|
|
import androidx.camera.core.CameraSelector;
|
|
|
|
|
import androidx.camera.core.ImageAnalysis;
|
|
|
|
|
import androidx.camera.core.ImageCapture;
|
|
|
|
|
import androidx.camera.core.ImageCaptureException;
|
|
|
|
|
import androidx.camera.core.Preview;
|
|
|
|
|
import androidx.camera.lifecycle.ProcessCameraProvider;
|
|
|
|
|
import androidx.camera.view.PreviewView;
|
|
|
|
|
import androidx.core.content.ContextCompat;
|
|
|
|
|
|
|
|
|
|
import android.net.Uri;
|
|
|
|
|
import android.os.Bundle;
|
|
|
|
|
import android.util.Log;
|
|
|
|
|
import android.view.View;
|
|
|
|
|
import android.widget.Toast;
|
|
|
|
|
|
|
|
|
|
import com.google.common.util.concurrent.ListenableFuture;
|
|
|
|
|
import com.xypower.mppreview.MyAnalyzer;
|
|
|
|
|
import com.xypower.mppreview.R;
|
|
|
|
|
import com.xypower.mppreview.bean.Contants;
|
|
|
|
|
import com.xypower.mppreview.databinding.ActivityCameraChannelBinding;
|
|
|
|
|
|
|
|
|
|
import java.io.File;
|
|
|
|
|
import java.text.SimpleDateFormat;
|
|
|
|
|
import java.util.List;
|
|
|
|
|
import java.util.Locale;
|
|
|
|
|
import java.util.concurrent.ExecutorService;
|
|
|
|
|
import java.util.concurrent.Executors;
|
|
|
|
|
|
|
|
|
|
public class CameraChannelActivity extends AppCompatActivity implements View.OnClickListener {
|
|
|
|
|
|
|
|
|
|
static {
|
|
|
|
|
loadLibrary("mppreview");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private com.xypower.mppreview.databinding.ActivityCameraChannelBinding viewBinding;
|
|
|
|
|
private int camerid;
|
|
|
|
|
private ImageCapture imageCapture;
|
|
|
|
|
private ExecutorService cameraExecutor;
|
|
|
|
|
private File outputDirectory;
|
|
|
|
|
|
|
|
|
|
private static native void setInt(int cmd, int val);
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
protected void onCreate(Bundle savedInstanceState) {
|
|
|
|
|
super.onCreate(savedInstanceState);
|
|
|
|
|
viewBinding = ActivityCameraChannelBinding.inflate(getLayoutInflater());
|
|
|
|
|
setContentView(viewBinding.getRoot());
|
|
|
|
|
camerid = getIntent().getIntExtra(Contants.CAMERAID, 0);
|
|
|
|
|
initEvent();
|
|
|
|
|
|
|
|
|
|
// 设置照片等保存的位置
|
|
|
|
|
outputDirectory = getOutputDirectory();
|
|
|
|
|
|
|
|
|
|
cameraExecutor = Executors.newSingleThreadExecutor();
|
|
|
|
|
|
|
|
|
|
startCamera(camerid);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
protected void onDestroy() {
|
|
|
|
|
super.onDestroy();
|
|
|
|
|
cameraExecutor.shutdown();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void initEvent() {
|
|
|
|
|
viewBinding.imageCaptureButton.setOnClickListener(this);
|
|
|
|
|
viewBinding.foward.setOnClickListener(this);
|
|
|
|
|
viewBinding.back.setOnClickListener(this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void onClick(View v) {
|
|
|
|
|
switch (v.getId()) {
|
|
|
|
|
case R.id.image_capture_button:
|
|
|
|
|
takePhoto();
|
|
|
|
|
break;
|
|
|
|
|
case R.id.foward:
|
|
|
|
|
setInt(311, 101);
|
|
|
|
|
break;
|
|
|
|
|
case R.id.back:
|
|
|
|
|
setInt(311, 201);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void startCamera(int cameraid) {
|
|
|
|
|
// 将Camera的生命周期和Activity绑定在一起(设定生命周期所有者),这样就不用手动控制相机的启动和关闭。
|
|
|
|
|
ListenableFuture<ProcessCameraProvider> cameraProviderFuture = ProcessCameraProvider.getInstance(this);
|
|
|
|
|
|
|
|
|
|
cameraProviderFuture.addListener(() -> {
|
|
|
|
|
try {
|
|
|
|
|
// 将你的相机和当前生命周期的所有者绑定所需的对象
|
|
|
|
|
ProcessCameraProvider processCameraProvider = cameraProviderFuture.get();
|
|
|
|
|
|
|
|
|
|
// 创建一个Preview 实例,并设置该实例的 surface 提供者(provider)。
|
|
|
|
|
PreviewView viewFinder = viewBinding.viewFinder;
|
|
|
|
|
Preview preview = new Preview.Builder().build();
|
|
|
|
|
preview.setSurfaceProvider(viewFinder.getSurfaceProvider());
|
|
|
|
|
|
|
|
|
|
// 选择后置摄像头作为默认摄像头
|
|
|
|
|
// CameraSelector cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA;
|
|
|
|
|
|
|
|
|
|
List<CameraInfo> availableCameraInfos = processCameraProvider.getAvailableCameraInfos();
|
|
|
|
|
CameraInfo cameraInfo = availableCameraInfos.get(cameraid);
|
|
|
|
|
CameraSelector cameraSelector = cameraInfo.getCameraSelector();
|
|
|
|
|
|
|
|
|
|
// 创建拍照所需的实例
|
|
|
|
|
imageCapture = new ImageCapture.Builder().build();
|
|
|
|
|
|
|
|
|
|
// 设置预览帧分析
|
|
|
|
|
ImageAnalysis imageAnalysis = new ImageAnalysis.Builder().build();
|
|
|
|
|
imageAnalysis.setAnalyzer(cameraExecutor, new MyAnalyzer());
|
|
|
|
|
|
|
|
|
|
// 重新绑定用例前先解绑
|
|
|
|
|
processCameraProvider.unbindAll();
|
|
|
|
|
|
|
|
|
|
// 绑定用例至相机
|
|
|
|
|
processCameraProvider.bindToLifecycle(CameraChannelActivity.this, cameraSelector, preview, imageCapture, imageAnalysis);
|
|
|
|
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
Log.e(Contants.TAG, "用例绑定失败!" + e);
|
|
|
|
|
}
|
|
|
|
|
}, ContextCompat.getMainExecutor(this));
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void takePhoto() {
|
|
|
|
|
// 确保imageCapture 已经被实例化, 否则程序将可能崩溃
|
|
|
|
|
if (imageCapture != null) {
|
|
|
|
|
// 创建带时间戳的输出文件以保存图片,带时间戳是为了保证文件名唯一
|
|
|
|
|
File photoFile = new File(outputDirectory, new SimpleDateFormat(Contants.FILENAME_FORMAT, Locale.SIMPLIFIED_CHINESE).format(System.currentTimeMillis()) + ".jpg");
|
|
|
|
|
|
|
|
|
|
// 创建 output option 对象,用以指定照片的输出方式
|
|
|
|
|
ImageCapture.OutputFileOptions outputFileOptions = new ImageCapture.OutputFileOptions.Builder(photoFile).build();
|
|
|
|
|
|
|
|
|
|
// 执行takePicture(拍照)方法
|
|
|
|
|
imageCapture.takePicture(outputFileOptions, ContextCompat.getMainExecutor(this), new ImageCapture.OnImageSavedCallback() {// 保存照片时的回调
|
|
|
|
|
@Override
|
|
|
|
|
public void onImageSaved(@NonNull ImageCapture.OutputFileResults outputFileResults) {
|
|
|
|
|
Uri savedUri = Uri.fromFile(photoFile);
|
|
|
|
|
String msg = "照片捕获成功! " + savedUri;
|
|
|
|
|
Toast.makeText(getBaseContext(), msg, Toast.LENGTH_SHORT).show();
|
|
|
|
|
Log.d(Contants.TAG, msg);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void onError(@NonNull ImageCaptureException exception) {
|
|
|
|
|
Log.e(Contants.TAG, "Photo capture failed: " + exception.getMessage());
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private File getOutputDirectory() {
|
|
|
|
|
File mediaDir = new File(getExternalMediaDirs()[0], getString(R.string.app_name));
|
|
|
|
|
boolean isExist = mediaDir.exists() || mediaDir.mkdir();
|
|
|
|
|
return isExist ? mediaDir : null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|