我正在使用Camera2API 有我的代码
public class MainActivity extends AppCompatActivity {
private static Context context;
private CameraManager mCameraManager = null;
public static final String LOG_TAG = "mistake";
private final int CAMERA1 = 0;
private final int CAMERA2 = 1;
private CameraHelper[] myCameras = null;
private Button mButtonOpenCamera1 = null;
private Button mButtonOpenCamera2 = null;
private TextureView mImageView = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
context = this;
//получаем обьект камера менеджер
mCameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
mImageView = (TextureView) findViewById(R.id.image_view);
// Получения списка камер в устрйстве
String[] cameraList = new String[0];
try {
cameraList = mCameraManager.getCameraIdList();
} catch (CameraAccessException e) {
e.printStackTrace();
}
//нужно обязательно не забыть инициализировать массив
myCameras = new CameraHelper[cameraList.length];
for (String cameraID : cameraList) {
System.out.println("cameraID: " + cameraID);
int id = Integer.parseInt(cameraID);
// создаем обработчик для камеры
myCameras[id] = new CameraHelper(mCameraManager, cameraID, getApplicationContext());
// выводим инормацию по камере
myCameras[id].viewFormatSize(ImageFormat.YUV_420_888);
// устанавливаем текстуру для отображения
myCameras[id].setTextureView(mImageView);
}
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()) 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()) myCameras[CAMERA2].openCamera();
}
}
});
}
public static void ToastPrint(String cameraId) {
Toast.makeText(context, "Open camera with id: " + cameraId, Toast.LENGTH_LONG).show();
}
}
theri是帮助类
public class CameraHelper {
private CameraCaptureSession mSession = null;
private CameraManager mCameraManager = null;
private CameraDevice mCameraDevice = null;
private String mCameraID = null;
private Context context;
private TextureView mTextureView;
private ImageReader imageReader;
private Handler handler;
private Surface jpegCaptureSurface;
private static ByteArrayOutputStream outputStream;
public CameraHelper(@NonNull CameraManager cameraManager, @NonNull String cameraID, Context context) {
mCameraManager = cameraManager;
mCameraID = cameraID;
this.context = context;
//нужно разобраться с этой строчкой, она 650 в коде
handler = new Handler();
}
public static ByteArrayOutputStream getOutputStream() {
return outputStream;
}
public void viewFormatSize(int formatSize) {
// Получения характеристик камеры, Для получения характеристик необходимо
// использовать метод getCameraCharacteristics(String cameraId). Этот метод возвращает объект
// класса CameraCharacteristics, в котором сконцентрированы параметры по камере. В данном классе
// сконцентрировано огромное количество параметров
CameraCharacteristics cc;
try {
cc = mCameraManager.getCameraCharacteristics(mCameraID);
// Получения списка выходного формата, который поддерживает камера
StreamConfigurationMap configurationMap =
cc.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
// Получения списка разрешений которые поддерживаются для формата jpeg
Size[] sizesJPEG = new Size[0];
if (configurationMap != null) {
sizesJPEG = configurationMap.getOutputSizes(ImageFormat.JPEG);
}
if (sizesJPEG != null) {
for (Size item : sizesJPEG) {
System.out.println("w:" + item.getWidth() + " h:" + item.getHeight());
}
} else {
Log.e(MainActivity.LOG_TAG, "camera with id: " + mCameraID + " don`t support format: " +
formatSize);
}
} catch (CameraAccessException e) {
Log.e(MainActivity.LOG_TAG, e.getMessage());
}
}
public boolean isOpen() {
return mCameraDevice != null;
}
// В методе openCamera() с помощью нашего менеджера открываем камеры. В параметрах метода
// указываем, какую камеру открывать, а также обработчик, который будет отслеживать состояния
// открытия камеры.
public void openCamera() {
try {
// я так понимаю что здесь мы проверяем прописан ли у нас доступ к камере в манифесте и
// если все в порядке то выполняется открытие камеры
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.CAMERA) !=
PackageManager.PERMISSION_GRANTED) {
return;
}
mCameraManager.openCamera(mCameraID, mCameraCallback, null);
} catch (CameraAccessException e) {
Log.e(MainActivity.LOG_TAG, e.getMessage());
}
}
public void closeCamera() {
if (mCameraDevice != null) {
mCameraDevice.close();
mCameraDevice = null;
}
}
private CameraDevice.StateCallback mCameraCallback = new CameraDevice.StateCallback() {
@Override
public void onOpened(@NonNull CameraDevice camera) {
mCameraDevice = camera;
createCameraPreviewSession();
System.out.println("----------" + mCameraDevice.getId());
MainActivity.ToastPrint(mCameraDevice.getId());
}
@Override
public void onDisconnected(@NonNull CameraDevice camera) {
mCameraDevice.close();
Log.i(MainActivity.LOG_TAG, "disconnect camera with id:" + mCameraDevice.getId());
mCameraDevice = null;
}
@Override
public void onError(@NonNull CameraDevice camera, int error) {
Log.i(MainActivity.LOG_TAG, "error! camera id:" + camera.getId() + " error:" + error);
}
};
private void createCameraPreviewSession() {
// для получения изображения нам необходимо использовать ImageReader. Для получения
// максимально возможной скорости передачи кадров нам необходимо использовать «сырой формат». То
// есть, jpeg нам не подойдет, поскольку он будет давать задержку на время конвертации кадра и
// таким образом у нас возникнет очень низкий fps. Для получения максимальной продуктивности
// следует использовать ImageFormat.YUV_420_888.
imageReader = ImageReader.newInstance(640, 480, ImageFormat.JPEG, 2);
imageReader.setOnImageAvailableListener(onImageAvailableListener, handler);
//эти 2 строчки пока не понятно зачем нужны
SurfaceTexture texture = mTextureView.getSurfaceTexture();
texture.setDefaultBufferSize(640, 480);
try {
final CaptureRequest.Builder builder =
mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
builder.addTarget(jpegCaptu reSurface);
// builder.addTarget(surface);
//это добавление возможных эффектов
// builder.set(CaptureRequest.CONTROL_AWB_MODE, CaptureRequest.CONTROL_AWB_MODE_INCANDESCENT);
// builder.set(CaptureRequest.CONTROL_EFFECT_MODE, CaptureRequest.CONTROL_EFFECT_MODE_SEPIA);
// builder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_SINGLE);
mCameraDevice.createCaptureSession(
Collections.singletonList(imageReader.getSurface()),
// Collections.singletonList(surface),
new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(@NonNull CameraCaptureSession session) {
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();
}
}
private final ImageReader.OnImageAvailableListener onImageAvailableListener =
new ImageReader.OnImageAvailableListener() {
@Override
public void onImageAvailable(ImageReader reader) {
final Image image = reader.acquireLatestImage();
jpegCaptureSurface = reader.getSurface();
handler.post(new ImageSaver(context));
}
};
private static class ImageSaver implements Runnable {
private BufferedOutputStream bos;
private Context context;
public ImageSaver(Context context) {
this.context = context;
}
@Override
public void run() {
final File pictureFile = getOutputMediaFile();
if (pictureFile == null) {
return;
}
try {
bos = new BufferedOutputStream(
new FileOutputStream(pictureFile));
bos.write(convertOutputToByteArray(getOutputStream()));
bos.flush();
Toast.makeText(context, "Picture saved: " + pictureFile.getName(),
Toast.LENGTH_SHORT).show();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private byte[] convertOutputToByteArray(ByteArrayOutputStream stream) {
return stream.toByteArray();
}
private static File getOutputMediaFile() {
File mediaStorageDir = new File("/sdcard/", "JCG Camera");
if (!mediaStorageDir.exists()) {
if (!mediaStorageDir.mkdirs()) {
return null;
}
}
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File mediaFile = new File(mediaStorageDir.getPath() + File.separator + "IMG_" +
timeStamp + ".png");
return mediaFile;
}
}
public void setTextureView(TextureView mImageView) {
mTextureView = mImageView;
}
有一个指向我的github的链接:
https://goo.gl/3yaTKo
当我在openCamera()
课程中启动方法CameraHelper
时,
我看到了错误
java.lang.IllegalArgumentException: Null Surface targets are not allowed
at android.hardware.camera2.impl.CameraDeviceImpl.submitCaptureRequest(CameraDeviceImpl.java:602)
at android.hardware.camera2.impl.CameraDeviceImpl.setRepeatingRequest(CameraDeviceImpl.java:663)
at android.hardware.camera2.impl.CameraCaptureSessionImpl.setRepeatingRequest(CameraCaptureSessionImpl.java:204)
at com.example.aleksey.camera2api.CameraHelper$2.onConfigured(CameraHelper.java:185)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
为什么会出错?
答案 0 :(得分:0)
您似乎注释掉了在构建器中设置曲面的线:
// builder.addTarget(surface);
另外,在调用任何依赖它的东西之前,请确保等待表面准备就绪。