Camera oder Camera2 API

  • Antworten:15
Sercan Savran
  • Forum-Beiträge: 11

16.04.2017, 09:58:43 via Website

Also vorerst sollte gesagt werden, ich habe die Suchfunktion benutzt (vielleicht aber nicht die richtigen Suchbegriffe eingetippt).

Zu meinem Vorhaben: ich versuche ein Service zu entwickeln, der alle 5 Sekunden im Hintergrund (ich weiß durch recherche, dass ich ein "Fakepreview" dafür machen muss, was nicht angezeigt wird) mit der Frontkamera Bilder schießt, ähnlich wie ein Dashcam halt nur für Bilder.

Als Testgerät habe ich ein Note 2 hier rumliegen (SDK 19). Nun habe ich ein Tutorial durchgearbeitet welches mit der Camera2 API arbeitet und diese API unterstützt nur Geräte ab SDK version 21 (Natoll).

Also ich weiß, dass es eine Camera API gibt, die SDK versionen vor 21 noch unterstütz und ich kann mir denken, dass die ältere Camera API für Geräte mit SDK version ab 21 noch super funktionieren wird (Hoffen wir mal noch lange genug, dass ich nicht nach paar Monaten nochmal umbauen muss :D).

Gibt es irgendwelche tutorials für die normale Camera API, wo ich schnell fuß finden kann. Ich meine es muss nicht unbedingt ein Tutorial sein, wo alle 5 Sekunden ein Bild geschossen werden. Es reicht mir erst einmal zu verstehen, wie ich die Camera API nutzen kann um mit der Frontkamera meines Geräts auf Buttonklick Fotos schießen kann, rest sollte ich (hoffentlich) selbst hinkriegen

Antworten
swa00
  • Forum-Beiträge: 3.704

16.04.2017, 10:06:53 via Website

Hallo Sercan,

hast du mal Stackoverflow durchgeackert ?

Ich habe dort auf Anhieb jede Menge ältere Beispiele ausfindig gemacht.
z.b.
http://stackoverflow.com/questions/14421694/taking-pictures-with-camera-on-android-programmatically

.

P.S Auch wenn du noch neu in diesem Forum bist, begrüssen wir es ,
dass Anfragen zumindest mit einem "Hallo", "Danke" und "Bitte" geschmückt sind.

— geändert am 16.04.2017, 10:08:46

Liebe Grüße - Stefan
[ App - Entwicklung ]

Pascal P.Sercan SavranKlaus

Antworten
Sercan Savran
  • Forum-Beiträge: 11

16.04.2017, 14:09:19 via Website

Hallo swa00,

Zuerst bedanke ich mich für dein angehängtes Link und muss zugeben, dass du recht hast. Ein Hallo/Danke/Bitte sollte zu einem Beitrag dazugehören. Ich versuche mal mit dem auf StackOverflow befindlichen Demo ein wenig rumzuexperimentieren und würde mich bei euch erneut wenden, falls ich bei etwas nicht weiterkomme.

Liebe Grüße :)

Antworten
Sercan Savran
  • Forum-Beiträge: 11

16.04.2017, 14:28:12 via Website

Hallo swa00,

dass war aber nun wirklich nicht dass, was ich meinte. Ich will ja nicht über die interne Kamera-App ein Foto schießen um es dann anschließend abzuspeichern. Mein App soll ja quasi wie ein Dashcam funktionieren und in einem Service im Hintergrund ein Bild mithilfe der Camera API schießen können...

— geändert am 16.04.2017, 14:28:34

Antworten
swa00
  • Forum-Beiträge: 3.704

16.04.2017, 19:40:08 via Website

Hallo Sercan,

die deprecated API ist hier zu finden

https://developer.android.com/reference/android/hardware/Camera.html

Jetzt musst du leider so vorgehen , wie wir das auch tun würden und ggf.
irgendwo ein "veraltetes" Beispiel finden, wenn dir die Doku nicht reicht.

Ich kann mir nicht vorstellen , das Keines mehr zu finden ist ( auch bei stackoverflow )

Liebe Grüße - Stefan
[ App - Entwicklung ]

