知乎专栏 |
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())); } }