Android的使用前置摄像头进行拍照摄像头、Android

2023-09-05 09:48:37 作者:毒盅。

这是我第一次使用摄像机。我读了很多例子,也文档,所以我试图让自己的类来拍照的前置摄像头。

这就是我想出了:

 公共类CameraController {

私人上下文的背景下;

私人布尔hasCamera;

私人摄像头摄像头;
私人诠释cameraId;

公共CameraController(上下文C){
    上下文= c.getApplicationContext();

    如果(context.getPackageManager()。hasSystemFeature(PackageManager.FEATURE_CAMERA)){
        cameraId = getFrontCameraId();

        如果(cameraId!= -1){
            hasCamera = TRUE;
        }其他{
            hasCamera = FALSE;
        }
    }其他{
        hasCamera = FALSE;
    }
}

公共布尔hasCamera(){
    返回hasCamera;
}

公共无效getCameraInstance(){
    摄像头= NULL;

    如果(hasCamera){
        尝试{
            摄像头= Camera.open(cameraId);
        }
        赶上(例外五){

        }
    }
}

公共无效takePicture(){
    如果(hasCamera){
        camera.takePicture(NULL,NULL,mPicture);
    }
}

公共无效releaseCamera(){
    如果(相机!= NULL){
        camera.release();
        摄像头= NULL;
    }
}

私人诠释getFrontCameraId(){
    INT CAMID = -1;
    INT numberOfCameras = Camera.getNumberOfCameras();
    CameraInfo CI =新CameraInfo();

    的for(int i = 0; I< numberOfCameras;我++){
        Camera.getCameraInfo(I,CI);
        如果(ci.facing == CameraInfo.CAMERA_FACING_FRONT){
            CAMID =我;
        }
    }

    返回CAMID;
}

私人PictureCallback mPicture =新PictureCallback(){
    @覆盖
    公共无效onPictureTaken(byte []的数据,摄像头摄像头){
        文件PictureFile的= getOutputMediaFile();

        如果(PictureFile的== NULL){
            Log.d(TEST,错误创建的媒体文件,检查存储权限);
            返回;
        }

        尝试{
            FileOutputStream中FOS =新的FileOutputStream(PictureFile的);
            fos.write(数据);
            fos.close();
        }赶上(FileNotFoundException异常E){
            Log.d(TEST,找不到文件:+ e.getMessage());
        }赶上(IOException异常E){
            Log.d(TEST,访问文件时出错:+ e.getMessage());
        }
    }
};

私人文件getOutputMediaFile(){
    //为了安全起见,你应该检查SD卡安装
    //在此之前使用Environment.getExternalStorageState()。

    文件mediaStorageDir =新的文件(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),MyCameraApp);

    //这个位置效果最好,如果你希望共享的创建的图像
    //应用程序之间,坚持后,您的应用程序已被卸载。

    //创建存储目录,如果它不存在
    如果(!mediaStorageDir.exists()){
        如果(!mediaStorageDir.mkdirs()){
            返回null;
        }
    }

    //创建一个媒体文件名
    字符串的timeStamp =新的SimpleDateFormat(YYYYMMDD_HHMMSS)格式(新的Date())。

    文件媒体文件;
    媒体文件=新的文件(mediaStorageDir.getPath()+文件分割符+IMG _+的timeStamp +。JPG);

    返回媒体文件;
}
}
 
安卓手机如何设置用前摄像头拍照

所以,该类似乎是美好的,但我不能让任何图片来自它。 在LogCat中我得到了以下内容:

  03-11 19:23:58.556:D / TEST(18655):快照GO!
