Android Камера android.аппаратура.Камера устарела


Если android.hardware.Camera устарела, и вы не можете использовать переменную Camera, тогда какова была бы альтернатива этому?

3 77

3 ответа:

документация API

по словам руководство для разработчиков Android на android.hardware.Camera, они заявляют:

мы рекомендуем использовать новый тег android.аппаратура.camera2 API для новых приложений.

на странице информации о компании android.hardware.camera2, (ссылка выше), указано:

андроид.аппаратура.пакет camera2 предоставляет интерфейс для отдельных устройств камеры, подключенных к устройство Android. он заменяет устаревший класс камеры.

проблема

когда вы проверите эту документацию, вы обнаружите, что реализация этих двух 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 olde camera работает с int примитивы для идентификаторов камер, в то время как новый работает с String объекты. Для этого примера я быстро исправил это, используя int в качестве индекса в новом API. Если камера возвращается не всегда в том же порядке, это уже вызовет вопросы. Альтернативный подход заключается в работе со строковыми объектами и строковым представлением старого int камеры, которые, вероятно, безопаснее.

на

теперь, чтобы обойти эту огромную разницу, вы можете сначала реализовать интерфейс и ссылаться на этот интерфейс в своем коде.

здесь я перечислю некоторый код для этого интерфейса и 2 реализации. Вы можете ограничить реализацию тем, что вы фактически используете API камеры, чтобы ограничить объем работы.

в следующем разделе я быстро объясню, как загрузить один или другой.

интерфейс для упаковки все, что вам нужно, чтобы ограничить этот пример у меня есть только 2 метода здесь.

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 класс вы должны будете проверить уровень API, так как CameraNew доступно только на уровне api 21.

если у вас уже настроена инъекция зависимостей, вы можете сделать это в своем модуле при предоставлении 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, вы можете просто сделать утилиту или использовать заводской шаблон для создания правильного. Важной частью является то, что уровень API проверяется.

столкнулся с той же проблемой, поддерживая старые устройства через устаревший API камеры и нуждаясь в новом API Camera2 как для текущих устройств, так и для перемещения в будущее; я столкнулся с теми же проблемами-и есть не нашел стороннюю библиотеку, которая соединяет 2 API, вероятно, потому, что они очень разные,Я обратился к основным принципам ООП.

2 API заметно отличаются, что делает их взаимозаменяемость проблематичной для клиента объекты, ожидающие интерфейсы, представленные в старом API. Новый API имеет различные объекты с различными методами, используя различные архитектуры. Получил любовь к Google, но ragnabbit! это расстраивает.

поэтому я создал интерфейс, фокусирующийся только на функциональности камеры, необходимой моему приложению, и создал простую оболочку для и API, который реализует этот интерфейс. таким образом, моя активность камеры не должна заботиться о том, какая платформа ее бежим дальше...

Я также настроил Синглтон для управления API(АМИ); создание экземпляра оболочки старого API с помощью моего интерфейса для старых устройств ОС Android и класса оболочки нового API для новых устройств с использованием нового API. Синглтон имеет типичный код для получения уровня API, а затем экземпляры правильного объекта.

один и тот же интерфейс используется обоими классами-оболочками, поэтому не имеет значения, работает ли приложение на Jellybean или Marshmallow-до тех пор, пока интерфейс предоставляет моему приложению то, что ему нужно от любого API камеры, используя те же сигнатуры метода; камера работает в приложении одинаково как для более новых, так и для более старых версий Android.

Синглтон также может делать некоторые связанные вещи, не связанные с API-интерфейсами-например, обнаруживать, что на устройстве действительно есть камера, и сохранять в медиатеку.

Я надеюсь, что идея поможет вам.

теперь мы должны использовать Android.аппаратура.camera2 как android.аппаратура.Камера устарела, которая будет работать только на API > 23 фонарик

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


            }
        });
    }
}