경우 android.hardware.Camera
사용되지 않으며 당신이 변수를 사용할 수 없습니다 Camera
다음, 어떤이에 대한 대안을 것입니까?
경우 android.hardware.Camera
사용되지 않으며 당신이 변수를 사용할 수 없습니다 Camera
다음, 어떤이에 대한 대안을 것입니까?
답변:
에 대한 Android 개발자 가이드 에 따르면 android.hardware.Camera
다음과 같습니다.
새로운 애플리케이션 에는 새로운 android.hardware.camera2 API를 사용하는 것이 좋습니다 .
에 대한 정보 페이지 android.hardware.camera2
(위에 링크 됨)에 다음과 같이 명시되어 있습니다.
android.hardware.camera2 패키지는 Android 기기에 연결된 개별 카메라 기기에 대한 인터페이스를 제공합니다. 더 이상 사용되지 않는 Camera 클래스를 대체합니다.
해당 문서를 확인하면이 두 가지 Camera API의 구현이 매우 다르다는 것을 알 수 있습니다.
예를 들어 카메라 방향 설정 android.hardware.camera
@Override
public int getOrientation(final int cameraId) {
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(cameraId, info);
return info.orientation;
}
대 android.hardware.camera2
@Override
public int getOrientation(final int cameraId) {
try {
CameraManager manager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
String[] cameraIds = manager.getCameraIdList();
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraIds[cameraId]);
return characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
} catch (CameraAccessException e) {
// TODO handle error properly or pass it on
return 0;
}
}
이로 인해 하나에서 다른 것으로 전환하고 두 구현을 모두 처리 할 수있는 코드를 작성하기가 어렵습니다.
이 단일 코드 예제에서는 이전 카메라 API가 int
카메라 ID의 기본 요소 와 함께 작동하는 반면 새 카메라 API는 String
객체 와 함께 작동 한다는 사실을 이미 해결해야했습니다 . 이 예에서는 int를 새 API의 인덱스로 사용하여 신속하게 수정했습니다. 카메라 반품이 항상 동일한 순서가 아닌 경우 이미 문제가 발생합니다. 대체 접근 방식은 아마도 더 안전한 이전 int cameraID의 String 객체 및 String 표현으로 작업하는 것입니다.
이제이 큰 차이를 해결하기 위해 먼저 인터페이스를 구현하고 코드에서 해당 인터페이스를 참조 할 수 있습니다.
여기에 해당 인터페이스와 두 가지 구현에 대한 몇 가지 코드를 나열합니다. 작업량을 제한하기 위해 카메라 API를 실제로 사용하는 것으로 구현을 제한 할 수 있습니다.
다음 섹션에서는 둘 중 하나를로드하는 방법을 빠르게 설명하겠습니다.
이 예제를 제한하기 위해 필요한 모든 것을 래핑하는 인터페이스는 여기에 두 가지 방법 만 있습니다.
public interface CameraSupport {
CameraSupport open(int cameraId);
int getOrientation(int cameraId);
}
이제 이전 카메라 하드웨어 API에 대한 클래스가 있습니다.
@SuppressWarnings("deprecation")
public class CameraOld implements CameraSupport {
private Camera camera;
@Override
public CameraSupport open(final int cameraId) {
this.camera = Camera.open(cameraId);
return this;
}
@Override
public int getOrientation(final int cameraId) {
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(cameraId, info);
return info.orientation;
}
}
그리고 새로운 하드웨어 API에 대한 또 다른 하나 :
public class CameraNew implements CameraSupport {
private CameraDevice camera;
private CameraManager manager;
public CameraNew(final Context context) {
this.manager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
}
@Override
public CameraSupport open(final int cameraId) {
try {
String[] cameraIds = manager.getCameraIdList();
manager.openCamera(cameraIds[cameraId], new CameraDevice.StateCallback() {
@Override
public void onOpened(CameraDevice camera) {
CameraNew.this.camera = camera;
}
@Override
public void onDisconnected(CameraDevice camera) {
CameraNew.this.camera = camera;
// TODO handle
}
@Override
public void onError(CameraDevice camera, int error) {
CameraNew.this.camera = camera;
// TODO handle
}
}, null);
} catch (Exception e) {
// TODO handle
}
return this;
}
@Override
public int getOrientation(final int cameraId) {
try {
String[] cameraIds = manager.getCameraIdList();
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraIds[cameraId]);
return characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
} catch (CameraAccessException e) {
// TODO handle
return 0;
}
}
}
이제 귀하 CameraOld
또는 CameraNew
클래스 를로드 하려면 CameraNew
API 레벨 21에서만 사용할 수 있으므로 API 레벨을 확인해야합니다 .
이미 종속성 주입을 설정 한 경우 CameraSupport
구현을 제공 할 때 모듈에서이를 수행 할 수 있습니다 . 예:
@Module public class CameraModule {
@Provides
CameraSupport provideCameraSupport(){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
return new CameraNew(context);
} else {
return new CameraOld();
}
}
}
DI를 사용하지 않는 경우 유틸리티를 만들거나 Factory 패턴을 사용하여 적절한 것을 만들 수 있습니다. 중요한 부분은 API 레벨이 확인된다는 것입니다.
@SuppressWarnings
이 QA 에 대한 몇 가지 정보입니다. stackoverflow.com/questions/7397996/…
동일한 문제에 직면 하여 더 이상 사용되지 않는 카메라 API를 통해 이전 기기를 지원하고 현재 기기 모두에 새로운 Camera2 API가 필요하며 미래로 이동합니다. 나는 동일한 문제에 부딪 혔고 두 API를 연결하는 타사 라이브러리를 찾지 못했습니다. 매우 다르기 때문에 기본 OOP 주체로 전환했습니다 .
2 개의 API는 현저하게 다르기 때문에 이전 API에 제공된 인터페이스를 예상하는 클라이언트 객체에서 이들을 교환하는 데 문제가 있습니다. 새 API에는 다른 아키텍처를 사용하여 빌드 된 메서드가 다른 여러 개체가 있습니다. Google에 대한 사랑이 있지만 ragnabbit! 실망 스럽네요.
그래서 앱에 필요한 카메라 기능에만 초점을 맞춘 인터페이스를 만들고 해당 인터페이스 를 구현하는 두 API에 대한 간단한 래퍼를 만들었습니다 . 이렇게하면 카메라 활동이 어떤 플랫폼에서 실행되는지 신경 쓸 필요가 없습니다.
또한 API를 관리하기 위해 Singleton을 설정했습니다. 이전 Android OS 기기의 경우 내 인터페이스로 이전 API의 래퍼를 인스턴스화하고 새 API를 사용하는 최신 기기의 경우 새 API의 래퍼 클래스를 인스턴스화합니다. 싱글 톤에는 API 레벨을 가져온 다음 올바른 객체를 인스턴스화하는 일반적인 코드가 있습니다.
두 래퍼 클래스 에서 동일한 인터페이스를 사용 하므로 앱이 Jellybean 또는 Marshmallow에서 실행되는지 여부는 중요하지 않습니다. 인터페이스가 동일한 메서드 서명을 사용하여 Camera API에서 필요한 것을 앱에 제공하는 한; 카메라는 Android의 최신 버전과 이전 버전 모두에서 동일한 방식으로 앱에서 실행됩니다.
Singleton은 또한 API에 연결되지 않은 몇 가지 관련 작업을 수행 할 수 있습니다. 예를 들어 장치에 실제로 카메라가 있는지 감지하고 미디어 라이브러리에 저장하는 것입니다.
아이디어가 도움이 되었기를 바랍니다.
public interface AllCameraInterface { void open(); boolean setDirection(); Bitmap preview(); Bitmap takePhoto(); void close(); }
public interface AllCameraInterface { void open(); Bitmap takePhoto(); void close(); etc... }
public class NCamera implements AllCameraInterface...
public class OCamera implements AllCameraInterface...
public class AllCamera { private static AllCamera ourInstance = new AllCamera(); public static AllCamera getInstance() {...} private AllCameraInterface camera; private AllCamera() { if (android.os.Build.VERSION.SDK_INT <= 20) { camera = new OCamera(); } else { camera = new NCamera(); } }
그런 방법이 ... 그것을 반환
camera2
시겠습니까? 정말 혼란 스러워요 ... 난 그냥 필요 enableAutofocus
: 카메라를 열고 초점 설정하는 방법을 stackoverflow.com/questions/19076316/...
이제 android.hardware.camera2를 사용해야합니다. android.hardware.Camera는 더 이상 사용되지 않으며 API> 23 FlashLight에서만 작동합니다.
public class MainActivity extends AppCompatActivity {
Button button;
Boolean light=true;
CameraDevice cameraDevice;
private CameraManager cameraManager;
private CameraCharacteristics cameraCharacteristics;
String cameraId;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button=(Button)findViewById(R.id.button);
cameraManager = (CameraManager)
getSystemService(Context.CAMERA_SERVICE);
try {
cameraId = cameraManager.getCameraIdList()[0];
} catch (CameraAccessException e) {
e.printStackTrace();
}
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(light){
try {
cameraManager.setTorchMode(cameraId,true);
} catch (CameraAccessException e) {
e.printStackTrace();
}
light=false;}
else {
try {
cameraManager.setTorchMode(cameraId,false);
} catch (CameraAccessException e) {
e.printStackTrace();
}
light=true;
}
}
});
}
}
사용할 카메라 API에 대한 답변이 잘못되었습니다. 또는 부족하다고 말하는 것이 좋습니다.
일부 휴대폰 (예 : Samsung Galaxy S6)은 API 레벨 21 이상일 수 있지만 여전히 Camera2 API를 지원하지 않을 수 있습니다.
CameraCharacteristics mCameraCharacteristics = mCameraManager.getCameraCharacteristics(mCameraId);
Integer level = mCameraCharacteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
if (level == null || level == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY) {
return false;
}
Camera2Api의 CameraManager 클래스에는 카메라 특성을 읽는 메서드가 있습니다. 하드웨어 현명한 장치가 Camera2 Api를 지원하는지 확인해야합니다.
그러나 심각한 응용 프로그램에서 작동하게하려면 처리해야 할 더 많은 문제가 있습니다. 예를 들어, 자동 플래시 옵션이 일부 장치에서 작동하지 않거나 전화기의 배터리 수준이 카메라에 RuntimeException을 생성하거나 전화기가 잘못된 값을 반환 할 수 있습니다. 카메라 ID 등
따라서 최선의 접근 방식은 어떤 이유로 Camera2가 시작되지 않는 경우 Camera1을 시도 할 수 있으며 이것이 실패하면 Android를 호출하여 기본 카메라를 열 수 있으므로 대체 메커니즘을 사용하는 것입니다.
if ( getActivity().getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH)) {
CameraManager cameraManager=(CameraManager) getActivity().getSystemService(Context.CAMERA_SERVICE);
try {
String cameraId = cameraManager.getCameraIdList()[0];
cameraManager.setTorchMode(cameraId,true);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
android.hardware.camera2