Android cámara android.hardware.Cámara en desuso


Si android.hardware.Camera está en desuso y no puede usar la variable Camera, entonces ¿cuál sería la alternativa a esto?

Author: raja121, 2015-01-21

3 answers

Documentación de la API

De acuerdo con la guía para desarrolladores de Android para android.hardware.Camera, dicen:

Recomendamos usar el nuevo android.hardware.camera2 API para nuevas aplicaciones.

En la página de información sobre android.hardware.camera2, (enlazado arriba), se indica:

El androide.hardware.el paquete camera2 proporciona una interfaz para dispositivos de cámara individuales conectados a un dispositivo Android. Reemplaza la cámara obsoleta clase.

El problema

Cuando revises esa documentación encontrarás que la implementación de estas 2 API de cámara son muy diferentes.

Por ejemplo, obtener la orientación de la cámara en 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 una a otra y escribir código que pueda manejar ambas implementaciones.

Tenga en cuenta que en este ejemplo de código único ya tuve que trabajar alrededor del hecho de que el olde camera API funciona con int primitivas para ID de cámara, mientras que la nueva funciona con objetos String. Para este ejemplo lo arreglé rápidamente usando el int como un índice en la nueva API. Si la cámara devuelta no siempre está en el mismo orden, esto ya causará problemas. El enfoque alternativo es trabajar con objetos String y la representación String del antiguo int cameraIDs, lo cual es probablemente más seguro.

Uno de distancia alrededor

Ahora para trabajar en torno a esta enorme diferencia que puede implemente primero una interfaz y haga referencia a esa interfaz en su código.

Aquí voy a enumerar algún código 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 que 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 tienen una clase para el viejo 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;
        }
    }
}

Cargando la API adecuada

Ahora para cargar su clase CameraOld o CameraNew tendrá que verificar el nivel de API ya que CameraNew solo está disponible desde el nivel de api 21.

Si ya tiene configurada la inyección de dependencias, puede hacerlo en su módulo cuando proporcione la implementación CameraSupport. 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, solo puede hacer una utilidad o usar Factory patrón para crear el adecuado. La parte importante es que se comprueba el nivel de API.

 81
Author: hcpl,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-09-01 12:15:31

Ante el mismo problema, soportando dispositivos más antiguos a través de la obsoleta camera API y necesitando la nueva Camera2 API para ambos dispositivos actuales y moviéndome hacia el futuro; me encontré con los mismos problemas {y he no encontrado una biblioteca de terceros que une las 2 API, probablemente porque son muy diferentes, recurrí a principios básicos de OOP .

Las 2 API son marcadamente diferentes, lo que hace que intercambiarlas sea problemático para los objetos del cliente que esperan interfaces presentadas en la antigua API. La nueva API tiene diferentes objetos con diferentes métodos, construidos utilizando una arquitectura diferente. Tengo amor por Google, pero ragnabbit! eso es frustrante.

Así que creé una interfaz centrada solo en la funcionalidad de la cámara que mi aplicación necesita, y creé un envoltorio 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 la API (s); instanciando el envoltorio de la API anterior con mi interfaz para dispositivos Android OS más antiguos, y la nueva clase de envoltorio de la API para dispositivos más nuevos que utilizan la nueva API. El singleton tiene el código típico para obtener el nivel de API y luego las instancias del objeto correcto.

La misma interfaz es utilizada por ambas clases de wrapper, por lo que no importa si la Aplicación se ejecuta en Jellybean o Marshmallow--siempre y cuando la interfaz proporcione a mi aplicación lo que necesita de cualquiera de las API de la cámara, usando las mismas firmas de método; la cámara se ejecuta en la Aplicación de la misma manera para las versiones más nuevas y más antiguas de Android.

El Singleton también puede hacer algunas cosas relacionadas no vinculadas a las API like como detectar que efectivamente hay una cámara en el dispositivo, y guardar en la biblioteca de medios.

Espero que la idea te ayude.

 5
Author: Robert Sherman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-06-16 18:25:22

Ahora tenemos que usar android.hardware.camera2 como android.hardware.La cámara está obsoleta, que 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;
                    }


            }
        });
    }
}
 0
Author: abhay rastogi Codeblended,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-20 13:47:04