Подключение к камере Android

102
25 марта 2021, 16:50

Пытаюсь выводить изображение с камеры на экран, делаю это так:

package com.example.camwifi;
import android.graphics.Matrix;
import android.graphics.RectF;
import android.hardware.Camera;
import android.hardware.Camera.CameraInfo;
import android.hardware.Camera.Size;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.Display;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.Window;
import android.view.WindowManager;
import java.io.IOException;
public class MainActivity extends AppCompatActivity {
    SurfaceView sv;
    SurfaceHolder holder;
    HolderCallback holderCallback;
    Camera camera;
    final int CAMERA_ID = 0;
    final boolean FULL_SCREEN = true;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
        setContentView(R.layout.activity_main);
        Log.i("MyLog","HelloWorld");
        sv = (SurfaceView) findViewById(R.id.surfaceView);
        holder = sv.getHolder();
        holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        holderCallback = new HolderCallback();
        holder.addCallback(holderCallback);
    }
    @Override
    protected void onResume() {
        super.onResume();
        camera = Camera.open(CAMERA_ID);
        setPreviewSize(FULL_SCREEN);
    }
    @Override
    protected void onPause() {
        super.onPause();
        if (camera != null) {
            camera.lock();
            camera.stopPreview();
            camera.release();
            camera = null;
        }
    }
    class HolderCallback implements SurfaceHolder.Callback {
        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            try {
                camera.setPreviewDisplay(holder);
                camera.startPreview();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width,
                                   int height) {
            camera.stopPreview();
            setCameraDisplayOrientation(CAMERA_ID);
            try {
                camera.setPreviewDisplay(holder);
                camera.startPreview();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
        }
    }
    void setPreviewSize(boolean fullScreen) {
        // получаем размеры экрана
        Display display = getWindowManager().getDefaultDisplay();
        boolean widthIsMax = display.getWidth() > display.getHeight();
        // определяем размеры превью камеры
        Size size = camera.getParameters().getPreviewSize();
        RectF rectDisplay = new RectF();
        RectF rectPreview = new RectF();
        // RectF экрана, соотвествует размерам экрана
        rectDisplay.set(0, 0, display.getWidth(), display.getHeight());
        // RectF первью
        if (widthIsMax) {
            // превью в горизонтальной ориентации
            rectPreview.set(0, 0, size.width, size.height);
        } else {
            // превью в вертикальной ориентации
            rectPreview.set(0, 0, size.height, size.width);
        }
        Matrix matrix = new Matrix();
        // подготовка матрицы преобразования
        if (!fullScreen) {
            // если превью будет "втиснут" в экран (второй вариант из урока)
            matrix.setRectToRect(rectPreview, rectDisplay,
                    Matrix.ScaleToFit.START);
        } else {
            // если экран будет "втиснут" в превью (третий вариант из урока)
            matrix.setRectToRect(rectDisplay, rectPreview,
                    Matrix.ScaleToFit.START);
            matrix.invert(matrix);
        }
        // преобразование
        matrix.mapRect(rectPreview);
        // установка размеров surface из получившегося преобразования
        sv.getLayoutParams().height = (int) (rectPreview.bottom);
        sv.getLayoutParams().width = (int) (rectPreview.right);
    }
    void setCameraDisplayOrientation(int cameraId) {
        // определяем насколько повернут экран от нормального положения
        int rotation = getWindowManager().getDefaultDisplay().getRotation();
        int degrees = 0;
        switch (rotation) {
            case Surface.ROTATION_0:
                degrees = 0;
                break;
            case Surface.ROTATION_90:
                degrees = 90;
                break;
            case Surface.ROTATION_180:
                degrees = 180;
                break;
            case Surface.ROTATION_270:
                degrees = 270;
                break;
        }
        int result = 0;
        // получаем инфо по камере cameraId
        CameraInfo info = new CameraInfo();
        Camera.getCameraInfo(cameraId, info);
        // задняя камера
        if (info.facing == CameraInfo.CAMERA_FACING_BACK) {
            result = ((360 - degrees) + info.orientation);
        } else
            // передняя камера
            if (info.facing == CameraInfo.CAMERA_FACING_FRONT) {
                result = ((360 - degrees) - info.orientation);
                result += 360;
            }
        result = result % 360;
        camera.setDisplayOrientation(result);
    }
}