Sercan Savran

Antworten
Sercan Savran
  • Forum-Beiträge: 11

16.04.2017, 22:31:27 via Website

Hallo,

erstmal danke, dass Ihr euch die Zeit genommen habt zu antworten.
@Pascal P.: wenn ich Camera2 API nehme, werden damit ja nur noch Geräte unterstützt, deren Android Version ab SDK 21 ist? Also kommt es nicht in Frage, wenn ich die Unterstützung auch für Geräte unter SDK 21anbieten will.

Ich habe nun die deprecated API genommen, leider ist es so, dass es bei SDK 24 mit einem Galaxy S7 Edge nicht korrekt funktioniert...

Wenn ich nun auf dem o.g. Gerät mit SDK 24 versuche, bekomme ich bei Camera.getNumberOfCameras() eine 0,
da die Camera ein null ist. Heisst es nun, dass deprecated Camera API mit SDK 24 nicht mehr funktioniert? :O
Auf folgenden Geräten funktioniert es wunderbar:
Galaxy S3 (SDK 16)
Galaxy Note (SDK19)
Huawei P8 Lite (SDK22) (Wobei hier Preview läuft, aber es kommt ein Runtime Exception sobald ich ein Bild aufnehmen will)

public static Camera getCameraInstance(){

    Camera c = null;

        int camCount = 0;
        Camera.CameraInfo camInfo = new Camera.CameraInfo();
        camCount = Camera.getNumberOfCameras();
        for(int i = 0; i <camCount;i++){
            Camera.getCameraInfo(i, camInfo);
            if(camInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT){
                try {
                    c = Camera.open(i);
                    return c;
                }
                catch (Exception e){
                    // Camera is not available (in use or does not exist)
                }
            }
        }
       // c = Camera.open(); // attempt to get a Camera instance


    return c; // returns null if camera is unavailable
}

— geändert am 16.04.2017, 22:45:21

Antworten
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

16.04.2017, 22:34:19 via App

Dann brauchst du eine Klasse die dir beide Apis entsprechend Kapselt. Dann tut es immer und kannst beide benutzen. Dann musst du nur noch entscheiden ab welcher Api Version welche Kamera Ansteuerung benutzt wird.

LG Pascal //It's not a bug, it's a feature. :) ;)

Sercan Savran

Antworten
Sercan Savran
  • Forum-Beiträge: 11

16.04.2017, 22:54:08 via Website

Pascal P.

Dann brauchst du eine Klasse die dir beide Apis entsprechend Kapselt. Dann tut es immer und kannst beide benutzen. Dann musst du nur noch entscheiden ab welcher Api Version welche Kamera Ansteuerung benutzt wird.

Ohh... Da haben sich die Leute von Android ja was sehr gutes einfallen lassen :'(
Also muss ich quasi beide APIs implementieren und bevor ich starte prüfen, welches Android Version das Endgerät
nutzt um dementsprechend deprecated Camera oder Camera2 API zu verwenden? :O

Dies hier habe ich auf StackOverflow gefunden, so könnte ich nun rausfinden ob Endgerät auf SDK 15-21 läuft
oder >= 21 ist?

  if ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1)  
                                        && ((Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP))) {
               // your code here - is between 15-21

     } else if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
               // your code here - is api 21
     }

EDIT: Also Programmiererfahrung habe ich eigentlich soweit, auch in Java. Aber das ganze schreit mir danach, dass ich am besten ein Interface dafür schreibe und der Interface sich um die Orgie (Entschuldige mein Wortwahl) zwischen deprecated Camera und Camera2 API kümmert und ich im Hauptprogramm darum nicht mehr kümmern muss...

— geändert am 17.04.2017, 05:04:11

Antworten
swa00
  • Forum-Beiträge: 3.704

16.04.2017, 22:59:07 via Website

... sieht gut aus :-)

Liebe Grüße - Stefan
[ App - Entwicklung ]

Sercan Savran

Antworten
Sercan Savran
  • Forum-Beiträge: 11

17.04.2017, 05:55:51 via Website

Hallo,

