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 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 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; } }