Frage Android Kamera android.hardware.Camera veraltet


ob android.hardware.Camera ist veraltet und Sie können die Variable nicht verwenden CameraWas wäre dann die Alternative?


75
2018-01-21 11:18


Ursprung


Antworten:


API-Dokumentation

Entsprechend der Android-Entwickler führen zum android.hardware.Camera, sie sagen:

Wir empfehlen die Verwendung des neuen android.hardware.camera2 API für neue Anwendungen.

Auf der Informationsseite über android.hardware.camera2(oben verlinkt) heißt es:

Das Paket android.hardware.camera2 bietet eine Schnittstelle zu einzelnen Kamera-Geräten, die mit einem Android-Gerät verbunden sind. Es ersetzt die veraltete Kamera-Klasse.

Das Problem

Wenn Sie diese Dokumentation überprüfen, werden Sie feststellen, dass die Implementierung dieser 2 Kamera-APIs sehr unterschiedlich ist.

Zum Beispiel, um die Kameraausrichtung zu aktivieren android.hardware.camera

@Override
public int getOrientation(final int cameraId) {
    Camera.CameraInfo info = new Camera.CameraInfo();
    Camera.getCameraInfo(cameraId, info);
    return info.orientation;
}

Gegen 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;
    }
}

Dies macht es schwierig, von einem zum anderen zu wechseln und Code zu schreiben, der beide Implementierungen handhaben kann.

Beachten Sie, dass ich in diesem Code-Beispiel bereits die Tatsache umgehen musste, dass die alte Kamera-API funktioniert int Primitive für Kamera-IDs, während die neue mit arbeitet String Objekte. In diesem Beispiel habe ich das schnell behoben, indem ich int als Index in der neuen API verwendet habe. Wenn die zurückgegebenen Kameras nicht immer in der gleichen Reihenfolge sind, führt dies bereits zu Problemen. Alternativer Ansatz ist es, mit String-Objekten und String-Repräsentationen der alten int-Kamera-IDs zu arbeiten, was wahrscheinlich sicherer ist.

Ein Weg herum

Um diesen großen Unterschied zu umgehen, können Sie zunächst eine Schnittstelle implementieren und diese Schnittstelle in Ihrem Code referenzieren.

Hier werde ich einen Code für diese Schnittstelle und die 2 Implementierungen auflisten. Sie können die Implementierung auf das beschränken, was Sie tatsächlich von der Kamera-API verwenden, um den Arbeitsaufwand zu begrenzen.

Im nächsten Abschnitt werde ich schnell erklären, wie man den einen oder anderen lädt.

Die Schnittstelle umhüllt alles was du brauchst, um dieses Beispiel einzuschränken Ich habe hier nur 2 Methoden.

public interface CameraSupport {
    CameraSupport open(int cameraId);
    int getOrientation(int cameraId);
}

Habe jetzt eine Klasse für die alte Kamera-Hardware 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;
    }
}

Und noch eins für die neue Hardware-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;
        }
    }
}

Laden der richtigen API

Jetzt laden Sie entweder Ihre CameraOld oder CameraNew Klasse müssen Sie seitdem die API-Ebene überprüfen CameraNew ist nur verfügbar ab api level 21.

Wenn Sie bereits eine Abhängigkeitsinjektion eingerichtet haben, können Sie dies in Ihrem Modul tun, wenn Sie die CameraSupport Implementierung. Beispiel:

@Module public class CameraModule {

    @Provides
    CameraSupport provideCameraSupport(){
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            return new CameraNew(context);
        } else {
            return new CameraOld();
        }
    } 
}

Wenn Sie DI nicht verwenden, können Sie einfach ein Dienstprogramm erstellen oder das Factory-Muster verwenden, um das richtige zu erstellen. Wichtiger Teil ist, dass die API-Ebene überprüft wird.


77
2018-01-21 11:26



Mit dem gleichen Problem konfrontiertunterstützt ältere Geräte über die veraltete Kamera-API und benötigt die neue Camera2-API sowohl für aktuelle Geräte als auch für die Zukunft; Ich bin auf dieselben Probleme gestoßen - und habe nicht eine 3rd-Party-Bibliothek gefunden, die die 2 APIs überbrückt, wahrscheinlich weil sie sehr unterschiedlich sind, Ich wandte mich den grundlegenden OOP-Prinzipien zu.

Die zwei APIs unterscheiden sich deutlich voneinander, so dass sie für Client-Objekte, die die in der alten API dargestellten Schnittstellen erwarten, problematisch sind. Die neue API verfügt über verschiedene Objekte mit unterschiedlichen Methoden, die mit einer anderen Architektur erstellt wurden. Habe Liebe für Google, aber Ragnabbit! das ist frustrierend.

Also habe ich eine Schnittstelle geschaffen, die sich nur auf die Kamerafunktionalität konzentriert, die meine App benötigt, und einen einfachen Wrapper für beide APIs, die diese Schnittstelle implementieren. So muss sich meine Kameraaktivität nicht darum kümmern, auf welcher Plattform sie läuft ...

Ich habe auch einen Singleton eingerichtet, um die API (s) zu verwalten. Die Wrapper der älteren API werden mit meiner Schnittstelle für ältere Android OS-Geräte und die Wrapper-Klasse der neuen API für neuere Geräte mit der neuen API aktualisiert. Der Singleton hat typischen Code, um die API-Ebene zu erhalten, und führt dann das korrekte Objekt aus.

Die gleiche Schnittstelle wird von beiden Wrapper-Klassen verwendetEs spielt also keine Rolle, ob die App auf Jellybean oder Marshmallow läuft - solange die Schnittstelle meine App mit den gleichen Methodensignaturen mit dem versorgt, was sie von beiden Camera-APIs benötigt; Die Kamera läuft in der App auf die gleiche Weise für neuere und ältere Versionen von Android.

Der Singleton kann auch einige verwandte Dinge tun, die nicht an die APIs gebunden sind - wie das Erkennen, dass sich tatsächlich eine Kamera auf dem Gerät befindet und das Speichern in der Medienbibliothek.

Ich hoffe, die Idee hilft dir.


5
2018-06-16 18:25



Jetzt müssen wir android.hardware.camera2 als android.hardware.Camera ist veraltet, die nur auf API> 23 FlashLight funktioniert

   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
2018-06-20 13:47