Android 카메라 android.hardware.Camera 지원 중단됨 당신이 변수를 사용할 수

경우 android.hardware.Camera사용되지 않으며 당신이 변수를 사용할 수 없습니다 Camera다음, 어떤이에 대한 대안을 것입니까?



답변

API 문서

에 대한 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;
        }
    }
}

적절한 API로드

이제 귀하 CameraOld또는 CameraNew클래스 를로드 하려면 CameraNewAPI 레벨 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 레벨이 확인된다는 것입니다.


답변

동일한 문제에 직면 하여 더 이상 사용되지 않는 카메라 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에 연결되지 않은 몇 가지 관련 작업을 수행 할 수 있습니다. 예를 들어 장치에 실제로 카메라가 있는지 감지하고 미디어 라이브러리에 저장하는 것입니다.

아이디어가 도움이 되었기를 바랍니다.


답변

이제 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();
           }


 }