Як відкрити "фронтальну камеру" на платформі Android?


82

Більш загально, якщо пристрій має більше однієї вбудованої камери, чи є спосіб ініціалізувати одну з них зокрема?

Я не знайшов його в довідковій документації Android:

Samsung SHW-M100S має дві камери. Якщо немає посилання на використання двох камер, будь-яка ідея, як це зробив Samsung ...?


Відповіді:


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

Додайте такі дозволи у AndroidManifest.xmlфайл:

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

Примітка: Ця функція доступна у Прянику (2.3) та версії Android.


Чи можна якось використовувати це за допомогою Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);техніки, щоб відкрити існуючу програму камери?
loeschg

3
@loeschg по-своєму Intentобробляє дії камери. Цей прийом використовується, коли ви використовуєте SurfaceViewфункціонал камери.

ось що я зрозумів. Дякую!
loeschg

2
Дуже класний пост. Мені знадобився деякий час, щоб зрозуміти, що облицювання камери необов’язково є однаковим, ніж індекс камери. Наприклад, у мого планшета є лише одна камера (індекс: 0), але спрямована спереду (індекс: 1). Тому використання простого коду, такого як Camera.open (CameraInfo.CAMERA_FACING_FRONT), є нісенітницею.
Маттіас

@Matthias Погоджуюсь з тобою, приятель. Оскільки у нас різні виробники, наша техніка програмування змінюється відповідно до наших потреб. Дякуємо за виділення.

14

Усі старіші методи відповідей застаріли Google (нібито через подібні проблеми), оскільки API 21 вам потрібно використовувати API Camera 2:

Цей клас застарів на рівні API 21. Ми рекомендуємо використовувати новий API android.hardware.camera2 для нових додатків.

У новому API у вас є майже повна влада над камерою пристрою Android і документація явно радить

String[] getCameraIdList()

а потім використовуйте отриманий CameraId, щоб відкрити камеру:

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

99% фронтальних камер мають id = "1", а задню камеру id = "0" відповідно до цього:

Незнімні камери використовують цілі числа, що починаються з 0, для своїх ідентифікаторів, тоді як знімні камери мають унікальний ідентифікатор для кожного окремого пристрою, навіть якщо вони однакові моделі.

Однак це означає, що, якщо ситуація з пристроєм є рідкісною, як просто планшет з 1 фронтальною камерою, вам потрібно підрахувати, скільки вбудованих камер у вас, і розмістити порядок камери за її значимістю ("0"). Отже, CAMERA_FACING_FRONT == 1 CAMERA_FACING_BACK == 0, що означає, що задня камера важливіша за фронтальну.

Я не знаю про єдиний метод ідентифікації фронтальної камери на всіх пристроях Android. Простіше кажучи, ОС Android всередині пристрою з якихось причин насправді не може дізнатись, яка саме камера є. Можливо, єдиним твердокодованим ідентифікатором камери є ціле число, що представляє її важливість, або, можливо, на деяких пристроях, на яку би сторону ви не звернулися ... " назад ".

Документація : https://developer.android.com/reference/android/hardware/camera2/package-summary.html

Явні приклади : https://github.com/googlesamples/android-Camera2Basic


Для старішого API (не рекомендується, оскільки він не буде працювати на сучасних телефонах новішої версії Android, а передача - це важка справа). Просто використовуйте той самий Integer CameraID (1), щоб відкрити фронтальну камеру, як у цій відповіді :

cam = Camera.open(1);

Якщо ви довіряєте OpenCV виконати частину камери:

Всередині

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

для фронтальної камери використовуйте наступне:

        opencv:camera_id="1"

10

Станом на Android 2.1, Android підтримує лише одну камеру в своєму SDK. Цілком ймовірно, що це буде додано в майбутньому випуску Android.


1
це твердження справедливо і для Android 2.2?
ozmank

2
@ozmank: Так, підтримка декількох камер не була додана до 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
Хороша робота над Galaxy S Важливий "camera-id", а не "camera_id"
Махеш,

3
Ніколи не вважайте, що 90 градусів дадуть вам правильний поворот для портрета. На багатьох пристроях все по-різному.
колінтоші

4

Для API 21 (5.0) та пізніших версій ви можете використовувати 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

Щоб відкрити задню камеру: -

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

Щоб відкрити передню камеру: -

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)

Я не міг змусити це працювати для API 28 і вище. Крім того, безпосереднє відкриття передньої камери неможливо на деяких пристроях (залежить від виробника).


2

З виходом Android 2.3 (Gingerbread) тепер ви можете використовувати android.hardware.Cameraклас, щоб отримати кількість камер, інформацію про конкретну камеру та отримати посилання на конкретну Camera. Ознайомтесь з новими CameraAPI тут .


1

build.gradle

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

Встановити подання

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

/ * Це не належним чином, це рішення для старих пристроїв, що працюють під управлінням Android 4.0 або старішої версії. Це можна використовувати для тестування, але не рекомендується для основної розробки. Це рішення можна розглядати лише як тимчасове рішення. Але це рішення допомогло багатьом, тому я не маю наміру видаляти цю відповідь * /


7
Я не думаю, що це задокументоване використання. open (int id) приймає ідентифікатор, а не положення камери
XY

13
вилучіть цю оманливу відповідь
Alex Cohn

13
@AmalanDhananjayan: див., Наприклад, коментар @Matthias вище : ... Мені
Alex Cohn

5
Це болдердаш. Навіть не намагайтеся цим користуватися.
Адам

4
Це жахливо. НІКОЛИ цього не роби. Цю відповідь слід заборонити. Camera.open () приймає ідентифікатор камери, а не порядкове значення обличчя камери! Це не вдається на значній більшості пристроїв і працює лише завдяки чистій німій удачі.
colintheshots
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.