| 知乎专栏 |
https://developer.android.google.cn/codelabs/camerax-getting-started?hl=zh-cn#0
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.home.HomeFragment">
<androidx.camera.view.PreviewView
android:id="@+id/previewView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<Button
android:id="@+id/captureButton"
android:layout_width="110dp"
android:layout_height="wrap_content"
android:layout_marginBottom="50dp"
android:layout_marginEnd="50dp"
android:elevation="2dp"
android:text="拍摄"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintEnd_toStartOf="@id/vertical_centerline" />
<Button
android:id="@+id/cameraSelectorButton"
android:layout_width="110dp"
android:layout_height="wrap_content"
android:layout_marginBottom="50dp"
android:layout_marginStart="50dp"
android:elevation="2dp"
android:text="前后镜头"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/vertical_centerline" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/vertical_centerline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent=".50" />
</androidx.constraintlayout.widget.ConstraintLayout>
package cn.aigcsst.medical.ui.home;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.util.Size;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.camera.core.Camera;
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.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import com.google.common.util.concurrent.ListenableFuture;
import java.io.File;
import java.util.concurrent.ExecutionException;
import cn.aigcsst.medical.R;
import cn.aigcsst.medical.databinding.FragmentHomeBinding;
import cn.aigcsst.medical.ui.gallery.GalleryFragment;
public class HomeFragment extends Fragment {
private static final String TAG = HomeFragment.class.getSimpleName();
private static final int REQUEST_CODE = 200;
Preview preview = new Preview.Builder().build();
boolean switchCameraFrontBack = true;
ImageAnalysis imageAnalysis = new ImageAnalysis.Builder().setTargetResolution(new Size(1280, 720)).build();
private FragmentHomeBinding binding;
private ListenableFuture<ProcessCameraProvider> cameraProviderFuture;
private ProcessCameraProvider cameraProvider;
public View onCreateView(@NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
HomeViewModel homeViewModel =
new ViewModelProvider(this).get(HomeViewModel.class);
binding = FragmentHomeBinding.inflate(inflater, container, false);
View root = binding.getRoot();
// final TextView textView = binding.textHome;
// homeViewModel.getText().observe(getViewLifecycleOwner(), textView::setText);
binding.previewView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return false;
}
});
return root;
}
@Override
public void onDestroyView() {
super.onDestroyView();
binding = null;
}
@Override
public void onDestroy() {
super.onDestroy();
if (cameraProvider != null) {
cameraProvider.unbindAll();
}
}
@Override
public void onPause() {
super.onPause();
//出去的时候要释放相机资源
if (cameraProvider != null) {
cameraProvider.unbindAll();
}
}
@Override
public void onResume() {
super.onResume();
// ListenableFuture<ProcessCameraProvider> processCameraProvider = ProcessCameraProvider.getInstance(this);
cameraProviderFuture = ProcessCameraProvider.getInstance(requireContext());
binding.captureButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d(TAG, "Shut");
try {
ImageCapture imageCapture = new ImageCapture.Builder().setTargetRotation(requireView().getDisplay().getRotation()).build();
cameraProvider = cameraProviderFuture.get();
cameraProvider.bindToLifecycle(getViewLifecycleOwner(), CameraSelector.DEFAULT_FRONT_CAMERA, imageAnalysis, imageCapture);
// cameraProviderFuture.bindToLifecycle(lifecycleOwner, cameraSelector, imageCapture, imageAnalysis, preview);
// File file = new File(Environment.getExternalStorageDirectory() + "/" + System.currentTimeMillis() + ".png");
File file = new File(getContext().getExternalFilesDir(Environment.DIRECTORY_PICTURES) + "/" + System.currentTimeMillis() + ".jpg");
Log.d(TAG, file.getAbsolutePath());
ImageCapture.OutputFileOptions outputFileOptions = new ImageCapture.OutputFileOptions.Builder(file).build();
// ScheduledExecutorService cameraExecutor = CameraXExecutors.mainThreadExecutor();
imageCapture.takePicture(outputFileOptions, ContextCompat.getMainExecutor(requireContext()), new ImageCapture.OnImageSavedCallback() {
@Override
public void onImageSaved(ImageCapture.OutputFileResults outputFileResults) {
// insert your code here.
Toast.makeText(requireContext(), outputFileResults.getSavedUri().toString(), Toast.LENGTH_SHORT).show();
Log.d(TAG, "onImageSaved: saved");
GalleryFragment fragment = GalleryFragment.newInstance(outputFileResults.getSavedUri().toString());
requireActivity().getSupportFragmentManager().beginTransaction().replace(R.id.nav_host_fragment_content_main, fragment).addToBackStack("HomeFragment").commit();
// requireActivity().getSupportFragmentManager().beginTransaction()
// .replace(R.id.nav_host_fragment_content_main, GalleryFragment.newInstance(outputFileResults.getSavedUri().toString()))
//// .addToBackStack("GalleryFragment")
// .commit();
// getView().findViewById(R.id.play_btn).setOnClickListener(v -> {
cameraProvider.unbindAll();
//
// Bundle bundle = new Bundle();
// bundle.putString("image", outputFileResults.getSavedUri().toString());
// Navigation.findNavController(requireView()).navigate(R.id.nav_gallery, bundle);
// });
}
@Override
public void onError(@NonNull ImageCaptureException error) {
// insert your code here.
Log.d(TAG, "onImageSaved: saved" + error.getMessage());
}
}
);
} catch (Exception e) {
e.printStackTrace();
}
}
});
binding.cameraSelectorButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// CameraSelector cameraSelector = new CameraSelector.Builder()
// .requireLensFacing(CameraSelector.LENS_FACING_BACK)
// .build();
CameraSelector cameraSelector;
if (switchCameraFrontBack) {
cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA;
switchCameraFrontBack = false;
} else {
cameraSelector = CameraSelector.DEFAULT_FRONT_CAMERA;
switchCameraFrontBack = true;
}
// preview.setSurfaceProvider(binding.previewView.getSurfaceProvider());
cameraProvider.unbindAll();
Camera camera = cameraProvider.bindToLifecycle(getViewLifecycleOwner(), cameraSelector, preview);
}
});
//回来的时候要重新绑定一下:
cameraProviderFuture.addListener(() -> {
try {
cameraProvider = cameraProviderFuture.get();
// Preview preview = new Preview.Builder().build();
// CameraSelector cameraSelector = new CameraSelector.Builder()
//// .requireLensFacing(CameraSelector.LENS_FACING_BACK)
// .requireLensFacing(CameraSelector.LENS_FACING_FRONT)
// .build();
cameraProvider.unbindAll();
CameraSelector cameraSelector = CameraSelector.DEFAULT_FRONT_CAMERA;
preview.setSurfaceProvider(binding.previewView.getSurfaceProvider());
Camera camera = cameraProvider.bindToLifecycle(getViewLifecycleOwner(), cameraSelector, preview);
// bindPreview(cameraProvider);
} catch (ExecutionException | InterruptedException e) {
// No errors need to be handled for this Future.
// This should never be reached.
}
}, ContextCompat.getMainExecutor(requireContext()));
}
}