从相机捕获并显示图像?

时间:2019-01-02 01:46:23

标签: android bitmap android-imageview android-camera2 android-file

我是Android的新手,正在从事一个项目,该项目需要从摄像机捕获图像并在按下按钮时将其显示在屏幕上,同时同时允许用户查看相机的内容流。虽然我查看了诸如this link之类的几个答案,但它们主要涉及使用现有相机应用程序显示图像。但是,我更喜欢使用硬件本身。我的代码主要来自https://inducesmile.com/android/android-camera2-api-example-tutorial/。我将Android Studio 3.2.1和API 22用作最低SDK。这是我的代码:

ACTIVITY_MAIN.XML布局文件

  <?xml version="1.0" encoding="utf-8"?>
  <android.support.constraint.ConstraintLayout 
  xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:exported="true"
  tools:context=".MainActivity">

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:gravity="end"
    android:orientation="vertical" >

    <TextureView
        android:id="@+id/texture"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"  />

    <Button
        android:id="@+id/btn_takepicture"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/take_picture" />

    <ImageView
        android:id="@+id/animation_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1" />

 </LinearLayout>
</android.support.constraint.ConstraintLayout>

STRINGS.XML文件

<resources>
<string name="app_name">ColorDesignProjectAPI22</string>
<string name="take_picture">Take picture</string>
</resources>

MAINACTIVITY.JAVA文件

  package com.user.colordesignprojectapi22;

  import android.support.v7.app.AppCompatActivity;
  import android.os.Bundle;
  import android.Manifest;
  import android.content.Context;
  import android.content.pm.PackageManager;
  import android.graphics.Bitmap;
  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.CameraMetadata;
  import android.hardware.camera2.CaptureRequest;
  import android.hardware.camera2.TotalCaptureResult;
  import android.hardware.camera2.params.StreamConfigurationMap;
  import android.media.Image;
  import android.media.ImageReader;
  import android.os.Environment;
  import android.os.Handler;
  import android.os.HandlerThread;
  import android.support.annotation.NonNull;
  import android.support.v4.app.ActivityCompat;
  import android.util.Log;
  import android.util.Size;
  import android.util.SparseIntArray;
  import android.view.Surface;
  import android.view.TextureView;
  import android.view.View;
  import android.widget.Button;
  import android.widget.ImageView;
  import android.widget.Toast;
  import java.io.File;
  import java.io.FileNotFoundException;
  import java.io.FileOutputStream;
  import java.io.IOException;
  import java.io.OutputStream;
  import java.nio.ByteBuffer;
  import java.util.ArrayList;
  import java.util.Arrays;
  import java.util.List;




public class MainActivity extends AppCompatActivity {
private static final String TAG = "AndroidCameraApi";
private Button takePictureButton;
private TextureView textureView;
private static final SparseIntArray ORIENTATIONS = new SparseIntArray();

static {
    ORIENTATIONS.append(Surface.ROTATION_0, 90);
    ORIENTATIONS.append(Surface.ROTATION_90, 0);
    ORIENTATIONS.append(Surface.ROTATION_180, 270);
    ORIENTATIONS.append(Surface.ROTATION_270, 180);
}

private String cameraId;
protected CameraDevice cameraDevice;
protected CameraCaptureSession cameraCaptureSessions;
protected CaptureRequest.Builder captureRequestBuilder;
private Size imageDimension;
private ImageReader imageReader;
private File file;
private static final int REQUEST_CAMERA_PERMISSION = 200;
private Handler mBackgroundHandler;
private HandlerThread mBackgroundThread;
private Bitmap bitmap;
private ImageView imageView;
private String filepath;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    textureView = findViewById(R.id.texture);
    assert textureView != null;
    textureView.setSurfaceTextureListener(textureListener);
    imageView = new ImageView(this);
    imageView = findViewById(R.id.animation_view);
    takePictureButton = findViewById(R.id.btn_takepicture);
    assert takePictureButton != null;
    takePictureButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            takePicture(); 
        }
    });
}

TextureView.SurfaceTextureListener textureListener = new TextureView.SurfaceTextureListener() {
    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
        openCamera();
    }

    @Override
    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {

    }

    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
        return false; 
    }

    @Override
    public void onSurfaceTextureUpdated(SurfaceTexture surface) {

    }
};
private final CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {
    @Override
    public void onOpened(CameraDevice camera) {
        Log.e(TAG, "onOpened");
        cameraDevice = camera;
        createCameraPreview();
    }

    @Override
    public void onDisconnected(CameraDevice camera) {
        cameraDevice.close();
    }

    @Override
    public void onError(CameraDevice camera, int error) {
        cameraDevice.close();
        cameraDevice = null;
    }
};

protected void startBackgroundThread() {
    mBackgroundThread = new HandlerThread("Camera Background");
    mBackgroundThread.start();
    mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
}

