如何获取 CameraControl 和 CameraInfo
How to get CameraControl and CameraInfo
我是初级 Android 开发人员。
我使用的是 CameraX 的最新版本 (alpha08)。
我正在尝试设置缩放功能,为此我需要 CameraControl。
要获得 CameraControl,我需要一个 Camera 实例 -> Camera.getCameraControl() 根据 https://developer.android.com/reference/androidx/camera/core/CameraControl
我似乎无法获取 Camera 的实例。如果我尝试实例化 Camera,它会要求我实现 getCameraControl() 和 getCameraInfo(),它们都 return null.
谁能告诉我怎么做?
这是我的 ApplicationClass 文件
public class ApplicationClass extends Application implements CameraXConfig.Provider {
@NonNull
@Override
public CameraXConfig getCameraXConfig() {
return Camera2Config.defaultConfig();
}
}
我的 startCamera() 函数进入我的 CameraActivity
private void startCamera() {
CameraSelector mCameraSelector = CameraSelector.DEFAULT_BACK_CAMERA;
mFlashToggle.setVisibility(View.VISIBLE);
mGalleryFAB.setVisibility(View.VISIBLE);
mTakePhotoFAB.setVisibility(View.VISIBLE);
Point mSize = new Point();
Display mDisplay = getWindowManager().getDefaultDisplay();
mDisplay.getSize(mSize);
int mWidth = mSize.x;
int mHeight = mSize.y;
Preview mPreview = new Preview.Builder()
.setTargetResolution(new Size(mWidth, mHeight))
.build();
mPreview.setPreviewSurfaceProvider(mCameraPP.getPreviewSurfaceProvider());
ImageCapture mImageCapture = new ImageCapture.Builder()
.setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
.setTargetRotation(getWindowManager().getDefaultDisplay().getRotation())
.setTargetResolution(new Size(mWidth, mHeight))
.build();
// FLASHLIGHT PART
mFlashToggle.getBackground().setAlpha(0);
mFlashToggle.setOnClickListener(new View.OnClickListener() {
boolean mIsActivated = true;
@Override
public void onClick(View v) {
if (mIsActivated) {
mImageCapture.setFlashMode(ImageCapture.FLASH_MODE_ON);
mFlashToggle.setColorFilter(getResources().getColor(R.color.conforme));
mFlashToggle.getBackground().setAlpha(0);
mIsActivated = false;
} else {
mImageCapture.setFlashMode(ImageCapture.FLASH_MODE_OFF);
mFlashToggle.setColorFilter(getResources().getColor(R.color.black));
mFlashToggle.getBackground().setAlpha(0);
mIsActivated = true;
}
}
});
// CLICK ON TAKE PHOTO BUTTON TRIGGERS THIS
mTakePhotoFAB.setOnClickListener(view -> {
mDir = new File(getExternalCacheDir(), "PhotosAuthentifier");
boolean success = true;
if (!mDir.exists()) {
success = mDir.mkdir();
}
if (success) {
File mFile = new File(mDir, new SimpleDateFormat("yyyyMMdd-HHmmss", Locale.getDefault()).format(new Date()) + ".jpg");
mImageCapture.takePicture(mFile, command -> new Thread(command).start(),
new ImageCapture.OnImageSavedCallback() {
@Override
public void onImageSaved(@NonNull File file) {
runOnUiThread(() -> {
// ADD PHOTO INTO FINAL TAB
mListOfPhotos.add(file.getAbsolutePath());
// UPDATE PREVIEW OF PHOTOS ON SCREEN
mAdapter.setmListOfPhotos(mListOfPhotos);
mRecyclerView.setAdapter(mAdapter);
if (mListOfPhotos.size() < 3) {
actualNumberOfPhoto();
} else {
actualNumberOfPhoto();
}
});
}
@Override
public void onError(int imageCaptureError, @NonNull String message, @Nullable Throwable cause) {
String mMessage = "Photo capture failed: " + message;
Toast.makeText(CameraActivity.this, mMessage, Toast.LENGTH_SHORT).show();
assert cause != null;
cause.printStackTrace();
}
});
}
});
// CLICK ON SEND BUTTON TRIGGERS THIS
mSendPhotoFAB.setOnClickListener(view -> {
if (mSendPhotoFAB.isClickable()) {
mSendPhotoFAB.setClickable(false);
AlertDialog.Builder mAlertDialogBuilder = new AlertDialog.Builder(CameraActivity.this);
String mMessage = null;
if (sIDDemande == 0) {
LayoutInflater mInflater = this.getLayoutInflater();
View mDialogView = mInflater.inflate(R.layout.activity_camera_parameters, null);
// Parameters initialization
mDescriptionET = mDialogView.findViewById(R.id.activityCameraParametersDescriptionET);
mLanguageSpinner = mDialogView.findViewById(R.id.activityCameraSpecimenLanguageSpinner);
mMarkerYesButton = mDialogView.findViewById(R.id.activityCameraMarkerYesButton);
mMarkerNoButton = mDialogView.findViewById(R.id.activityCameraMarkerNoButton);
mMarkerInfoIB = mDialogView.findViewById(R.id.activityCameraMarkerInfoIB);
TextView mMarkerTV = mDialogView.findViewById(R.id.activityCamera15CreditTV);
TextView mMarkerInfoTV = mDialogView.findViewById(R.id.activityCameraMarkerInfoTV);
mSerialNumberET = mDialogView.findViewById(R.id.activityCameraSerialNumberET);
mModelNameET = mDialogView.findViewById(R.id.activityCameraModelNameET);
mAlertDialogBuilder.setView(mDialogView);
// OPTIONAL PARAMETERS FORM
if (sIDDemande == 0) {
ArrayAdapter<String> mSpinnerAdapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item);
mSpinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mLanguageSpinner.setAdapter(mSpinnerAdapter);
mSpinnerAdapter.add(getResources().getString(R.string.french));
mSpinnerAdapter.add(getResources().getString(R.string.english));
mSpinnerAdapter.notifyDataSetChanged();
//To make Description part scrollable
mDescriptionET.setOnTouchListener((v, event) -> {
if (mDescriptionET.hasFocus()) {
v.getParent().requestDisallowInterceptTouchEvent(true);
if ((event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_SCROLL) {
v.getParent().requestDisallowInterceptTouchEvent(false);
return true;
}
}
return false;
});
// Default specimen language is defined according to app language
String mLanguage = LocaleHelper.getLanguage(this).getString(LocaleHelper.SELECTED_LANGUAGE, null);
if (mLanguage != null) {
if (mLanguage.equals("fr")) {
mLanguageSpinner.setSelection(0);
} else if (mLanguage.equals("en")) {
mLanguageSpinner.setSelection(1);
}
}
mMarkerInfoIB.setOnClickListener(v -> {
if (!mMarkerInfoIsClicked) {
mMarkerInfoTV.setVisibility(View.VISIBLE);
mMarkerInfoIsClicked = true;
} else {
mMarkerInfoTV.setVisibility(View.GONE);
mMarkerInfoIsClicked = false;
}
});
mMarkerNoButton.setBackgroundColor(getResources().getColor(R.color.authentifier));
mMarkerYesButton.setBackgroundColor(getResources().getColor(R.color.text_color));
mMarkerYesButton.setOnClickListener(v -> {
if (!mMarkerYesClicked) {
mMarkerYesButton.setBackgroundColor(getResources().getColor(R.color.authentifier));
mMarkerNoButton.setBackgroundColor(getResources().getColor(R.color.text_color));
mMarkerTV.setVisibility(View.VISIBLE);
mMarkerYesClicked = true;
}
});
mMarkerNoButton.setOnClickListener(v -> {
if (mMarkerYesClicked) {
mMarkerNoButton.setBackgroundColor(getResources().getColor(R.color.authentifier));
mMarkerYesButton.setBackgroundColor(getResources().getColor(R.color.text_color));
mMarkerTV.setVisibility(View.GONE);
mMarkerYesClicked = false;
}
});
if (mAlertDialog != null) {
Objects.requireNonNull(mAlertDialog.getWindow()).setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
}
}
}
if (sIDDemande != 0) {
mMessage = getResources().getString(R.string.validationBeforePursue);
}
mAlertDialogBuilder
.setTitle(R.string.activityCameraParametersTitle)
.setCancelable(false)
.setMessage(mMessage)
.setPositiveButton(R.string.yes, (dialog, which) -> {
((AlertDialog) dialog).getButton(which).setClickable(false);
dialog.dismiss();
if (sIDDemande != 0) {
new AsyncTaskSendComplementaryPhotos(sCameraActivity, sCameraActivity.getApplicationContext()).execute();
} else {
if (mDescriptionET.getText() != null && !mDescriptionET.getText().toString().equals("")) {
mMapApplication.put(ConstantsClass.APPLICATION_DESCRIPTION, mDescriptionET.getText().toString());
}
if (mSerialNumberET.getText() != null && !mSerialNumberET.getText().toString().equals("")) {
mMapApplication.put(ConstantsClass.SERIAL_NUMBER, mSerialNumberET.getText().toString());
}
if (mModelNameET.getText() != null && !mModelNameET.getText().toString().equals("")) {
mMapApplication.put(ConstantsClass.MODEL_NAME, mModelNameET.getText().toString());
}
String mSpinnerValue = mLanguageSpinner.getSelectedItem().toString();
if (mSpinnerValue.equals("French")) {
mSpinnerValue = "Français";
}
if (mSpinnerValue.equals("English")) {
mSpinnerValue = "Anglais";
}
mMapApplication.put(ConstantsClass.LANGUAGE_SPECIMEN, mSpinnerValue);
if (mMarkerYesClicked) {
mMapApplication.put(ConstantsClass.MARKER, "OUI");
} else {
mMapApplication.put(ConstantsClass.MARKER, "NON");
}
new AsyncTaskSendData(sCameraActivity).execute();
}
})
.setNegativeButton(R.string.no, (dialogInterface, i) -> {
dialogInterface.dismiss();
mSendPhotoFAB.setClickable(true);
});
mAlertDialog = mAlertDialogBuilder.create();
mAlertDialog.show();
} else {
Toast mToast = Toast.makeText(this, getResources().getString(R.string.waitingMessageBeforeParameters), Toast.LENGTH_LONG);
View mToastView = mToast.getView();
mToastView.setBackgroundColor(getResources().getColor(R.color.authentifier));
mToast.setGravity(Gravity.CENTER, 0, 0);
mToast.show();
}
});
// CLICK ON GALLERY BUTTON TRIGGERS THIS
mGalleryFAB.setOnClickListener(view -> {
checkPermissions();
if (mPermission) {
Intent mIntentGallery = new Intent(Intent.ACTION_PICK);
mIntentGallery.setType("image/*");
startActivityForResult(mIntentGallery, GALLERY_REQUEST);
}
});
ImageAnalysis mAnalysis = new ImageAnalysis.Builder()
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
.build();
mCameraProviderFuture.addListener(() -> {
try {
mCameraProvider = mCameraProviderFuture.get();
} catch (ExecutionException | InterruptedException e) {
e.printStackTrace();
}
assert mCameraProvider != null;
mCameraProvider.bindToLifecycle(sCameraActivity, mCameraSelector, mPreview, mAnalysis, mImageCapture);
}, ContextCompat.getMainExecutor(this));
}
您将获得 androidx.camera.core.Camera
个实例,这是在您的方法结束时调用 mCameraProvider.bindToLifecycle(sCameraActivity, mCameraSelector, mPreview, mAnalysis, mImageCapture);
的结果。
示例:
private Camera camera;
camera = mCameraProvider.bindToLifecycle(sCameraActivity, mCameraSelector, mPreview, mAnalysis, mImageCapture);
然后,当您需要访问Camera的CameraControl或CameraInfo时,只需使用:
camera.getCameraControl()
camera.getCameraInfo()
我是初级 Android 开发人员。 我使用的是 CameraX 的最新版本 (alpha08)。
我正在尝试设置缩放功能,为此我需要 CameraControl。 要获得 CameraControl,我需要一个 Camera 实例 -> Camera.getCameraControl() 根据 https://developer.android.com/reference/androidx/camera/core/CameraControl
我似乎无法获取 Camera 的实例。如果我尝试实例化 Camera,它会要求我实现 getCameraControl() 和 getCameraInfo(),它们都 return null.
谁能告诉我怎么做?
这是我的 ApplicationClass 文件
public class ApplicationClass extends Application implements CameraXConfig.Provider {
@NonNull
@Override
public CameraXConfig getCameraXConfig() {
return Camera2Config.defaultConfig();
}
}
我的 startCamera() 函数进入我的 CameraActivity
private void startCamera() {
CameraSelector mCameraSelector = CameraSelector.DEFAULT_BACK_CAMERA;
mFlashToggle.setVisibility(View.VISIBLE);
mGalleryFAB.setVisibility(View.VISIBLE);
mTakePhotoFAB.setVisibility(View.VISIBLE);
Point mSize = new Point();
Display mDisplay = getWindowManager().getDefaultDisplay();
mDisplay.getSize(mSize);
int mWidth = mSize.x;
int mHeight = mSize.y;
Preview mPreview = new Preview.Builder()
.setTargetResolution(new Size(mWidth, mHeight))
.build();
mPreview.setPreviewSurfaceProvider(mCameraPP.getPreviewSurfaceProvider());
ImageCapture mImageCapture = new ImageCapture.Builder()
.setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
.setTargetRotation(getWindowManager().getDefaultDisplay().getRotation())
.setTargetResolution(new Size(mWidth, mHeight))
.build();
// FLASHLIGHT PART
mFlashToggle.getBackground().setAlpha(0);
mFlashToggle.setOnClickListener(new View.OnClickListener() {
boolean mIsActivated = true;
@Override
public void onClick(View v) {
if (mIsActivated) {
mImageCapture.setFlashMode(ImageCapture.FLASH_MODE_ON);
mFlashToggle.setColorFilter(getResources().getColor(R.color.conforme));
mFlashToggle.getBackground().setAlpha(0);
mIsActivated = false;
} else {
mImageCapture.setFlashMode(ImageCapture.FLASH_MODE_OFF);
mFlashToggle.setColorFilter(getResources().getColor(R.color.black));
mFlashToggle.getBackground().setAlpha(0);
mIsActivated = true;
}
}
});
// CLICK ON TAKE PHOTO BUTTON TRIGGERS THIS
mTakePhotoFAB.setOnClickListener(view -> {
mDir = new File(getExternalCacheDir(), "PhotosAuthentifier");
boolean success = true;
if (!mDir.exists()) {
success = mDir.mkdir();
}
if (success) {
File mFile = new File(mDir, new SimpleDateFormat("yyyyMMdd-HHmmss", Locale.getDefault()).format(new Date()) + ".jpg");
mImageCapture.takePicture(mFile, command -> new Thread(command).start(),
new ImageCapture.OnImageSavedCallback() {
@Override
public void onImageSaved(@NonNull File file) {
runOnUiThread(() -> {
// ADD PHOTO INTO FINAL TAB
mListOfPhotos.add(file.getAbsolutePath());
// UPDATE PREVIEW OF PHOTOS ON SCREEN
mAdapter.setmListOfPhotos(mListOfPhotos);
mRecyclerView.setAdapter(mAdapter);
if (mListOfPhotos.size() < 3) {
actualNumberOfPhoto();
} else {
actualNumberOfPhoto();
}
});
}
@Override
public void onError(int imageCaptureError, @NonNull String message, @Nullable Throwable cause) {
String mMessage = "Photo capture failed: " + message;
Toast.makeText(CameraActivity.this, mMessage, Toast.LENGTH_SHORT).show();
assert cause != null;
cause.printStackTrace();
}
});
}
});
// CLICK ON SEND BUTTON TRIGGERS THIS
mSendPhotoFAB.setOnClickListener(view -> {
if (mSendPhotoFAB.isClickable()) {
mSendPhotoFAB.setClickable(false);
AlertDialog.Builder mAlertDialogBuilder = new AlertDialog.Builder(CameraActivity.this);
String mMessage = null;
if (sIDDemande == 0) {
LayoutInflater mInflater = this.getLayoutInflater();
View mDialogView = mInflater.inflate(R.layout.activity_camera_parameters, null);
// Parameters initialization
mDescriptionET = mDialogView.findViewById(R.id.activityCameraParametersDescriptionET);
mLanguageSpinner = mDialogView.findViewById(R.id.activityCameraSpecimenLanguageSpinner);
mMarkerYesButton = mDialogView.findViewById(R.id.activityCameraMarkerYesButton);
mMarkerNoButton = mDialogView.findViewById(R.id.activityCameraMarkerNoButton);
mMarkerInfoIB = mDialogView.findViewById(R.id.activityCameraMarkerInfoIB);
TextView mMarkerTV = mDialogView.findViewById(R.id.activityCamera15CreditTV);
TextView mMarkerInfoTV = mDialogView.findViewById(R.id.activityCameraMarkerInfoTV);
mSerialNumberET = mDialogView.findViewById(R.id.activityCameraSerialNumberET);
mModelNameET = mDialogView.findViewById(R.id.activityCameraModelNameET);
mAlertDialogBuilder.setView(mDialogView);
// OPTIONAL PARAMETERS FORM
if (sIDDemande == 0) {
ArrayAdapter<String> mSpinnerAdapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item);
mSpinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mLanguageSpinner.setAdapter(mSpinnerAdapter);
mSpinnerAdapter.add(getResources().getString(R.string.french));
mSpinnerAdapter.add(getResources().getString(R.string.english));
mSpinnerAdapter.notifyDataSetChanged();
//To make Description part scrollable
mDescriptionET.setOnTouchListener((v, event) -> {
if (mDescriptionET.hasFocus()) {
v.getParent().requestDisallowInterceptTouchEvent(true);
if ((event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_SCROLL) {
v.getParent().requestDisallowInterceptTouchEvent(false);
return true;
}
}
return false;
});
// Default specimen language is defined according to app language
String mLanguage = LocaleHelper.getLanguage(this).getString(LocaleHelper.SELECTED_LANGUAGE, null);
if (mLanguage != null) {
if (mLanguage.equals("fr")) {
mLanguageSpinner.setSelection(0);
} else if (mLanguage.equals("en")) {
mLanguageSpinner.setSelection(1);
}
}
mMarkerInfoIB.setOnClickListener(v -> {
if (!mMarkerInfoIsClicked) {
mMarkerInfoTV.setVisibility(View.VISIBLE);
mMarkerInfoIsClicked = true;
} else {
mMarkerInfoTV.setVisibility(View.GONE);
mMarkerInfoIsClicked = false;
}
});
mMarkerNoButton.setBackgroundColor(getResources().getColor(R.color.authentifier));
mMarkerYesButton.setBackgroundColor(getResources().getColor(R.color.text_color));
mMarkerYesButton.setOnClickListener(v -> {
if (!mMarkerYesClicked) {
mMarkerYesButton.setBackgroundColor(getResources().getColor(R.color.authentifier));
mMarkerNoButton.setBackgroundColor(getResources().getColor(R.color.text_color));
mMarkerTV.setVisibility(View.VISIBLE);
mMarkerYesClicked = true;
}
});
mMarkerNoButton.setOnClickListener(v -> {
if (mMarkerYesClicked) {
mMarkerNoButton.setBackgroundColor(getResources().getColor(R.color.authentifier));
mMarkerYesButton.setBackgroundColor(getResources().getColor(R.color.text_color));
mMarkerTV.setVisibility(View.GONE);
mMarkerYesClicked = false;
}
});
if (mAlertDialog != null) {
Objects.requireNonNull(mAlertDialog.getWindow()).setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
}
}
}
if (sIDDemande != 0) {
mMessage = getResources().getString(R.string.validationBeforePursue);
}
mAlertDialogBuilder
.setTitle(R.string.activityCameraParametersTitle)
.setCancelable(false)
.setMessage(mMessage)
.setPositiveButton(R.string.yes, (dialog, which) -> {
((AlertDialog) dialog).getButton(which).setClickable(false);
dialog.dismiss();
if (sIDDemande != 0) {
new AsyncTaskSendComplementaryPhotos(sCameraActivity, sCameraActivity.getApplicationContext()).execute();
} else {
if (mDescriptionET.getText() != null && !mDescriptionET.getText().toString().equals("")) {
mMapApplication.put(ConstantsClass.APPLICATION_DESCRIPTION, mDescriptionET.getText().toString());
}
if (mSerialNumberET.getText() != null && !mSerialNumberET.getText().toString().equals("")) {
mMapApplication.put(ConstantsClass.SERIAL_NUMBER, mSerialNumberET.getText().toString());
}
if (mModelNameET.getText() != null && !mModelNameET.getText().toString().equals("")) {
mMapApplication.put(ConstantsClass.MODEL_NAME, mModelNameET.getText().toString());
}
String mSpinnerValue = mLanguageSpinner.getSelectedItem().toString();
if (mSpinnerValue.equals("French")) {
mSpinnerValue = "Français";
}
if (mSpinnerValue.equals("English")) {
mSpinnerValue = "Anglais";
}
mMapApplication.put(ConstantsClass.LANGUAGE_SPECIMEN, mSpinnerValue);
if (mMarkerYesClicked) {
mMapApplication.put(ConstantsClass.MARKER, "OUI");
} else {
mMapApplication.put(ConstantsClass.MARKER, "NON");
}
new AsyncTaskSendData(sCameraActivity).execute();
}
})
.setNegativeButton(R.string.no, (dialogInterface, i) -> {
dialogInterface.dismiss();
mSendPhotoFAB.setClickable(true);
});
mAlertDialog = mAlertDialogBuilder.create();
mAlertDialog.show();
} else {
Toast mToast = Toast.makeText(this, getResources().getString(R.string.waitingMessageBeforeParameters), Toast.LENGTH_LONG);
View mToastView = mToast.getView();
mToastView.setBackgroundColor(getResources().getColor(R.color.authentifier));
mToast.setGravity(Gravity.CENTER, 0, 0);
mToast.show();
}
});
// CLICK ON GALLERY BUTTON TRIGGERS THIS
mGalleryFAB.setOnClickListener(view -> {
checkPermissions();
if (mPermission) {
Intent mIntentGallery = new Intent(Intent.ACTION_PICK);
mIntentGallery.setType("image/*");
startActivityForResult(mIntentGallery, GALLERY_REQUEST);
}
});
ImageAnalysis mAnalysis = new ImageAnalysis.Builder()
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
.build();
mCameraProviderFuture.addListener(() -> {
try {
mCameraProvider = mCameraProviderFuture.get();
} catch (ExecutionException | InterruptedException e) {
e.printStackTrace();
}
assert mCameraProvider != null;
mCameraProvider.bindToLifecycle(sCameraActivity, mCameraSelector, mPreview, mAnalysis, mImageCapture);
}, ContextCompat.getMainExecutor(this));
}
您将获得 androidx.camera.core.Camera
个实例,这是在您的方法结束时调用 mCameraProvider.bindToLifecycle(sCameraActivity, mCameraSelector, mPreview, mAnalysis, mImageCapture);
的结果。
示例:
private Camera camera;
camera = mCameraProvider.bindToLifecycle(sCameraActivity, mCameraSelector, mPreview, mAnalysis, mImageCapture);
然后,当您需要访问Camera的CameraControl或CameraInfo时,只需使用:
camera.getCameraControl()
camera.getCameraInfo()