Como abro a “câmera frontal” na plataforma Android?


82

De forma mais geral, se um dispositivo tiver mais de uma câmera embutida, há uma maneira de inicializar uma delas em particular?

Não o encontrei na documentação de referência do Android:

Samsung SHW-M100S possui duas câmeras. Se não houver referência ao uso de duas câmeras, alguma ideia de como a Samsung fez ...?


Respostas:


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

Adicione as seguintes permissões no AndroidManifest.xmlarquivo:

<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" />

Nota: Este recurso está disponível no Gingerbread (2.3) e na versão Android superior.


É possível usar isso de alguma forma com a Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);técnica para abrir o aplicativo de câmera existente?
loeschg

3
@loeschg Intentlida com a ação da câmera à sua maneira. Essa técnica é usada quando você está usando SurfaceViewpara explorar a funcionalidade da câmera.

isso é o que eu imaginei. Obrigado!
loeschg

2
Postagem muito legal. Levei um tempo para descobrir que a face da câmera não é necessariamente a mesma que o índice da câmera. Por exemplo, meu tablet tem apenas uma câmera (índice: 0), mas voltado para a frente (índice voltado: 1). Portanto, usar o código simples como Camera.open (CameraInfo.CAMERA_FACING_FRONT) é um absurdo.
Matthias

@Matthias Concordo com você, companheiro. Como temos diferentes OEMs, nossa técnica de programação é alterada de acordo com nossas necessidades. Obrigado por destacar.

14

Todos os métodos de respostas mais antigos foram descontinuados pelo Google (supostamente por causa de problemas como este), já que a API 21 você precisa usar a API Camera 2:

Esta classe foi descontinuada na API de nível 21. Recomendamos o uso da nova API android.hardware.camera2 para novos aplicativos.

Na API mais recente, você tem poder quase total sobre a câmera do dispositivo Android e a documentação orienta explicitamente para

String[] getCameraIdList()

e usar o CameraId obtido para abrir a câmera:

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

99% das câmeras frontais têm id = "1", e a id da câmera traseira = "0" de acordo com isto:

As câmeras não removíveis usam números inteiros começando em 0 para seus identificadores, enquanto as câmeras removíveis têm um identificador exclusivo para cada dispositivo individual, mesmo se forem do mesmo modelo.

No entanto , isso significa que se a situação do dispositivo for rara, como apenas um tablet com câmera frontal, você precisará contar quantas câmeras embutidas você tem e colocar a ordem da câmera por sua importância ("0"). Então CAMERA_FACING_FRONT == 1 CAMERA_FACING_BACK == 0, o que implica que a câmera traseira é mais importante do que a frontal.

Não sei sobre um método uniforme para identificar a câmera frontal em todos os dispositivos Android. Dito de forma simples, o sistema operacional Android dentro do dispositivo não pode realmente descobrir qual câmera está exatamente onde por alguns motivos: talvez a única ID codificada da câmera seja um número inteiro representando sua importância ou talvez em alguns dispositivos, o lado que você virar estará .. " costas".

Documentação : https://developer.android.com/reference/android/hardware/camera2/package-summary.html

Exemplos explícitos : https://github.com/googlesamples/android-Camera2Basic


Para a API mais antiga (não é recomendado, porque não funcionará em telefones modernos com a versão Android mais recente e a transferência é uma dor no traseiro). Basta usar o mesmo Integer CameraID (1) para abrir a câmera frontal como nesta resposta :

cam = Camera.open(1);

Se você confia no OpenCV para fazer a parte da câmera:

Dentro

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

use o seguinte para a câmera frontal:

        opencv:camera_id="1"

10

A partir do Android 2.1, o Android suporta apenas uma única câmera em seu SDK. É provável que isso seja adicionado em uma versão futura do Android.


1
esta declaração é válida para Android 2.2 também?
ozmank

2
@ozmank: Sim, o suporte a múltiplas câmeras não foi adicionado até o Android 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();
    }
}

3
Bom trabalho no Galaxy S Importante "camera-id" e não "camera_id"
Mahesh

3
Nunca presuma que 90 graus lhe dará a rotação correta para retrato. É diferente em muitos dispositivos.
colintheshots

4

Para API 21 (5.0) e posterior, você pode usar a 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.
        }
    }
}

4

Para abrir a câmera traseira : -

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

Para abrir a câmera frontal : -

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)

Não consegui fazer funcionar para API 28 e superior. Além disso, abrir a câmera frontal diretamente não é possível em alguns dispositivos (depende do fabricante).


2

Com o lançamento do Android 2.3 (Gingerbread), agora você pode usar a android.hardware.Cameraclasse para obter o número de câmeras, informações sobre uma câmera específica e obter uma referência para uma específica Camera. Confira as novas CameraAPIs aqui .


1

build.gradle

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

Definir vista

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);

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();
}

/ * Esta não é a maneira correta, esta é uma solução para dispositivos mais antigos que executam Android 4.0 ou mais antigo. Isso pode ser usado para fins de teste, mas não recomendado para o desenvolvimento principal. Esta solução pode ser considerada apenas como uma solução temporária. Mas essa solução tem ajudado muitos, então não pretendo excluir esta resposta * /


7
Não acho que seja um uso documentado. aberto (int id) aceita o id, não a posição da câmera
XY de

13
remova esta resposta enganosa
Alex Cohn

13
@AmalanDhananjayan: veja, por exemplo, o comentário de @Matthias acima : … Levei um tempo para descobrir que a face da câmera não é necessariamente o mesmo que o índice da câmera. Por exemplo, meu tablet tem apenas uma câmera (índice: 0), mas voltado para a frente (índice voltado: 1). Portanto, usar o código simples como Camera.open (CameraInfo.CAMERA_FACING_FRONT) é um absurdo.
Alex Cohn

5
Isso é bobagem. Nem tente usar isso.
Adam

4
Isso é horrível. NUNCA faça isso. Esta resposta deve ser banida. Camera.open () aceita um id de câmera, não o valor ordinal da face da câmera! Isso falha em uma minoria significativa de dispositivos e só funciona por pura sorte.
colintheshots
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.