developer tip

Android 카메라 android.hardware.Camera 지원 중단됨

optionbox 2020. 9. 6. 09:28
반응형

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

If you don't use DI you can just make a utility or use Factory pattern to create the proper one. Important part is that the API level is checked.


Faced with the same issue, supporting older devices via the deprecated camera API and needing the new Camera2 API for both current devices and moving into the future; I ran into the same issues -- and have not found a 3rd party library that bridges the 2 APIs, likely because they are very different, I turned to basic OOP principals.

The 2 APIs are markedly different making interchanging them problematic for client objects expecting the interfaces presented in the old API. The new API has different objects with different methods, built using a different architecture. Got love for Google, but ragnabbit! that's frustrating.

So I created an interface focussing on only the camera functionality my app needs, and created a simple wrapper for both APIs that implements that interface. That way my camera activity doesn't have to care about which platform its running on...

I also set up a Singleton to manage the API(s); instancing the older API's wrapper with my interface for older Android OS devices, and the new API's wrapper class for newer devices using the new API. The singleton has typical code to get the API level and then instances the correct object.

The same interface is used by both wrapper classes, so it doesn't matter if the App runs on Jellybean or Marshmallow--as long as the interface provides my app with what it needs from either Camera API, using the same method signatures; the camera runs in the App the same way for both newer and older versions of Android.

The Singleton can also do some related things not tied to the APIs--like detecting that there is indeed a camera on the device, and saving to the media library.

I hope the idea helps you out.


Now we have to use android.hardware.camera2 as android.hardware.Camera is deprecated which will only work on 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;
                    }


            }
        });
    }
}

Answers provided here as which camera api to use are wrong. Or better to say they are insufficient.

Some phones (for example Samsung Galaxy S6) could be above api level 21 but still may not support 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;
}

CameraManager class in Camera2Api has a method to read camera characteristics. You should check if hardware wise device is supporting Camera2 Api or not.

But there are more issues to handle if you really want to make it work for a serious application: Like, auto-flash option may not work for some devices or battery level of the phone might create a RuntimeException on Camera or phone could return an invalid camera id and etc.

So best approach is to have a fallback mechanism as for some reason Camera2 fails to start you can try Camera1 and if this fails as well you can make a call to Android to open default Camera for you.

참고URL : https://stackoverflow.com/questions/28065930/android-camera-android-hardware-camera-deprecated

반응형