如何在安卓平台打开“前置摄像头”?

Posted

技术标签:

【中文标题】如何在安卓平台打开“前置摄像头”?【英文标题】:How do I open the "front camera" on the Android platform? 【发布时间】:2011-02-16 06:21:58 【问题描述】:

更一般地说,如果设备有多个嵌入式摄像头, 有没有办法特别初始化其中一个?

我在 android 参考文档中没有找到它:

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

三星 SHW-M100S 有两个摄像头。如果没有提到使用两个摄像头,你知道三星是怎么做到的吗……?

【问题讨论】:

How to use Front Facing Camera on Samsung Galaxy S的可能重复 【参考方案1】:

从 Android 2.1 开始,Android 在其 SDK 中仅支持单个摄像头。这很可能会在未来的 Android 版本中添加。

【讨论】:

此声明对 Android 2.2 也有效? @ozmank:是的,直到 Android 2.3 才添加多摄像头支持。【参考方案2】:
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();
    

【讨论】:

在 Galaxy S 上工作良好 重要的“camera-id”不是“camera_id” 永远不要假设 90 度会让你得到正确的肖像旋转。它在许多设备上有所不同。【参考方案3】:

随着Android 2.3 (Gingerbread) 的发布,您现在可以使用android.hardware.Camera 类来获取摄像头的数量、特定摄像头的相关信息以及对特定Camera 的引用。查看新的Camera API here。

【讨论】:

【参考方案4】:
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 Intent 以自己的方式处理相机动作。当您使用SurfaceView 来利用相机功能时,会使用此技术。 这就是我的想法。谢谢! 非常酷的帖子。我花了一段时间才发现相机朝向不一定与相机索引相同。例如,我的平板电脑只有一个摄像头(索引:0)但面向前方(面对索引:1)。因此使用像 Camera.open(CameraInfo.CAMERA_FACING_FRONT) 这样的简单代码是没有意义的。 @Matthias 同意你的观点。由于我们有不同的 OEM,我们的编程技术会根据我们的需要进行更改。感谢您强调。【参考方案5】:
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 或更早版本的旧设备的解决方案。这可以用于测试目的,但不推荐用于主要开发。此解决方案只能被视为临时解决方案。但是这个解决方案帮助了很多人,所以我不打算删除这个答案*/

【讨论】:

我认为它没有记录在案的用法。 open(int id) 接受 id,而不是相机位置 请删除这个误导性的答案 @AmalanDhananjayan:例如参见@Matthias above 的评论:……我花了一段时间才发现摄像头朝向不一定与摄像头索引相同。例如,我的平板电脑只有一个摄像头(索引:0)但面向前方(面对索引:1)。因此使用像 Camera.open(CameraInfo.CAMERA_FACING_FRONT) 这样的简单代码是没有意义的。 这是秃头。甚至不要尝试使用它。 这太可怕了。永远不要这样做。这个答案应该被禁止。 Camera.open() 接受一个摄像头 ID,而不是摄像头朝向的序数值!这在极少数设备上都失败了,而且只能靠运气。【参考方案6】:

Google 已弃用所有旧答案的方法(可能是因为这样的麻烦),因为 API 21 你需要 use Camera 2 API:

此类已在 API 级别 21 中弃用。我们建议使用新的 android.hardware.camera2 API 用于新应用程序。

在 the newer 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 操作系统无法真正找出哪个摄像头的确切位置:也许唯一的摄像头硬编码 id 是一个表示其重要性的整数,或者在某些设备上,无论您转向哪一边都会是..”回来”。

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

显式示例:https://github.com/googlesamples/android-Camera2Basic


对于较旧的 API(不建议这样做,因为它不适用于较新的 Android 版本的现代手机,并且传输很麻烦)。只需使用相同的 Integer CameraID (1) 打开前置摄像头,就像在this answer 中一样:

cam = Camera.open(1);

如果您信任 OpenCV 来做相机部分:

里面

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

使用以下前置摄像头:

        opencv:camera_id="1"

【讨论】:

【参考方案7】:

对于 API 21 (5.0) 及更高版本,您可以使用 CameraManager API's

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.
        
    

【讨论】:

【参考方案8】:

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

【讨论】:

【参考方案9】:

打开后置摄像头:-

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 及更高版本,您有解决方案吗?【参考方案10】:

我发现这很好用。

fun frontCamera(context: Context): Int 
    val cameraManager = context.getSystemService(Context.CAMERA_SERVICE) as CameraManager
    return cameraManager.cameraIdList
        .find  id ->
            cameraManager.getCameraCharacteristics(id)[LENS_FACING] == LENS_FACING_FRONT
        ?.toInt() ?: 0

【讨论】:

以上是关于如何在安卓平台打开“前置摄像头”?的主要内容,如果未能解决你的问题,请参考以下文章

如何使前置摄像头拍摄的视频不是逆安卓?

安卓手机打开摄像头失败正在切换另外一个摄像头是怎么回事儿?

android Camera如何判断当前使用的摄像头是前置还是后置

移动端如何通过文件表单调用前置摄像头(IOS和安卓都能用)

如何在android中使用Intent打开前置摄像头?

前置摄像头和后置摄像头同时打开?