если android.hardware.Camera
устарело и вы не можете использовать эту переменную Camera
, то какая альтернатива этому?
если android.hardware.Camera
устарело и вы не можете использовать эту переменную Camera
, то какая альтернатива этому?
Ответы:
Согласно руководству для разработчиков Androidandroid.hardware.Camera
, они заявляют:
Мы рекомендуем использовать новый API android.hardware.camera2 для новых приложений.
На информационной странице о android.hardware.camera2
(ссылка выше) указано:
Пакет android.hardware.camera2 предоставляет интерфейс для отдельных камер, подключенных к устройству Android. Он заменяет устаревший класс 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
примитивами для идентификаторов камеры, а новый работает с String
объектами. В этом примере я быстро исправил это, используя int в качестве индекса в новом API. Если камера возвращается не всегда в том же порядке, это уже вызовет проблемы. Альтернативный подход - работать с объектами String и строковым представлением старых int cameraID, что, вероятно, более безопасно.
Теперь, чтобы обойти эту огромную разницу, вы можете сначала реализовать интерфейс и ссылаться на него в своем коде.
Здесь я перечислю код для этого интерфейса и 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;
}
}
}
Теперь, чтобы загрузить ваш 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.
@SuppressWarnings
этом QA stackoverflow.com/questions/7397996/…
Столкнулся с той же проблемой , поддерживая старые устройства через устаревший API камеры и нуждаясь в новом API Camera2 как для текущих устройств, так и в будущем; Я столкнулся с теми же проблемами - и не нашел сторонней библиотеки, объединяющей 2 API, вероятно, из-за того, что они очень разные, я обратился к основным принципам ООП .
Эти 2 API заметно отличаются, что затрудняет их замену для клиентских объектов, ожидающих интерфейсов, представленных в старом API. В новом API есть разные объекты с разными методами, построенные с использованием другой архитектуры. Получил любовь к Google, но ragnabbit! это расстраивает.
Поэтому я создал интерфейс, ориентированный только на функции камеры, необходимые моему приложению, и создал простую оболочку для обоих API, реализующих этот интерфейс. Таким образом, моя работа с камерой не должна заботиться о том, на какой платформе она работает ...
Я также установил Singleton для управления API (ами); создание экземпляра старой оболочки API с моим интерфейсом для старых устройств на ОС Android и нового класса оболочки API для новых устройств, использующих новый API. Синглтон имеет типичный код для получения уровня API, а затем экземпляры правильного объекта.
Один и тот же интерфейс используется обоими классами-оболочками , поэтому не имеет значения, работает ли приложение на Jellybean или Marshmallow - до тех пор, пока интерфейс предоставляет моему приложению все, что ему нужно, от любого API камеры с использованием одних и тех же сигнатур методов; камера работает в приложении одинаково как для новых, так и для старых версий Android.
Синглтон также может выполнять некоторые связанные действия, не связанные с 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, но по-прежнему могут не поддерживать API Camera2.
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 в Camera2Api имеет метод для чтения характеристик камеры. Вы должны проверить, поддерживает ли аппаратное устройство Camera2 Api или нет.
Но есть и другие проблемы, которые нужно решить, если вы действительно хотите, чтобы он работал для серьезного приложения: например, опция автоматической вспышки может не работать для некоторых устройств, или уровень заряда батареи телефона может создать исключение RuntimeException на камере, или телефон может вернуть недопустимый идентификатор камеры и т. д.
Поэтому лучший подход - иметь запасной механизм, поскольку по какой-то причине 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