我正在实现一个出勤功能,需要你采取当前的GPS位置和自拍.
这是简化的Replikin活动
public class CheckinActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityCheckinBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
binding.btnTakePicture.setOnClickListener(v -> {
CameraActivity.launch(CheckinActivity.this, 67);
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
String photoPath = CameraActivity.getResult(resultCode, data);
if (photoPath == null) return;
else {
// Display the captured image on ImageView
}
}
}
字符串
这是执行实际工作的Camera Activity
public class CameraActivity extends AppCompatActivity {
private PreviewView previewView;
private ListenableFuture<ProcessCameraProvider> cameraProviderFuture;
ActivityCameraBinding binding;
private int mLensFacing;
ProcessCameraProvider processCameraProvider;
public static void launch(Activity context) {
context.startActivityForResult(new Intent(context, CameraActivity.class), 67);
}
public static void launch(Activity context, int requestCode) {
context.startActivityForResult(new Intent(context, CameraActivity.class), requestCode);
}
public static String getResult(int resultCode, @Nullable Intent data) {
if (resultCode != RESULT_OK || data == null) return null;
return data.getStringExtra("IMG_PATH");
}
public static String getResult(int requestCode, int resultCode, @Nullable Intent data) {
if (requestCode != 67 || resultCode != RESULT_OK || data == null) return null;
return data.getStringExtra("IMG_PATH");
}
@SuppressLint("RestrictedApi")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityCameraBinding.inflate(getLayoutInflater());
previewView = binding.previewView;
setContentView(binding.getRoot());
cameraProviderFuture = ProcessCameraProvider.getInstance(this);
mLensFacing = CameraSelector.DEFAULT_BACK_CAMERA.getLensFacing();
cameraProviderFuture.addListener(new Runnable() {
@Override
public void run() {
try {
//ProcessCameraProvider cameraProvider = cameraProviderFuture.get();
processCameraProvider = cameraProviderFuture.get();
bindUsecase(processCameraProvider);
} catch (ExecutionException | InterruptedException e) {
e.printStackTrace();
}
}
}, ContextCompat.getMainExecutor(this));
binding.btnCameraSwitch.setOnClickListener(v -> {
switchCamera();
});
}
private void switchCamera(){
int newLensFacing;
if (mLensFacing == CameraSelector.LENS_FACING_FRONT){
newLensFacing = CameraSelector.LENS_FACING_BACK;
} else {
newLensFacing = CameraSelector.LENS_FACING_FRONT;
}
try {
if (processCameraProvider.hasCamera(CameraSelector.DEFAULT_FRONT_CAMERA)) {
mLensFacing = newLensFacing;
bindUsecase(processCameraProvider);
return;
}
}
catch (CameraInfoUnavailableException ce){
Toast.makeText(getApplicationContext(), "Camera is not found...", Toast.LENGTH_SHORT).show();
}
}
private void bindUsecase(@NonNull ProcessCameraProvider cameraProvider){
processCameraProvider.unbindAll();
ImageCapture imageCapture = new ImageCapture.Builder()
.setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
.setTargetResolution(new Size(1280, 720))
.build();
binding.btnCameraCapture.setOnClickListener(v -> {
String FILENAME_FORMAT = "ddMMyyyy_HHmmss";
ContentValues capturedContentValues = new ContentValues();
capturedContentValues.put(MediaStore.MediaColumns.DISPLAY_NAME,
"CC_"+new SimpleDateFormat(FILENAME_FORMAT, Locale.US).format(System.currentTimeMillis()));
capturedContentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DCIM+"/CoolCompany");
capturedContentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg");
ImageCapture.OutputFileOptions outputFileOptions1 = new ImageCapture.OutputFileOptions.Builder(getContentResolver(),
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
capturedContentValues).build();
imageCapture.takePicture(outputFileOptions1, ContextCompat.getMainExecutor(CameraActivity.this),
new ImageCapture.OnImageSavedCallback() {
@Override
public void onImageSaved(@NonNull ImageCapture.OutputFileResults output) {
Intent data = new Intent();
data.putExtra("IMG_PATH", getRealPathFromURI(CameraActivity.this, output.getSavedUri()));
setResult(RESULT_OK, data);
finish();
}
@Override
public void onError(@NonNull ImageCaptureException exc) {
Toast.makeText(getApplicationContext(), "Failed to save image: "+exc.getMessage(), Toast.LENGTH_SHORT).show();
}
});
});
Preview preview = new Preview.Builder().build();
CameraSelector cameraSelector = new CameraSelector.Builder()
.requireLensFacing(mLensFacing).build();
preview.setSurfaceProvider(previewView.getSurfaceProvider());
cameraProvider.bindToLifecycle(((LifecycleOwner) this), cameraSelector, imageCapture, preview);
}
private String getRealPathFromURI(Context mContext, Uri contentUri) {
String[] proj = { MediaStore.Images.Media.DATA };
CursorLoader loader = new CursorLoader(mContext, contentUri, proj, null, null, null);
Cursor cursor = loader.loadInBackground();
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
String result = cursor.getString(column_index);
cursor.close();
return result;
}
}
型
有时,一些三星用户(运行Android 11)抱怨应用程序崩溃后采取自拍.他们指出我这些行:
Stack trace:
java.lang.IllegalStateException: Image is already closed
at android.media.Image.throwISEIfImageIsInvalid(Image.java:71)
at android.media.ImageReader$SurfaceImage.getFormat(ImageReader.java:833)
at androidx.camera.core.AndroidImageProxy.getFormat(AndroidImageProxy.java:84)
at androidx.camera.core.ForwardingImageProxy.getFormat(ForwardingImageProxy.java:71)
at androidx.camera.core.ImageUtil.ImageToJpegByteArray(ImageUtil.java:53)
at androidx.camera.core.ImageSaver.run(ImageSaver.java:76)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1157)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
型
不确定崩溃是由相机库内部的一些bug引起的,还是不正确的使用它。我使用CameraX 1.2.3,因为1.3.0和更高版本会导致Gradle错误(可能与其他库冲突),我想避免依赖地狱。
1条答案
按热度按时间llmtgqce1#
对于考勤功能,简化的Check-in活动可以捕获当前的GPS位置和自拍照。由于1.3.0及更高版本的问题,使用CameraX 1.2.3调查崩溃,以避免Gradle错误和潜在的库冲突。