protected void stopBackgroundThread() {
    mBackgroundThread.quitSafely();
    try {
        mBackgroundThread.join();
        mBackgroundThread = null;
        mBackgroundHandler = null;
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

public void takePicture() {
    if ( null == cameraDevice ) {
        Log.e(TAG, "cameraDevice is null");
        return;
    }

    CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
    try {
        CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraDevice.getId());
        Size[] jpegSizes = null;
        if ( characteristics != null ) {
            jpegSizes = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP).getOutputSizes(ImageFormat.JPEG);
        }
        int width = 640;
        int height = 480;
        if ( jpegSizes != null && 0 < jpegSizes.length ) {
            width = jpegSizes[0].getWidth();
            height = jpegSizes[0].getHeight();
        }
        ImageReader reader = ImageReader.newInstance(width, height, ImageFormat.JPEG, 1);
        List<Surface> outputSurfaces = new ArrayList<Surface>(2);
        outputSurfaces.add(reader.getSurface()); 
        outputSurfaces.add(new Surface(textureView.getSurfaceTexture())); 
        final CaptureRequest.Builder captureBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
        captureBuilder.addTarget(reader.getSurface());
        captureBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
        int rotation = getWindowManager().getDefaultDisplay().getRotation(); 
        captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS.get(rotation));
        filepath = Environment.getExternalStorageDirectory().toString();
        final File file = new File(filepath);
        ImageReader.OnImageAvailableListener readerListener = new ImageReader.OnImageAvailableListener() {
            @Override
            public void onImageAvailable(ImageReader reader) {
                Image image = null;
                try {
                    image = reader.acquireLatestImage(); 
                    ByteBuffer buffer = image.getPlanes()[0].getBuffer(); 
                    byte[] bytes = new byte[buffer.capacity()]; 
                    buffer.get(bytes); 
                    save(bytes); 
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    if (image != null) {
                        image.close();
                    }
                }
            }

            private void save(byte[] bytes) throws IOException {
                OutputStream output = null;
                try {
                    output = new FileOutputStream(file);
                    output.write(bytes); 
                }
                finally {
                    if (null != output) {
                        output.close();
                    }
                }
            }
        };
        reader.setOnImageAvailableListener(readerListener, mBackgroundHandler);
        final CameraCaptureSession.CaptureCallback captureListener = new CameraCaptureSession.CaptureCallback() {
            @Override
            public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
                super.onCaptureCompleted(session, request, result);
                Toast.makeText(MainActivity.this, "Saved:" + file, Toast.LENGTH_SHORT).show();
                createCameraPreview();
            }
        };
        cameraDevice.createCaptureSession(outputSurfaces, new CameraCaptureSession.StateCallback() {
            @Override
            public void onConfigured(CameraCaptureSession session) {
                try {
                    session.capture(captureBuilder.build(), captureListener, mBackgroundHandler);
                } catch (CameraAccessException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void onConfigureFailed(CameraCaptureSession session) {
            }
        }, mBackgroundHandler);
    } catch (CameraAccessException e) {
        e.printStackTrace();
    }
}

protected void createCameraPreview() {
    try {
        SurfaceTexture texture = textureView.getSurfaceTexture();
        assert texture != null;
        texture.setDefaultBufferSize(imageDimension.getWidth(), imageDimension.getHeight());
        Surface surface = new Surface(texture);
        captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
        captureRequestBuilder.addTarget(surface);
        cameraDevice.createCaptureSession(Arrays.asList(surface), new CameraCaptureSession.StateCallback() {
            @Override
            public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) {
                if (null == cameraDevice) {
                    return;
                }
                cameraCaptureSessions = cameraCaptureSession;
                updatePreview(); 
            }
            @Override
            public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) {
                Toast.makeText(MainActivity.this, "Configuration change", Toast.LENGTH_SHORT).show();                
            }
        }, null);
    } catch (CameraAccessException e) {
        e.printStackTrace();
    }
}

public void updatePreview() {
    if (null == cameraDevice) {
        Log.e(TAG, "updatePreview error, return");
    }
    captureRequestBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
    try {
            cameraCaptureSessions.setRepeatingRequest(captureRequestBuilder.build(), null, mBackgroundHandler);
                if(file.exists()) {
                    bitmap = BitmapFactory.decodeFile(file.getAbsolutePath()); 
                    if(bitmap!=null) {
                        System.out.println("LONG LIVE!");
                        imageView.setImageBitmap(bitmap);
                    }
                    if(bitmap==null){
                        System.out.println("HELP ME!");
                    }
                }
                if(!(file.exists()) {
                 System.out.println("No!!!!!");
                 }

    } catch (CameraAccessException e) {
        e.printStackTrace();
    }
}

final CameraCaptureSession.CaptureCallback captureCallbackListener = new CameraCaptureSession.CaptureCallback() {
    @Override
    public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
        super.onCaptureCompleted(session, request, result);
        Toast.makeText(MainActivity.this, "Saved:" + file, Toast.LENGTH_SHORT).show();
        createCameraPreview();
    }
};
private void openCamera() {
    CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
    Log.e(TAG, "is camera open");
    try {
        cameraId = manager.getCameraIdList()[0];
        CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
        StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
        assert map != null;
        imageDimension = map.getOutputSizes(SurfaceTexture.class)[0];
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CAMERA_PERMISSION);
            return;
        }
        manager.openCamera(cameraId, stateCallback, null);
    } catch (CameraAccessException e) {
        e.printStackTrace();
    }
    Log.e(TAG, "openCamera X");
}
private void closeCamera() {
    if (cameraDevice != null) {
        cameraDevice.close();
        cameraDevice = null;
    }
    if (imageReader != null) {
        imageReader.close();
        imageReader = null;
    }
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    if (requestCode == REQUEST_CAMERA_PERMISSION) {
        if (grantResults[0] == PackageManager.PERMISSION_DENIED) {
            Toast.makeText(MainActivity.this, "Sorry!!!, you can't use this app without granting permission", Toast.LENGTH_LONG).show();
            finish();
        }
    }
}

@Override
protected void onResume() {
    super.onResume();
    Log.e(TAG, "onResume");
    startBackgroundThread();
    if (textureView.isAvailable()) {
        openCamera();
    } else {
        textureView.setSurfaceTextureListener(textureListener);
    }
}

@Override
protected void onPause() {
    Log.e(TAG, "onPause");
    stopBackgroundThread();
    super.onPause();
 }
}

我确信答案很简单,就像向xml中添加一个新视图或类似的东西一样,但是我已经浏览了一个小时左右的文档,却没有发现任何明显的东西。

提前谢谢!

0 个答案:

没有答案