ich habe mich gerade eben rangesetzt und versucht es umzusetzen. Zuerst habe ich es erstmal so abgedeckt, dass ich mir eine eigene CameraOrgy-Klasse geschrieben habe. Im Konstruktor wird nun mit den If-Abfragen entschieden ob es sich um ein Gerät mit SDK Version ab oder unter 21 befindet. Je nach Version wird ein globaler boolean Wert deprecatedCamera auf true oder false gesetzt.

Als erstes habe ich versucht nur die depracated Camera API abzudecken. Im Activity ein CameraOrgy Objekt erstellt und auf Buttonclick die takePicture() Methode aufgerufen:

public void takePicture(){
       //FALLS SDK VERSION <= 21
        if(deprecatedCamera){
            this.c.takePicture(null, null, mPicture);
        }
        //FALL SDK VERSION > 21
        else{
            takeCameraTwoPicture();
        }
    }

Wo sich nur die deprecated Camera im CameraOrgy Klasse befand, war alles in bester Ordnung. Die App öffnete sich ganz normal und auf Buttonclick wurde ein Bild geschossen.

Nun wo sich die Methoden für die Camera 2 API im CameraOrgy Klasse befinden, bekomme ich ein java.lang.VerifyError. Hat es damit zu tun, dass mein minSdkVersion 19 ist? Falls ja wie bekomme ich es gelöst? Ich habe die CameraOrgy-Klasse ja nur deswegen erstellt, damit ich beide Versionsbereiche abdecken kann...
Das sehe ich auf der Console:

**E/AndroidRuntime: FATAL EXCEPTION: main
                  Process: com.example.sercan.camdemo, PID: 29165
                  java.lang.VerifyError: com/example/sercan/camdemo/CameraOrgy
                      at com.example.sercan.camdemo.CameraDemoActivity.onCreate(CameraDemoActivity.java:67)
                      at android.app.Activity.performCreate(Activity.java:5451)
                      at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1093)
                      at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2377)
                      at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2471)
                      at android.app.ActivityThread.access$900(ActivityThread.java:175)
                      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1308)
                      at android.os.Handler.dispatchMessage(Handler.java:102)
                      at android.os.Looper.loop(Looper.java:146)
                      at android.app.ActivityThread.main(ActivityThread.java:5602)
                      at java.lang.reflect.Method.invokeNative(Native Method)
                      at java.lang.reflect.Method.invoke(Method.java:515)
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1283)
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1099)
                      at dalvik.system.NativeStart.main(Native Method)**

— geändert am 17.04.2017, 06:00:29

Antworten
swa00
  • Forum-Beiträge: 3.704

17.04.2017, 07:29:35 via Website

Hallo Sercan,

Unter AS ist leider innerhalb ein und des selben Source keine Abkapselung mit
Preprocessor Direktiven möglich (so wie z.b. unter Visual Studio)

Jetzt müsstest du noch zusätzlich jetzt an dein Gradle ran und dort mit
buildTypes, Configs und ggf mit productFlavors arbeiten.

https://developer.android.com/studio/build/index.html

— geändert am 17.04.2017, 08:18:31

Liebe Grüße - Stefan
[ App - Entwicklung ]

Sercan Savran

Antworten
Sercan Savran
  • Forum-Beiträge: 11

17.04.2017, 11:23:39 via Website

swa00

Hallo swa00

Unter AS ist leider innerhalb ein und des selben Source keine Abkapselung mit
Preprocessor Direktiven möglich (so wie z.b. unter Visual Studio)

Ich verstehe das nicht so ganz? Ich habe bei AndroidStudio ja nicht die Möglichkeit, wie bei C-Sprachereihe
oben etwas vor der Ausführung des Codes auszuführen z.B. wie bei C-Sprachen mit #define o.ä. Oder sollte ich unter preprocessor directive was anderes verstehen? (thinking)

Jetzt müsstest du noch zusätzlich jetzt an dein Gradle ran und dort mit
buildTypes, Configs und ggf mit productFlavors arbeiten.

