if android.hardware.Camera
устарел, и вы не можете использовать переменную Camera
, то какова будет альтернатива этому?
Android-камера android.hardware.Camera устарела
Ответ 1
Документация по API
В соответствии с руководство для разработчиков Android для android.hardware.Camera
, они заявляют:
Мы рекомендуем использовать новый API android.hardware.camera2 для новых приложений.
На странице с информацией о android.hardware.camera2
(см. выше) указано:
Пакет android.hardware.camera2 предоставляет интерфейс для отдельных устройств камеры, подключенных к устройству Android. Он заменяет класс устаревших камер.
Проблема
Когда вы проверите эту документацию, вы обнаружите, что реализация этих 2 API-камеры очень отличается.
Например, ориентация камеры на android.hardware.Camera
@Override
public int getOrientation(final int cameraId) {
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(cameraId, info);
return info.orientation;
}
Versus 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
для идентификаторов камеры, а новый работает с объектами String
. В этом примере я быстро исправил это, используя int как индекс в новом API. Если камера возвращается не всегда в том же порядке, это уже вызовет проблемы. Альтернативный подход заключается в работе с объектами String и представлением String старых идентификаторов камеры, что, вероятно, безопаснее.
Один прочь вокруг
Теперь, чтобы обойти эту огромную разницу, вы можете реализовать интерфейс сначала и ссылаться на этот интерфейс в своем коде.
Здесь я перечислил код для этого интерфейса и 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, вы можете просто сделать утилиту или использовать шаблон Factory, чтобы создать правильный. Важная часть состоит в том, что проверяется уровень API.
Ответ 2
Столкнувшись с той же проблемой, поддерживая устаревшие устройства через устаревший API-интерфейс камеры и нуждающийся в новом API Camera2 для обоих текущих устройств и в будущем; Я столкнулся с теми же проблемами - и не нашел стороннюю библиотеку, которая объединяет 2 API, вероятно, потому что они очень разные, я обратился к основным принципам ООП.
2 API отлично различаются, что делает их проблемными для клиентских объектов, ожидая интерфейсов, представленных в старом API. Новый API имеет разные объекты с различными методами, построенными с использованием другой архитектуры. Получил любовь к Google, но ragnabbit! это расстраивает.
Итак, я создал интерфейс, ориентированный только на функциональность камеры, которую мне нужно для приложения, и создал простую оболочку для обоих API, которая реализует этот интерфейс. Таким образом, моя активность камеры не должна заботиться о какая платформа работает...
Я также создал Singleton для управления API (-ами); инсталляция старой оболочки API с моим интерфейсом для более старых устройств ОС Android и новый класс API-оболочки для новых устройств с использованием нового API. Синглтон имеет типичный код для получения уровня API, а затем экземпляр правильного объекта.
Тот же интерфейс используется обоими классами-оболочками, поэтому не имеет значения, работает ли приложение на Jellybean или Marshmallow - пока интерфейс предоставляет мое приложение тем, что ему нужно, от любого API-камеры, используя тот же метод подписи; камера работает в приложении так же, как для более ранних, так и для старых версий Android.
Синглтон также может выполнять некоторые связанные вещи, не связанные с API-интерфейсами - например, обнаружение того, что на устройстве действительно есть камера, и сохранение в медиа-библиотеке.
Я надеюсь, что эта идея поможет вам.
Ответ 3
Теперь мы должны использовать 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;
}
}
});
}
}