SurfaceView Camera App切换相机并修复黑暗预览

用户名

我正在使用表面视图构建相机应用程序。该应用程序正确加载了相机并捕获了图像。图像捕获中有两种情况:

  1. 图像被捕获,没有任何内容(即字节数组)发送到预览活动。在这里工作正常。

  2. 捕获图像,并将来自图片回调的字节数组发送到预览活动。

在第二种情况下,该应用程序显示黑屏,并且无响应。我不相信原因,因为我检查了许多教程并看到了相同的代码。

到目前为止,这是我的代码:

public class ImageActivity extends AppCompatActivity implements SurfaceHolder.Callback {

private static final String TAG = ImageActivity.class.getSimpleName();

private ImageButton closeIV;
private ImageView flipCameraIV;
private FloatingActionButton fab_capture;
private LinearLayout galleryLayout;

private Camera camera;
private Camera.PictureCallback jpegCallback;
private SurfaceView surfaceView;
private SurfaceHolder holder;

private int currCamId = 0;

private boolean isGalleryImg = false;
private boolean isCameraImg = false;

private byte[] camBytes = null;

private static final int GAL_REQ_CODE = 240;
private static final int CAM_PERM_CODE = 242;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
    setContentView(R.layout.activity_image);

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        getWindow().setStatusBarColor(getResources().getColor(R.color.black));
    }

    init();

    holder = surfaceView.getHolder();
    holder.addCallback(this);
    holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

    currCamId = Camera.CameraInfo.CAMERA_FACING_BACK;

}

private void handleClicks() {

    closeIV.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            finish();
        }
    });

    flipCameraIV.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Log.d(TAG, "Flip Clicked");
            switchCamera();
        }
    });

    galleryLayout.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            isGalleryImg = true;
            Log.d(TAG, "Gallery Button Clicked");
            Intent galleryIntent = new Intent(Intent.ACTION_GET_CONTENT);
            galleryIntent.setType("image/*");
            startActivityForResult(galleryIntent, GAL_REQ_CODE);
        }
    });

    fab_capture.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            captureImage();
        }
    });

    jpegCallback = new Camera.PictureCallback() {
        @Override
        public void onPictureTaken(byte[] bytes, Camera camera) {
            assert bytes != null;
            Log.d(TAG, "Camera Bytes Array Length:\t" + bytes.length);

            isCameraImg = true;

            ByteArrayOutputStream baos = new ByteArrayOutputStream();


            Intent intent = new Intent(ImageActivity.this, PreviewActivity.class);
            intent.putExtra("camera_bytes", bytes);
            intent.putExtra("fromCamera", isCameraImg);
            startActivity(intent);
            return;

            //refreshCamera();
        }
    };

}


private void captureImage() {
    camera.takePicture(null, null, jpegCallback);
}

public void refreshCamera() {
    if (holder.getSurface() == null) {
        return; // preview surface is empty
    }

    // stop preview, then make changes
    try {
        camera.stopPreview();
    } catch (Exception ex) {
        ex.printStackTrace();
    }

    try {
        camera.setPreviewDisplay(holder);
        camera.startPreview();
    } catch (IOException e) {
        e.printStackTrace();
    }

}

private void init() {
    closeIV = findViewById(R.id.closeIV);
    fab_capture = findViewById(R.id.fab_capture);
    galleryLayout = findViewById(R.id.galleryLayout);
    flipCameraIV = findViewById(R.id.flipCameraIV);
    surfaceView = findViewById(R.id.surfaceView);

    handleClicks();

}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if (requestCode == GAL_REQ_CODE && resultCode == RESULT_OK) {
        Uri imgUri = data.getData();
        Intent intent = new Intent(ImageActivity.this, PreviewActivity.class);
        intent.putExtra("fromGallery", isGalleryImg);
        intent.putExtra("gallery_image", imgUri.toString());
        startActivity(intent);
    }

}

@TargetApi(Build.VERSION_CODES.M)
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {

    for (int mResults : grantResults) {
        if (mResults == PackageManager.PERMISSION_DENIED) {
            requestPermissions(new String[]{Manifest.permission.CAMERA,
                            Manifest.permission.WRITE_EXTERNAL_STORAGE},
                    CAM_PERM_CODE);
        } else {
            Toast.makeText(ImageActivity.this, "Permission Already Granted", Toast.LENGTH_SHORT).show();
        }
    }

}

@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
    openCamera();
}