В эмуляторе с версией Android 5.1.1 всё работает нормально, но при запуске в эмуляторе версии Android 9 появляется ошибка Fail to connect to camera service и указывает на строку camera = Camera.open(CAMERA_ID);. Почему в одной версии работает всё нормально, а в другой нет? И как это исправить?

Answer 1

Нужно использовать библиотеку Camera2, вот код для решения этой задачи:

package com.example.camwifi_api21;
import android.Manifest;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.ImageFormat;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.media.Image;
import android.media.ImageReader;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.util.Size;
import android.view.TextureView;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
    private CameraManager mCameraManager=null;
    private final int CAMERA1=0;
    private final int CAMERA2=1;
    CameraHelper[] myCameras=null;
    private Button mButtonOpenCamera1=null;
    private Button mButtonOpenCamera2=null;
    private static final int PERMISSION_REQUEST = 1;
    private TextureView mImageView=null;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mImageView=(TextureView) findViewById(R.id.image_view);
        mCameraManager=(CameraManager) getSystemService(Context.CAMERA_SERVICE);
        try{
            String[] cameraList=mCameraManager.getCameraIdList();
            myCameras=new CameraHelper[cameraList.length];
            for(String cameraID:cameraList){
                Log.i("MyLog",cameraID);
                int id=Integer.parseInt(cameraID);
                myCameras[id]=new CameraHelper(mCameraManager,cameraID);
                myCameras[id].viewFormatSize(ImageFormat.JPEG);
                myCameras[id].setTextureView(mImageView);
            }
        } catch (CameraAccessException e) {
            Log.e("MyLog",e.getMessage());
            e.printStackTrace();
        }
        mButtonOpenCamera1=(Button) findViewById(R.id.btn_open_camera1);
        mButtonOpenCamera2=(Button) findViewById(R.id.btn_open_camera2);
        mButtonOpenCamera1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(myCameras[CAMERA2].isOpen()){
                    myCameras[CAMERA2].closeCamera();
                }
                if(myCameras[CAMERA1]!=null){
                    if(!myCameras[CAMERA1].isOpen()){
                        if(ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED){
                            ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.CAMERA}, PERMISSION_REQUEST);
                        }else{
                            myCameras[CAMERA1].openCamera();
                        }
                    }
                }
            }
        });
        mButtonOpenCamera2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(myCameras[CAMERA1].isOpen()){
                    myCameras[CAMERA1].closeCamera();
                }
                if(myCameras[CAMERA2]!=null){
                    if(!myCameras[CAMERA2].isOpen()){
                        if(ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED){
                            ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.CAMERA}, PERMISSION_REQUEST);
                        }else {
                            myCameras[CAMERA2].openCamera();
                        }
                    }
                }
            }
        });
    }
}
package com.example.camwifi_api21;
import android.annotation.SuppressLint;
import android.graphics.Camera;
import android.graphics.ImageFormat;
import android.graphics.SurfaceTexture;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.media.Image;
import android.media.ImageReader;
import android.media.MediaCas;
import android.support.annotation.NonNull;
import android.util.Log;
import android.util.Size;
import android.view.Surface;
import android.view.TextureView;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.sql.Array;
import java.util.Arrays;
public class CameraHelper {
    private CameraManager mCameraManager = null;
    private String mCameraID = null;
    private CameraDevice mCameraDevice = null;
    private TextureView mTextureView=null;
    private ImageReader mImageReaderYUV;
    private CameraDevice.StateCallback mCameraCallback = new CameraDevice.StateCallback() {
        @Override
        public void onOpened(@NonNull CameraDevice camera) {
            mCameraDevice = camera;
            createCameraPreviesSession();
            Log.i("MyLog", "Open camera with id:" + mCameraDevice.getId());
        }
        @Override
        public void onDisconnected(@NonNull CameraDevice camera) {
            mCameraDevice.close();
            Log.i("MyLog", "disconnect camera with id:" + mCameraDevice.getId());
            mCameraDevice = null;
        }
        @Override
        public void onError(@NonNull CameraDevice camera, int error) {
            Log.i("MyLog", "Error! camera id:" + camera.getId() + " error:" + error);
        }
    };
    private void createCameraPreviesSession(){
        SurfaceTexture texture=mTextureView.getSurfaceTexture();
        texture.setDefaultBufferSize(1920,1080);
        Surface surface=new Surface(texture);
        mImageReaderYUV=ImageReader.newInstance(1920,1080,ImageFormat.YUV_420_888,1);
        try{
            final CaptureRequest.Builder builder=mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
            builder.addTarget(surface);
            mCameraDevice.createCaptureSession(Arrays.asList(surface), new CameraCaptureSession.StateCallback() {
                @Override
                public void onConfigured(@NonNull CameraCaptureSession session) {
                    CameraCaptureSession mSession=session;
                    try{
                        mSession.setRepeatingRequest(builder.build(),null,null);
                    }catch (CameraAccessException e){
                        e.printStackTrace();
                    }
                }
                @Override
                public void onConfigureFailed(@NonNull CameraCaptureSession session) {}
            },null);
        }catch (CameraAccessException e){
            e.printStackTrace();
        }
    }
    public CameraHelper(@NonNull CameraManager cameraManager, @NonNull String cameraID) {
        mCameraManager = cameraManager;
        mCameraID = cameraID;
    }
    public void viewFormatSize(int formatSize) {
        CameraCharacteristics cc = null;
        try {
            cc = mCameraManager.getCameraCharacteristics(mCameraID);
            StreamConfigurationMap configurationMap = cc.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
            Size[] sizeJPEG = configurationMap.getOutputSizes(ImageFormat.JPEG);
            if (sizeJPEG != null) {
                for (Size item : sizeJPEG) {
                    Log.i("MyLog", "w:" + item.getWidth() + " h:" + item.getHeight());
                }
            } else {
                Log.e("MyLog", "camera with id: " + mCameraID + " don't support JPEG");
            }
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }
    public boolean isOpen() {
        if (mCameraDevice == null) {
            return false;
        } else {
            return true;
        }
    }
    @SuppressLint("MissingPermission")
    public void openCamera() {
        try {
            mCameraManager.openCamera(mCameraID, mCameraCallback, null);
        }catch (CameraAccessException e){
            Log.e("MyLog",e.getMessage());
        }
    }
    public void closeCamera(){
        if(mCameraDevice!=null){
            mCameraDevice.close();
            mCameraDevice=null;
        }
    }
    public void setTextureView(TextureView textureView){
        mTextureView=textureView;
    }
}
Answer 2

Все очень просто - Camera давно уже deprecated. Переезжайте на Camera2

READ ALSO
Не работает foreach в JSTL

Не работает foreach в JSTL

Вот jsp файл:

177
Не пойму почему не проходит тест

Не пойму почему не проходит тест

это моя тестовая конфигурация:

113
List vs ArrayList vs Vector

List vs ArrayList vs Vector

Хочу узнать в чём глобальная разница между ArrayList и VectorЯ поискал и нашёл только информацию о том,что вектор синхронизирован ( с чем?)

103
Сделать фрагмент неактивным

Сделать фрагмент неактивным

[![Имеется 2 фрагмента: фрагмент меню, и собственно фрагмент "Предложение дня" При нажатии на кнопку BUTTON, фрагмент "предложение дня" становится...

127