si android.hardware.Camera
está en desuso y no puede usar la variable Camera
, ¿cuál sería la alternativa a esto?
si android.hardware.Camera
está en desuso y no puede usar la variable Camera
, ¿cuál sería la alternativa a esto?
Respuestas:
Según la guía para desarrolladores de Androidandroid.hardware.Camera
, afirman:
Recomendamos utilizar la nueva API android.hardware.camera2 para nuevas aplicaciones.
En la página de información android.hardware.camera2
(enlazada arriba), se indica:
El paquete android.hardware.camera2 proporciona una interfaz para dispositivos de cámara individuales conectados a un dispositivo Android. Reemplaza la clase Camera obsoleta.
Cuando revise esa documentación, encontrará que la implementación de estas 2 API de cámara es muy diferente.
Por ejemplo, activar la orientación de la cámara 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;
}
}
Esto hace que sea difícil cambiar de uno a otro y escribir código que pueda manejar ambas implementaciones.
Tenga en cuenta que en este ejemplo de código único ya tuve que solucionar el hecho de que la API de la cámara antigua funciona con int
primitivas para los ID de cámara, mientras que la nueva funciona con String
objetos. Para este ejemplo, lo solucioné rápidamente usando int como índice en la nueva API. Si la cámara se devuelve no siempre en el mismo orden, esto ya causará problemas. El enfoque alternativo es trabajar con objetos String y la representación String de los antiguos ID de cámara int, que probablemente sea más seguro.
Ahora, para solucionar esta gran diferencia, primero puede implementar una interfaz y hacer referencia a esa interfaz en su código.
Aquí enumeraré algunos códigos para esa interfaz y las 2 implementaciones. Puede limitar la implementación a lo que realmente usa de la API de la cámara para limitar la cantidad de trabajo.
En la siguiente sección explicaré rápidamente cómo cargar uno u otro.
La interfaz envuelve todo lo que necesita, para limitar este ejemplo, solo tengo 2 métodos aquí.
public interface CameraSupport {
CameraSupport open(int cameraId);
int getOrientation(int cameraId);
}
Ahora tenga una clase para la antigua API de hardware de la cámara:
@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;
}
}
Y otro para la nueva API de hardware:
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;
}
}
}
Ahora, para cargar su clase CameraOld
o CameraNew
, tendrá que verificar el nivel de API, ya CameraNew
que solo está disponible desde el nivel 21 de API.
Si ya tiene configurada la inyección de dependencia, puede hacerlo en su módulo cuando proporcione la CameraSupport
implementación. Ejemplo:
@Module public class CameraModule {
@Provides
CameraSupport provideCameraSupport(){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
return new CameraNew(context);
} else {
return new CameraOld();
}
}
}
Si no usa DI, puede crear una utilidad o usar el patrón Factory para crear el adecuado. La parte importante es que se comprueba el nivel de API.
@SuppressWarnings
este control de calidad stackoverflow.com/questions/7397996/…
Enfrentado con el mismo problema , admitiendo dispositivos más antiguos a través de la API de la cámara obsoleta y necesitando la nueva API Camera2 para los dispositivos actuales y para el futuro; Me encontré con los mismos problemas, y no encontré una biblioteca de terceros que vincule las 2 API, probablemente porque son muy diferentes, recurrí a los principios básicos de OOP .
Las 2 API son marcadamente diferentes, por lo que intercambiarlas es problemático para los objetos de cliente que esperan las interfaces presentadas en la API anterior. La nueva API tiene diferentes objetos con diferentes métodos, construidos con una arquitectura diferente. Tengo amor por Google, ¡pero ragnabbit! eso es frustrante.
Así que creé una interfaz que se enfocaba solo en la funcionalidad de la cámara que mi aplicación necesita, y creé un contenedor simple para ambas API que implementa esa interfaz. De esa manera, la actividad de mi cámara no tiene que preocuparse por la plataforma en la que se ejecuta ...
También configuré un Singleton para administrar las API; instalando el contenedor de la API anterior con mi interfaz para los dispositivos con sistema operativo Android más antiguos, y la clase de contenedor de la nueva API para los dispositivos más nuevos que utilizan la nueva API. El singleton tiene un código típico para obtener el nivel de API y luego instancias del objeto correcto.
Ambas clases contenedoras utilizan la misma interfaz , por lo que no importa si la aplicación se ejecuta en Jellybean o Marshmallow, siempre que la interfaz proporcione a mi aplicación lo que necesita de la API de la cámara, utilizando las mismas firmas de métodos; la cámara se ejecuta en la aplicación de la misma manera para las versiones más nuevas y antiguas de Android.
Singleton también puede hacer algunas cosas relacionadas que no están vinculadas a las API, como detectar que efectivamente hay una cámara en el dispositivo y guardar en la biblioteca de medios.
Espero que la idea te ayude.
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(); } }
Entonces un método para devolverlo ...
camera2
? Estoy realmente confundido ... Solo necesito el enableAutofocus
método para abrir la cámara y establecer su enfoque: stackoverflow.com/questions/19076316/…
Ahora tenemos que usar android.hardware.camera2 ya que android.hardware.Camera está en desuso y solo funcionará en 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;
}
}
});
}
}
Las respuestas proporcionadas aquí sobre qué api de cámara usar son incorrectas. O mejor dicho, son insuficientes.
Algunos teléfonos (por ejemplo, Samsung Galaxy S6) pueden estar por encima del nivel 21 de la API, pero es posible que aún no sean compatibles con la 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;
}
La clase CameraManager en Camera2Api tiene un método para leer las características de la cámara. Debe verificar si el dispositivo de hardware es compatible con Camera2 Api o no.
Pero hay más problemas que manejar si realmente desea que funcione para una aplicación seria: por ejemplo, la opción de flash automático puede no funcionar para algunos dispositivos o el nivel de batería del teléfono puede crear una RuntimeException en la cámara o el teléfono podría devolver un valor no válido ID de cámara y etc.
Entonces, el mejor enfoque es tener un mecanismo de respaldo, ya que por alguna razón Camera2 no se inicia, puede probar Camera1 y, si esto también falla, puede hacer una llamada a Android para abrir la Cámara predeterminada para usted.
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