private void openCamera() {
    try {
        camera = Camera.open(currCamId);
    } catch (RuntimeException rex) {
        rex.printStackTrace();
    }

    Camera.Parameters parameters = camera.getParameters();
    parameters.setPreviewFrameRate(20);
    parameters.setPreviewSize(352, 288);
    camera.setDisplayOrientation(90);
    camera.setParameters(parameters);

    try {
        camera.setPreviewDisplay(holder);
    } catch (IOException e) {
        e.printStackTrace();
    }
    camera.startPreview();
}

@Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
    refreshCamera();
}

@Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
    camera.stopPreview();
    camera.release();
    camera = null;

}

@Override
protected void onPause() {
    super.onPause();
    camera.stopPreview();
}

@Override
protected void onDestroy() {
    super.onDestroy();
    if (camera != null){
        camera.stopPreview();
        camera.release();
        camera = null;
    }
}

}

另外,我尝试使用此代码段切换到前置摄像头,然后再切换回,但不起作用。

private void switchCamera() {

    // code I tried to switch camera with but not working

    if (currCamId == Camera.CameraInfo.CAMERA_FACING_BACK){
        currCamId = Camera.CameraInfo.CAMERA_FACING_FRONT;
    } else {
        currCamId = Camera.CameraInfo.CAMERA_FACING_BACK;
    }

    camera = Camera.open(currCamId);
    Camera.CameraInfo info = new Camera.CameraInfo();
    Camera.getCameraInfo(Camera.CameraInfo.CAMERA_FACING_FRONT, info);

    int rotation = this.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 rotate = (info.orientation - degrees + 360) % 360;
    Camera.Parameters parameters = camera.getParameters();
    parameters.setRotation(rotate);

    try {
        camera.setPreviewDisplay(surfaceView.getHolder());
    } catch (IOException e) {
        e.printStackTrace();
    }

    camera.setParameters(parameters);
    camera.setDisplayOrientation(90);
    camera.startPreview();

    //openCamera();

}

我需要解决此问题的帮助。谢谢。

阿索坎

如我所见,您正在尝试将图片作为字节数组发送,这是不可能的。因为自api23以来,意图大小受到限制。发送临时演员时,您必须考虑临时演员的大小,这确实会破坏用户体验并导致新活动的加载速度变慢。

无论如何,您的字节数组对于所有这些图片数据来说都太大了,我认为这会引起anr。你该怎么办 您必须先将该字节数组另存为jpeg文件,然后再将文件路径添加到您的意图中。看看这个解决方案

哦,而且,只是基于经验的友好建议,最好使用良好的相机库,而不要使用android-sdk的经典用法。正如我可以说的那样,Android开发的最糟糕的部分是关于媒体的,特别是关于相机api的任何事情。自2015年以来,与ios和google相比,这方面的进展令人遗憾。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

倾斜相机预览的SurfaceView

Camera和SurfaceView的奇怪行为

Camera View SurfaceView仅存储在横向中

Android SurfaceView预览模糊

来自MainActivity的Camera API SurfaceView的错误直接打开活动

在其中包含Camera Preview的SurfaceView截屏

带有Surfaceview的Android相机

适用于相机的SurfaceView与TextureView?

Android自定义相机拉伸Surfaceview

使用Surfaceview尺寸调整相机视图

SurfaceView在相机图像上显示噪点

从相机,SurfaceView或SurfaceHolder连续获取图像数据

SurfaceView-> Surface没有有效的本机窗口| Android Camera API | hardware.camera2

创建camera2会话后如何添加SurfaceView的多个表面

Android Camera 2 API镜头切换

相机实时预览在相机切换时冻结

CustomPaint Over Camera预览

如何在ContinuousCaptureActivity中使相机预览的面积为SurfaceView的一半

Android-在活动之间共享Surfaceview或在切换活动时阻止绘图任务锁定主线程

Android:如何在已经显示Camara预览的Surfaceview上绘制

滚动时,相机SurfaceView在视图寻呼机中闪烁

Android CameraControls /相机缩放/ SurfaceView问题-原因是什么?

在Android中使用SurfaceView在应用程序内使用相机

相机的SurfaceView在Android Lollipop OS中不起作用

如何在SurfaceView Android上制作裁剪相机视图

Camera App支持的方向?

Camera2可以连续访问相机预览图像

片段中的Android Camera预览

切换到前置摄像头和后置摄像头Android SurfaceView