03-11 19:23:58.556:I / caladbolg(272):2752686164 cald_client.c(464)24404 I [INF] + Cald_Client_ICamera_GetBufInfo指数[0X2]
03-11 19:23:58.556:I / caladbolg(272):2752687080 cald_client.c(487)24404 I [INF]  -  Cald_Client_ICamera_GetBufInfo(0)
03-11 19:23:58.556:I / caladbolg(272):2752687355 cald_client.c(464)24404 I [INF] + Cald_Client_ICamera_GetBufInfo指数[0x3中]
03-11 19:23:58.566:I / caladbolg(272):2752688057 cald_client.c(487)24404 I [INF]  -  Cald_Client_ICamera_GetBufInfo(0)
03-11 19:23:58.566:I / caladbolg(272):2752691108 cald_client.c(755)24404 I [INF] + Cald_Client_ICamera_EnableThumbnail
03-11 19:23:58.566:I / caladbolg(272):2752691749 cald_client.c(772)24404 I [INF] pBufNum [1]
03-11 19:23:58.566:I / caladbolg(272):2752692024 cald_client.c(778)24404 I [INF] PBUF [0]:0x4311b000
03-11 19:23:58.566:I / caladbolg(272):2752692817 cald_client.c(792)24404 I [INF]  -  Cald_Client_ICamera_EnableThumbnail(0)
03-11 19:23:58.566:I / caladbolg(272):2752693519 cald_client.c(832)24404 I [INF] + Cald_Client_ICamera_TakeSnapshot
03-11 19:23:58.566:I / caladbolg(272):2752693763 cald_client.c(849)24404 I [INF] pBufNum [1]
03-11 19:23:58.566:I / caladbolg(272):2752694007 cald_client.c(855)24404 I [INF] PBUF [0]:0x4ad01000
03-11 19:23:58.566:I / caladbolg(272):2752694831 cald_camctrl.c(6197)20324 P [PFM] 2752694831 Cald_CamCtrl_ICamera_TakeSnapshot
03-11 19:23:58.566:E / caladbolg(272):2752695137 cald_camctrl.c(19650)20324 E [CAM]错误:事件没有准备好当前的状态。
03-11 19:23:58.566:E / libcamera(272):receivePictureDone:收到不必要的回调。
03-11 19:23:58.566:I / caladbolg(272):2752696205 cald_client.c(869)24404 I [INF]  -  Cald_Client_ICamera_TakeSnapshot(0)
 

解决方案

我解决了这个问题。阅读一些其他职位和教程之后好像摄像机需要一个虚拟的表面,以preVIEW,即使我们不希望显示在preVIEW。

下面是我的最后code的情况下,任何人都需要它。请注意,以hasCamera我的意思是前置摄像头:

 公共类CameraController {

    私人上下文的背景下;

    私人布尔hasCamera;

    私人摄像头摄像头;
    私人诠释cameraId;

    公共CameraController(上下文C){
        上下文= c.getApplicationContext();

        如果(context.getPackageManager()。hasSystemFeature(PackageManager.FEATURE_CAMERA)){
            cameraId = getFrontCameraId();

            如果(cameraId!= -1){
                hasCamera = TRUE;
            }其他{
                hasCamera = FALSE;
            }
        }其他{
            hasCamera = FALSE;
        }
    }

    公共布尔hasCamera(){
        返回hasCamera;
    }

    公共无效getCameraInstance(){
        摄像头= NULL;

        如果(hasCamera){
            尝试{
                摄像头= Camera.open(cameraId);
                prepareCamera();
            }
            赶上(例外五){
                hasCamera = FALSE;
            }
        }
    }

    公共无效takePicture(){
        如果(hasCamera){
            camera.takePicture(NULL,NULL,mPicture);
        }
    }

    公共无效releaseCamera(){
        如果(相机!= NULL){
            camera.stop preVIEW();
            camera.release();
            摄像头= NULL;
        }
    }

    私人诠释getFrontCameraId(){
        INT CAMID = -1;
        INT numberOfCameras = Camera.getNumberOfCameras();
        CameraInfo CI =新CameraInfo();

        的for(int i = 0; I< numberOfCameras;我++){
            Camera.getCameraInfo(I,CI);
            如果(ci.facing == CameraInfo.CAMERA_FACING_FRONT){
                CAMID =我;
            }
        }

        返回CAMID;
    }

    私人无效prepareCamera(){
        SurfaceView视图=新SurfaceView(上下文);

        尝试{
            camera.set previewDisplay(view.getHolder());
        }赶上(IOException异常E){
            抛出新的RuntimeException(E);
        }

        camera.start preVIEW();

        Camera.Parameters PARAMS = camera.getParameters();
        params.setJpegQuality(100);

        camera.setParameters(PARAMS);
    }

    私人PictureCallback mPicture =新PictureCallback(){
        @覆盖
        公共无效onPictureTaken(byte []的数据,摄像头摄像头){
            文件PictureFile的= getOutputMediaFile();

            如果(PictureFile的== NULL){
                Log.d(TEST,错误创建的媒体文件,检查存储权限);
                返回;
            }

            尝试{
                Log.d(TEST,文件创建);
                FileOutputStream中FOS =新的FileOutputStream(PictureFile的);
                fos.write(数据);
                fos.close();
            }赶上(FileNotFoundException异常E){
                Log.d(TEST,找不到文件:+ e.getMessage());
            }赶上(IOException异常E){
                Log.d(TEST,访问文件时出错:+ e.getMessage());
            }
        }
    };

    私人文件getOutputMediaFile(){
        //为了安全起见,你应该检查SD卡安装
        //在此之前使用Environment.getExternalStorageState()。

        文件mediaStorageDir =新的文件(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),MyCameraApp);

        //这个位置效果最好,如果你希望共享的创建的图像
        //应用程序之间,坚持后,您的应用程序已被卸载。

        //创建存储目录,如果它不存在
        如果(!mediaStorageDir.exists()){
            如果(!mediaStorageDir.mkdirs()){
                返回null;
            }
        }

        //创建一个媒体文件名
        字符串的timeStamp =新的SimpleDateFormat(YYYYMMDD_HHMMSS)格式(新的Date())。

        文件媒体文件;
        媒体文件=新的文件(mediaStorageDir.getPath()+文件分割符+IMG _+的timeStamp +。JPG);

        返回媒体文件;
    }
}
 

