Как открыть «переднюю камеру» на платформе Android?


83

В более общем плане, если устройство имеет более одной встроенной камеры, есть ли способ инициализировать именно одну из них?

Я не нашел его в справочной документации 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" />

Примечание. Эта функция доступна в Gingerbread (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 Согласен с тобой, дружище. Поскольку у нас есть разные OEM-производители, наша методика программирования меняется в соответствии с нашими потребностями. Спасибо за выделение.

14

Все более старые методы ответов устарели Google (предположительно из-за подобных проблем), поскольку API 21 вам необходимо использовать API камеры 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, в то время как съемные камеры имеют уникальный идентификатор для каждого отдельного устройства, даже если они одной модели.

Однако это означает, что если ситуация с устройством встречается редко, например, только планшет с одной фронтальной камерой, вам нужно подсчитать, сколько у вас встроенных камер, и расположить камеры в порядке их важности («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 градусов обеспечат вам правильный поворот для портрета. На многих устройствах все по-другому.
colintheshots

4

Для API 21 (5.0) и более поздних версий вы можете использовать CameraManager API

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 и выше. Кроме того, на некоторых устройствах невозможно открыть фронтальную камеру напрямую (зависит от производителя).


Получили ли вы какое-либо решение для 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

6
Это чушь. Даже не пытайтесь использовать это.
Адам

4
Это ужасно. НИКОГДА не делайте этого. Этот ответ следует запретить. Camera.open () принимает идентификатор камеры, а не ее порядковый номер! Это не работает на значительном меньшинстве устройств и работает только по чистой случайности.
colintheshots
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.