якщо android.hardware.Camera
застаріла і ви не можете використовувати цю змінну Camera
, то що б було альтернативою цьому?
якщо android.hardware.Camera
застаріла і ви не можете використовувати цю змінну Camera
, то що б було альтернативою цьому?
Відповіді:
Згідно з посібником для розробників Androidandroid.hardware.Camera
, вони заявляють:
Ми рекомендуємо використовувати новий android.hardware.camera2 API для нових програм.
На сторінці інформації про android.hardware.camera2
(зв'язане вище) зазначено:
Пакет android.hardware.camera2 забезпечує інтерфейс до окремих пристроїв камер, підключених до пристрою Android. Він замінює застарілий клас Camera.
Перевіривши цю документацію, ви виявите, що реалізація цих 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;
}
Проти 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 представлення старих int cameraID, що, ймовірно, безпечніше.
Тепер, щоб вирішити цю величезну різницю, ви можете спочатку реалізувати інтерфейс і посилатись на цей інтерфейс у своєму коді.
Тут я перерахую код для цього інтерфейсу та 2 реалізації. Ви можете обмежити реалізацію тим, що ви фактично використовуєте API камери, щоб обмежити обсяг роботи.
У наступному розділі я швидко поясню, як завантажити те чи інше.
Інтерфейс, що обгортає все, що вам потрібно, щоб обмежити цей приклад, у мене є лише два способи.
public interface CameraSupport {
CameraSupport open(int cameraId);
int getOrientation(int cameraId);
}
Тепер у вас є клас для старих апаратних апаратів камери:
@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;
}
}
І ще одна для нових апаратних програм:
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 як для поточних пристроїв, так і в майбутнє; Я зіткнувся з тими ж проблемами - і не знайшов сторонньої бібліотеки, яка б’є два API, ймовірно, тому, що вони дуже різні, я звернувся до основних керівників ООП .
2 API помітно відрізняються, що робить їх обмін проблематичним для клієнтських об'єктів, які очікують інтерфейсів, представлених у старому API. Новий API має різні об’єкти з різними методами, побудовані з використанням іншої архітектури. Отримав любов до Google, але безкорисливий! це засмучує.
Тому я створив інтерфейс, орієнтований лише на функціональність камери, яка потрібна моєму додатку, і створив просту обгортку для обох API, яка реалізує цей інтерфейс. Таким чином, моя діяльність з фотоапарата не повинна дбати про те, на якій платформі працює її камера ...
Я також створив Singleton для управління API (ими); інстанціювання обгортки старішого API з моїм інтерфейсом для старих пристроїв з ОС Android та нового класу обгортки API для нових пристроїв, що використовують новий API. Синглтон має типовий код для отримання рівня API, а потім встановлює правильний об'єкт.
Один і той же інтерфейс використовується обома класами обгортки , тому не має значення, чи додаток працює на Jellybean або Marshmallow - доки інтерфейс надає моєму додатку те, що потрібно від API камери, використовуючи однаковий метод підписів; камера працює в додатку однаково як для новіших, так і для старих версій Android.
Singleton також може робити якісь пов’язані речі, не пов'язані з 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