Verstehe ich das richtig, dass ich 2 Camera Objekte habe, sprich DeprecatedCamera und Camera (implementiert Camera2 API) Klasse und durch mein gradle AndroidStudio mitteilen muss, welches er benutzen muss? Ich steige gerade gar nicht durch, wie sowas zu bewerkstelligen sein soll? :?

Hast du vielleicht Beispiele hierfür, wo Klassen je nach Version selektiert werden? :O
Oder denke ich gerade komplizierter als es eigentlich ist ? :?

Freue mich schon auf eure antworten und bedanke mich im Voraus.

Liebe Grüße :)

Antworten
swa00
  • Forum-Beiträge: 3.704

17.04.2017, 11:43:16 via Website

Hallo Secran,

richtig, unter AS gibt es keine Directive wie z.b. #ifdef, #endif.

Wenn du mit mit Anweisungen wie z.B.

if ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1)

nicht zurecht kommst, dann musst du dir zwei Buildvarianten im Gradle anlegen.

Da das in der Praxis allerdings unter AS recht aufwendig ist , solltest du Dir aus der Erfahrung
heraus lieber zwei Klassen bilden, und diese in zwei unterschiedlichen Projekten verwenden.

Die eleganteste Lösung wäre , wenn du mit eigenen und selbsterstellten Libraries arbeitest.

(So halte ich es in meinem Projekten)

Bis dato habe ich auch noch keine Lösung gefunden, Buildanhängig im Gradle die dependencies zu setzen.

— geändert am 17.04.2017, 11:46:36

Liebe Grüße - Stefan
[ App - Entwicklung ]

Pascal P.Sercan Savran

Antworten
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

17.04.2017, 13:11:38 via App

Ich würde das etwas anders aufbauen:
Ich würde ein Interface definieren dass mir alle Relevanten Methoden liefert welche unabhängig der CameraApiVersion sind.
Dann baue ich 2 Klassen auf für alte und neue Api welche beide das Interface implementieren.
Beim initialisieren muss ich dann einmal die Version prüfen und der Instanz des Interfaces die passende Klasseninstanz hinterlegen.
Somit ist es nach dem Init festgelegt welche CameraApi benutzt wird, man muss nicht ständig​ mit If auf die Version arbeiten und dem Interface ist es egal welche der beiden Klassen dahinter steckt solange beide halt das gleiche machen (von den Methoden her intern natürlich anders aufgebaut etc..)

LG Pascal //It's not a bug, it's a feature. :) ;)

LudySercan Savranswa00

Antworten
Sercan Savran
  • Forum-Beiträge: 11

17.04.2017, 20:43:27 via Website

Hallo,

@swa00
Also du meinst, ich soll am Ende 2 Applikationen auf den PlayStore hochladen? :O

Wenn ich nun bei gehe und eine eigene Library habe, muss die ja auch zwingenderweise beide API's implementieren und da bekomme ich ja auch Fehler oder habe ich da ein Denkfehler?

Bevor ich es vergesse, muss ich noch etwas seltsames berichten, was mir nun widerfahren ist. Wenn ich die Camera auf den FrameLayout anzeigen lasse, schießt es normale Bilder. Entferne ich die Preview kommen dunkle Bilder zustande, als wäre die Helligkeit runtergestellt. Woran liegt das ? :O

Pascal P.

Ich würde das etwas anders aufbauen:
Ich würde ein Interface definieren dass mir alle Relevanten Methoden liefert welche unabhängig der CameraApiVersion sind.
Dann baue ich 2 Klassen auf für alte und neue Api welche beide das Interface implementieren.
Beim initialisieren muss ich dann einmal die Version prüfen und der Instanz des Interfaces die passende Klasseninstanz hinterlegen.
Somit ist es nach dem Init festgelegt welche CameraApi benutzt wird, man muss nicht ständig​ mit If auf die Version arbeiten und dem Interface ist es egal welche der beiden Klassen dahinter steckt solange beide halt das gleiche machen (von den Methoden her intern natürlich anders aufgebaut etc..)

So meinte ich es eigentlich, wo ich meinte, dass das ganze mir nach einem Interface schreit. (cool)

— geändert am 17.04.2017, 20:45:23

Antworten