This is my first time using a camera. I've read a lot of examples and also the documentation, so I tried to make my own class to take pictures with the front facing camera.

This is what I came up with:

    public class CameraController {

private Context context;

private boolean hasCamera;

private Camera camera;
private int cameraId;

public CameraController(Context c){
    context = c.getApplicationContext();

    if(context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
        cameraId = getFrontCameraId();

        if(cameraId != -1){
            hasCamera = true;
        }else{
            hasCamera = false;
        }
    }else{
        hasCamera = false;
    }
}

public boolean hasCamera(){
    return hasCamera;
}

public void getCameraInstance(){
    camera = null;

    if(hasCamera){
        try{
            camera = Camera.open(cameraId);
        }
        catch(Exception e){

        }
    }
}

public void takePicture(){
    if(hasCamera){
        camera.takePicture(null,null,mPicture);
    }
}

public void releaseCamera(){
    if(camera != null){
        camera.release();
        camera = null;
    }
}

private int getFrontCameraId(){
    int camId = -1;
    int numberOfCameras = Camera.getNumberOfCameras();
    CameraInfo ci = new CameraInfo();

    for(int i = 0;i < numberOfCameras;i++){
        Camera.getCameraInfo(i,ci);
        if(ci.facing == CameraInfo.CAMERA_FACING_FRONT){
            camId = i;
        }
    }

    return camId;
}

private PictureCallback mPicture = new PictureCallback(){
    @Override
    public void onPictureTaken(byte[] data, Camera camera){
        File pictureFile = getOutputMediaFile();

        if(pictureFile == null){
            Log.d("TEST", "Error creating media file, check storage permissions");
            return;
        }

        try{
            FileOutputStream fos = new FileOutputStream(pictureFile);
            fos.write(data);
            fos.close();
        }catch(FileNotFoundException e){
            Log.d("TEST","File not found: "+e.getMessage());
        } catch (IOException e){
            Log.d("TEST","Error accessing file: "+e.getMessage());
        }
    }
};

private  File getOutputMediaFile(){
    // To be safe, you should check that the SDCard is mounted
    // using Environment.getExternalStorageState() before doing this.

    File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),"MyCameraApp");

    // This location works best if you want the created images to be shared
    // between applications and persist after your app has been uninstalled.

    // Create the storage directory if it does not exist
    if(!mediaStorageDir.exists()){
        if(!mediaStorageDir.mkdirs()){
            return null;
        }
    }

    // Create a media file name
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());

    File mediaFile;
    mediaFile = new File(mediaStorageDir.getPath()+File.separator+"IMG_"+timeStamp+".jpg");

    return mediaFile;
}
}

So the class seems to be fine, but I can't get any picture from it. In LogCat I get the following:

03-11 19:23:58.556: D/TEST(18655): SNAPSHOT GO!
03-11 19:23:58.556: I/caladbolg(272): 2752686164 cald_client.c                      (464) 24404 I [INF] + Cald_Client_ICamera_GetBufInfo index[0x2]
03-11 19:23:58.556: I/caladbolg(272): 2752687080 cald_client.c                      (487) 24404 I [INF] - Cald_Client_ICamera_GetBufInfo (0)
03-11 19:23:58.556: I/caladbolg(272): 2752687355 cald_client.c                      (464) 24404 I [INF] + Cald_Client_ICamera_GetBufInfo index[0x3]
03-11 19:23:58.566: I/caladbolg(272): 2752688057 cald_client.c                      (487) 24404 I [INF] - Cald_Client_ICamera_GetBufInfo (0)
03-11 19:23:58.566: I/caladbolg(272): 2752691108 cald_client.c                      (755) 24404 I [INF] + Cald_Client_ICamera_EnableThumbnail 
03-11 19:23:58.566: I/caladbolg(272): 2752691749 cald_client.c                      (772) 24404 I [INF] pBufNum[1]
03-11 19:23:58.566: I/caladbolg(272): 2752692024 cald_client.c                      (778) 24404 I [INF] pBuf[0]:0x4311b000
03-11 19:23:58.566: I/caladbolg(272): 2752692817 cald_client.c                      (792) 24404 I [INF] - Cald_Client_ICamera_EnableThumbnail (0)
03-11 19:23:58.566: I/caladbolg(272): 2752693519 cald_client.c                      (832) 24404 I [INF] + Cald_Client_ICamera_TakeSnapshot 
03-11 19:23:58.566: I/caladbolg(272): 2752693763 cald_client.c                      (849) 24404 I [INF] pBufNum[1]
03-11 19:23:58.566: I/caladbolg(272): 2752694007 cald_client.c                      (855) 24404 I [INF] pBuf[0]:0x4ad01000
03-11 19:23:58.566: I/caladbolg(272): 2752694831 cald_camctrl.c                    (6197) 20324 P [PFM] 2752694831 Cald_CamCtrl_ICamera_TakeSnapshot
03-11 19:23:58.566: E/caladbolg(272): 2752695137 cald_camctrl.c                   (19650) 20324 E [CAM] Error: The event is not ready in the current state.
03-11 19:23:58.566: E/libcamera(272): receivePictureDone: unnecessary callback was received.
03-11 19:23:58.566: I/caladbolg(272): 2752696205 cald_client.c                      (869) 24404 I [INF] - Cald_Client_ICamera_TakeSnapshot (0)

解决方案

I solved the problem. After reading some other posts and tutorials seems like that the camera needs a "dummy" surface to preview, even if we don't want the preview to be shown.

Here's my final code in case anyone needs it. Notice that by "hasCamera" I mean a front facing camera:

   public class CameraController {

    private Context context;

    private boolean hasCamera;

    private Camera camera;
    private int cameraId;

    public CameraController(Context c){
        context = c.getApplicationContext();

        if(context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
            cameraId = getFrontCameraId();

            if(cameraId != -1){
                hasCamera = true;
            }else{
                hasCamera = false;
            }
        }else{
            hasCamera = false;
        }
    }

    public boolean hasCamera(){
        return hasCamera;
    }

    public void getCameraInstance(){
        camera = null;

        if(hasCamera){
            try{
                camera = Camera.open(cameraId);
                prepareCamera();
            }
            catch(Exception e){
                hasCamera = false;
            }
        }
    }

    public void takePicture(){
        if(hasCamera){
            camera.takePicture(null,null,mPicture);
        }
    }

    public void releaseCamera(){
        if(camera != null){
            camera.stopPreview();
            camera.release();
            camera = null;
        }
    }

    private int getFrontCameraId(){
        int camId = -1;
        int numberOfCameras = Camera.getNumberOfCameras();
        CameraInfo ci = new CameraInfo();

        for(int i = 0;i < numberOfCameras;i++){
            Camera.getCameraInfo(i,ci);
            if(ci.facing == CameraInfo.CAMERA_FACING_FRONT){
                camId = i;
            }
        }

        return camId;
    }

    private void prepareCamera(){
        SurfaceView view = new SurfaceView(context);

        try{
            camera.setPreviewDisplay(view.getHolder());
        }catch(IOException e){
            throw new RuntimeException(e);
        }

        camera.startPreview();

        Camera.Parameters params = camera.getParameters();
        params.setJpegQuality(100);

        camera.setParameters(params);  
    }

    private PictureCallback mPicture = new PictureCallback(){
        @Override
        public void onPictureTaken(byte[] data, Camera camera){
            File pictureFile = getOutputMediaFile();

            if(pictureFile == null){
                Log.d("TEST", "Error creating media file, check storage permissions");
                return;
            }

            try{
                Log.d("TEST","File created");
                FileOutputStream fos = new FileOutputStream(pictureFile);
                fos.write(data);
                fos.close();
            }catch(FileNotFoundException e){
                Log.d("TEST","File not found: "+e.getMessage());
            } catch (IOException e){
                Log.d("TEST","Error accessing file: "+e.getMessage());
            }
        }
    };

    private File getOutputMediaFile(){
        // To be safe, you should check that the SDCard is mounted
        // using Environment.getExternalStorageState() before doing this.

        File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),"MyCameraApp");

        // This location works best if you want the created images to be shared
        // between applications and persist after your app has been uninstalled.

        // Create the storage directory if it does not exist
        if(!mediaStorageDir.exists()){
            if(!mediaStorageDir.mkdirs()){
                return null;
            }
        }

        // Create a media file name
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());

        File mediaFile;
        mediaFile = new File(mediaStorageDir.getPath()+File.separator+"IMG_"+timeStamp+".jpg");

        return mediaFile;
    }
}