Jak otworzyć „przedni aparat” na platformie Android?

83

Mówiąc bardziej ogólnie, jeśli urządzenie ma więcej niż jedną wbudowaną kamerę, czy istnieje sposób na zainicjowanie w szczególności jednej z nich?

Nie znalazłem tego w dokumentacji referencyjnej Androida:

Samsung SHW-M100S ma dwa aparaty. Jeśli nie ma wzmianki o używaniu dwóch aparatów, jakiś pomysł, jak zrobił to Samsung ...?

Sol
źródło

Odpowiedzi:

114
private Camera openFrontFacingCameraGingerbread() {
    int cameraCount = 0;
    Camera cam = null;
    Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
    cameraCount = Camera.getNumberOfCameras();
    for (int camIdx = 0; camIdx < cameraCount; camIdx++) {
        Camera.getCameraInfo(camIdx, cameraInfo);
        if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            try {
                cam = Camera.open(camIdx);
            } catch (RuntimeException e) {
                Log.e(TAG, "Camera failed to open: " + e.getLocalizedMessage());
            }
        }
    }

    return cam;
}

Dodaj następujące uprawnienia w AndroidManifest.xmlpliku:

<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" android:required="false" />
<uses-feature android:name="android.hardware.camera.front" android:required="false" />

Uwaga: ta funkcja jest dostępna w wersji Gingerbread (2.3) i nowszej wersji Androida.

Crisoforo Gaspar
źródło
Czy można to w jakiś sposób wykorzystać z Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);techniką otwierania istniejącej aplikacji aparatu?
loeschg
3
@loeschg Intentna swój sposób radzi sobie z ruchem kamery. Ta technika jest używana podczas korzystania SurfaceViewz funkcji aparatu.
to właśnie pomyślałem. Dzięki!
loeschg
2
Bardzo fajny post. Zajęło mi trochę czasu, zanim zrozumiałem, że skierowanie aparatu niekoniecznie jest tym samym, co indeks aparatu. Na przykład mój tablet ma tylko jeden aparat (indeks: 0), ale skierowany do przodu (indeks skierowany: 1). Dlatego używanie prostego kodu, takiego jak Camera.open (CameraInfo.CAMERA_FACING_FRONT), jest bezsensowne.
Matthias,
@Matthias Zgadzam się z tobą kolego. Ponieważ mamy różnych producentów OEM, nasza technika programowania zmienia się zgodnie z naszymi potrzebami. Dzięki za wyróżnienie.
14

Wszystkie metody starszych odpowiedzi są przestarzałe przez Google (prawdopodobnie z powodu takich problemów), ponieważ API 21 musisz użyć API Camera 2:

Ta klasa została wycofana na poziomie API 21. Zalecamy używanie nowego interfejsu API android.hardware.camera2 do nowych aplikacji.

W nowszym interfejsie API masz prawie całkowitą władzę nad aparatem urządzenia z Androidem i dokumentacją, która zawiera wyraźne porady

String[] getCameraIdList()

a następnie użyj uzyskanego CameraId, aby otworzyć kamerę:

void openCamera(String cameraId, CameraDevice.StateCallback callback, Handler handler)

99% przednich kamer ma id = "1", a tylny aparat id = "0", zgodnie z tym:

Kamery niewymienne używają jako identyfikatorów liczb całkowitych zaczynających się od 0, podczas gdy kamery wymienne mają niepowtarzalny identyfikator dla każdego urządzenia, nawet jeśli są tego samego modelu.

Oznacza to jednak , że jeśli sytuacja z urządzeniem jest rzadka, jak np. Tablet z jedną kamerą przednią, należy policzyć liczbę posiadanych kamer wbudowanych i uporządkować je według ich ważności („0”). Więc CAMERA_FACING_FRONT == 1 CAMERA_FACING_BACK == 0, co oznacza, że ​​tylna kamera jest ważniejsza niż przednia.

Nie znam jednolitej metody identyfikacji przedniego aparatu na wszystkich urządzeniach z Androidem. Mówiąc najprościej, system operacyjny Android w urządzeniu nie może naprawdę dowiedzieć się, która kamera jest dokładnie tam, z pewnych powodów: być może jedynym zakodowanym na stałe identyfikatorem kamery jest liczba całkowita reprezentująca jej znaczenie, a może na niektórych urządzeniach, w którą stronę się zwrócisz ... ” plecy".

Dokumentacja : https://developer.android.com/reference/android/hardware/camera2/package-summary.html

Jawne przykłady : https://github.com/googlesamples/android-Camera2Basic


W przypadku starszego API (nie jest to zalecane, ponieważ na nowoczesnych telefonach nie będzie działać nowsza wersja Androida, a transfer jest uciążliwy). Po prostu użyj tego samego Integer CameraID (1), aby otworzyć przednią kamerę, jak w tej odpowiedzi :

cam = Camera.open(1);

Jeśli ufasz OpenCV jako część aparatu:

Wewnątrz

    <org.opencv.android.JavaCameraView
    ../>

użyj następujących dla przedniego aparatu:

        opencv:camera_id="1"
iantonuk
źródło
10

Począwszy od Androida 2.1, Android obsługuje tylko jedną kamerę w swoim SDK. Jest prawdopodobne, że zostanie to dodane w przyszłej wersji Androida.

CommonsWare
źródło
1
to stwierdzenie dotyczy również Androida 2.2?
ozmank
2
@ozmank: Tak, obsługa wielu kamer nie została dodana do Androida 2.3.
CommonsWare
4
public void surfaceCreated(SurfaceHolder holder) {
    try {
        mCamera = Camera.open();
        mCamera.setDisplayOrientation(90);
        mCamera.setPreviewDisplay(holder);

        Camera.Parameters p = mCamera.getParameters();
        p.set("camera-id",2);
        mCamera.setParameters(p);   
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}
Mahesh
źródło
3
Dobra praca na Galaxy S Ważne „camera-id”, a nie „camera_id”
Mahesh
3
Nigdy nie zakładaj, że 90 stopni zapewni prawidłowy obrót portretu. Na wielu urządzeniach jest inaczej.
colintheshots
4

W przypadku interfejsu API 21 (5.0) i nowszych można używać interfejsów API CameraManager

try {
    String desiredCameraId = null;
    for(String cameraId : mCameraIDsList) {
        CameraCharacteristics chars =  mCameraManager.getCameraCharacteristics(cameraId);
        List<CameraCharacteristics.Key<?>> keys = chars.getKeys();
        try {
            if(CameraCharacteristics.LENS_FACING_FRONT == chars.get(CameraCharacteristics.LENS_FACING)) {
               // This is the one we want.
               desiredCameraId = cameraId;
               break;
            }
        } catch(IllegalArgumentException e) {
            // This key not implemented, which is a bit of a pain. Either guess - assume the first one
            // is rear, second one is front, or give up.
        }
    }
}
Airsource Ltd
źródło
4

Aby otworzyć tylną kamerę: -

val cameraIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
startActivityForResult(cameraIntent, REQUEST_CODE_CAMERA)

Aby otworzyć przedni aparat: -

val cameraIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
when {
     Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1 && Build.VERSION.SDK_INT < Build.VERSION_CODES.O -> {
         cameraIntent.putExtra("android.intent.extras.CAMERA_FACING", CameraCharacteristics.LENS_FACING_FRONT)  // Tested on API 24 Android version 7.0(Samsung S6)
     }
     Build.VERSION.SDK_INT >= Build.VERSION_CODES.O -> {
         cameraIntent.putExtra("android.intent.extras.CAMERA_FACING", CameraCharacteristics.LENS_FACING_FRONT) // Tested on API 27 Android version 8.0(Nexus 6P)
         cameraIntent.putExtra("android.intent.extra.USE_FRONT_CAMERA", true)
     }
     else -> cameraIntent.putExtra("android.intent.extras.CAMERA_FACING", 1)  // Tested API 21 Android version 5.0.1(Samsung S4)
}
startActivityForResult(cameraIntent, REQUEST_CODE_CAMERA)

Nie mogłem sprawić, by działało z API 28 i nowszymi. Również bezpośrednie otwarcie przedniego aparatu nie jest możliwe w niektórych urządzeniach (w zależności od producenta).

Shubham Raitka
źródło
Czy masz jakieś rozwiązanie tego problemu dla API 28 i nowszych?
Ankit Gupta
2

Wraz z wydaniem Androida 2.3 (Gingerbread) możesz teraz używać android.hardware.Cameraklasy, aby uzyskać informacje o liczbie kamer, informacje o konkretnej kamerze i odniesienie do konkretnego Camera. Sprawdź nowe Camerainterfejsy API tutaj .

Wesley Wiser
źródło
1

build.gradle

 dependencies {
       compile 'com.google.android.gms:play-services-vision:9.4.0+'
    }

Ustaw widok

CameraSourcePreview mPreview = (CameraSourcePreview) findViewById(R.id.preview);

GraphicOverlay mGraphicOverlay = (GraphicOverlay) findViewById(R.id.faceOverlay);

CameraSource mCameraSource = new CameraSource.Builder(context, detector)
                            .setRequestedPreviewSize(640, 480)
                            .setFacing(CameraSource.CAMERA_FACING_FRONT)
                            .setRequestedFps(30.0f)
                            .build();

           mPreview.start(mCameraSource, mGraphicOverlay);
Dheerendra Mitm
źródło
0
Camera camera;   
if (Camera.getNumberOfCameras() >= 2) {

    //if you want to open front facing camera use this line   
    camera = Camera.open(CameraInfo.CAMERA_FACING_FRONT);

    //if you want to use the back facing camera
    camera = Camera.open(CameraInfo.CAMERA_FACING_BACK);                
}

try {
    camera.setPreviewDisplay("your surface holder here");
    camera.startPreview();      
} catch (Exception e) {  
    camera.release();
}

/ * To nie jest właściwy sposób, jest to rozwiązanie dla starszych urządzeń z systemem Android 4.0 lub starszym. Można to wykorzystać do celów testowych, ale nie jest to zalecane do głównego programowania. To rozwiązanie można traktować jedynie jako rozwiązanie tymczasowe. Ale to rozwiązanie pomogło wielu, więc nie zamierzam usuwać tej odpowiedzi * /

Amalan Dhananjayan
źródło
7
Nie sądzę, żeby to udokumentowane użycie. open (int id) akceptuje identyfikator, a nie pozycję kamery
XY
13
usuń tę mylącą odpowiedź
Alex Cohn
13
@AmalanDhananjayan: zobacz na przykład komentarz @Matthias powyżej : … Zajęło mi trochę czasu,
Alex Cohn
6
To jest balderdash. Nawet nie próbuj tego używać.
Adam
4
To jest przerażające. NIGDY tego nie rób. Ta odpowiedź powinna zostać zakazana. Camera.open () akceptuje identyfikator kamery, a nie wartość porządkową kamery skierowanej w stronę! To zawodzi w przypadku znacznej mniejszości urządzeń i działa tylko dzięki głupiemu szczęściu.
Colintheshots