今天尝试用ChatGpt写一个Android Camera Demo,看看有怎样的惊喜~~
抱歉,作为AI语言模型,我无法提供完整的Android Camera Demo,但我可以给您提供一些基本的代码示例和指南来开始编写您自己的Demo。
- 添加权限
在AndroidManifest.xml文件中添加以下权限:
xml<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STOR
- 创建布局文件
在res/layout文件夹中创建一个名为activity_main.xml的布局文件,并添加一个SurfaceView用于预览相机捕获的图像。
xml<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<SurfaceView
android:id="@+id/surface_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<Button
android:id="@+id/capture_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Capture"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"/>
</RelativeLayout>
- 创建Camera对象
在MainActivity.java文件中创建一个Camera对象,并将其分配给SurfaceView以进行预览。
public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback {
private Camera mCamera;
private SurfaceView mSurfaceView;
private SurfaceHolder mSurfaceHolder;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mSurfaceView = findViewById(R.id.surface_view);
mSurfaceHolder = mSurfaceView.getHolder();
mSurfaceHolder.addCallback(this);
}
private void startCameraPreview() {
try {
mCamera = Camera.open();
mCamera.setPreviewDisplay(mSurfaceHolder);
mCamera.startPreview();
} catch (IOException e) {
e.printStackTrace();
}
}
private void stopCameraPreview() {
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
startCameraPreview();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
if (mSurfaceHolder.getSurface() == null) {
return;
}
stopCameraPreview();
startCameraPreview();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
stopCameraPreview();
}
}
- 拍照
添加一个Button,用于触发拍照操作,并在其OnClick事件中调用Camera.takePicture()方法来捕获图像。
public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback {
private Camera mCamera;
private SurfaceView mSurfaceView;
private SurfaceHolder mSurfaceHolder;
private Button mCaptureButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mSurfaceView = findViewById(R.id.surface_view);
mSurfaceHolder = mSurfaceView.getHolder();
mSurfaceHolder.addCallback(this);
mCaptureButton = findViewById(R.id.capture_button);
mCaptureButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mCamera.takePicture(null, null, mPictureCallback);
}
});
}
private Camera.PictureCallback mPictureCallback = new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
File pictureFile = getOutputMediaFile();
if (pictureFile == null) {
Log.d("MainActivity", "Error creating media file, check storage permissions");
return;
}
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
} catch (FileNotFoundException e) {
Log.d("MainActivity", "File not found: " + e.getMessage());
} catch (IOException e) {
Log.d("MainActivity", "Error accessing file: " + e.getMessage());
}
camera.startPreview();
}
};
private void startCameraPreview() {
try {
mCamera = Camera.open();
mCamera.setPreviewDisplay(mSurfaceHolder);
mCamera.startPreview();
} catch (IOException e) {
e.printStackTrace();
}
}
private void stopCameraPreview() {
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
startCameraPreview();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
if (mSurfaceHolder.getSurface() == null) {
return;
}
stopCameraPreview();
startCameraPreview();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
stopCameraPreview();
}
private static File getOutputMediaFile() {
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), "CameraDemo");
if (!mediaStorageDir.exists()) {
if (!mediaStorageDir.mkdirs()) {
Log.d("CameraDemo", "failed to create directory");
return null;
}
}
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date());
File mediaFile = new File(mediaStorageDir.getPath() + File.separator +
"IMG_" + timeStamp + ".jpg");
return mediaFile;
}
}
这就是一个简单的Android Camera Demo,它可以启动相机并显示预览,还可以捕获图像并将其保存到设备上。当然,您可以根据需要进行更改和扩展,例如添加摄像头切换、闪光灯控制等功能。
================================================================
上面的demo采用的是camera api1的接口,我试着问下,采用camera2 api来写一个。很快,chat gpt就给出了camera2 api的demo例子。我大概看了下,给出的demo基本都是没有问题的,应该是能直接跑的。
使用Camera2 API编写相机应用程序需要更多的代码,但它提供了更多的控制和更好的性能。以下是一个简单的Camera2 API示例应用程序,它可以打开相机、捕获图像并将其保存到设备上。
- 添加权限
在AndroidManifest.xml文件中添加以下权限:
xml<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera2.full" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STO
- 创建布局文件
在res/layout文件夹中创建一个名为activity_main.xml的布局文件,并添加一个TextureView用于预览相机捕获的图像。
xml<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextureView
android:id="@+id/texture_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<Button
android:id="@+id/capture_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Capture"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"/>
</RelativeLayout>
- 创建Camera对象
在MainActivity.java文件中创建一个CameraDevice对象,并将其分配给TextureView以进行预览。
public class MainActivity extends AppCompatActivity {
private TextureView mTextureView;
private Button mCaptureButton;
private CameraDevice mCameraDevice;
private CameraCaptureSession mCaptureSession;
private CaptureRequest.Builder mPreviewRequestBuilder;
private CaptureRequest mPreviewRequest;
private ImageReader mImageReader;
private File mFile;
private final CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() {
@Override
public void onOpened(CameraDevice camera) {
mCameraDevice = camera;
startPreview();
}
@Override
public void onDisconnected(CameraDevice camera) {
camera.close();
mCameraDevice = null;
}
@Override
public void onError(CameraDevice camera, int error) {
camera.close();
mCameraDevice = null;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextureView = findViewById(R.id.texture_view);
mCaptureButton = findViewById(R.id.capture_button);
mCaptureButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
takePicture();
}
});
mFile = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), "CameraDemo");
if (!mFile.exists()) {
mFile.mkdirs();
}
}
@Override
protected void onResume() {
super.onResume();
openCamera();
}
@Override
protected void onPause() {
super.onPause();
closeCamera();
}
private void openCamera() {
CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
try {
String cameraId = manager.getCameraIdList()[0];
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
Size[] sizes = map.getOutputSizes(SurfaceTexture.class);
int width = 640;
int height = 480;
if (sizes != null && sizes.length > 0) {
width = sizes[0].getWidth();
height = sizes[0].getHeight();
}
mImageReader = ImageReader.newInstance(width, height, ImageFormat.JPEG, 1);
mImageReader.setOnImageAvailableListener(mOnImageAvailableListener, null);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
return;
}
manager.openCamera(cameraId, mStateCallback, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private void closeCamera() {
if (mCaptureSession != null) {
mCaptureSession.close();
mCaptureSession = null;
}
if (mCameraDevice != null) {
mCameraDevice.close();
mCameraDevice = null;
}
if (mImageReader != null) {
mImageReader.close();
mImageReader = null;
}
}
private void startPreview() {
try {
SurfaceTexture texture = mTextureView.getSurfaceTexture();
texture.setDefaultBufferSize(mTextureView.getWidth(), mTextureView.getHeight());
Surface surface = new Surface(texture);
mPreviewRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
mPreviewRequestBuilder.addTarget(surface);
mCameraDevice.createCaptureSession(Arrays.asList(surface, mImageReader.getSurface()), new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(CameraCaptureSession session) {
mCaptureSession = session;
try {
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
mPreviewRequest = mPreviewRequestBuilder.build();
mCaptureSession.setRepeatingRequest(mPreviewRequest, null, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
@Override
public void onConfigureFailed(CameraCaptureSession session) {
Toast.makeText(MainActivity.this, "Failed to create capture session", Toast.LENGTH_SHORT).show();
}
}, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private void takePicture() {
if (mCameraDevice == null) {
return;
}
try {
final CaptureRequest.Builder captureBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
captureBuilder.addTarget(mImageReader.getSurface());
captureBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
int rotation = getWindowManager().getDefaultDisplay().getRotation();
captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, getOrientation(rotation));
CameraCaptureSession.CaptureCallback captureCallback = new CameraCaptureSession.CaptureCallback() {
@Override
public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
super.onCaptureCompleted(session, request, result);
Toast.makeText(MainActivity.this, "Image saved: " + mFile.getAbsolutePath(), Toast.LENGTH_SHORT).show();
startPreview();
}
};
mCaptureSession.stopRepeating();
mCaptureSession.abortCaptures();
mCaptureSession.capture(captureBuilder.build(), captureCallback, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private int getOrientation(int rotation) {
CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
try {
String cameraId = manager.getCameraIdList()[0];
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
int sensorOrientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
int deviceOrientation = ORIENTATIONS.get(rotation);
return (sensorOrientation + deviceOrientation + 360) % 360;
} catch (CameraAccessException e) {
e.printStackTrace();
}
return 0;
}
private final ImageReader.OnImageAvailableListener mOnImageAvailableListener = new ImageReader.OnImageAvailableListener() {
@Override
public void onImageAvailable(ImageReader reader) {
Image image = reader.acquireLatestImage();
if (image == null) {
return;
}
ByteBuffer buffer = image.getPlanes()[0].getBuffer();
byte[] bytes = new byte[buffer.remaining()];
buffer.get(bytes);
image.close();
FileOutputStream output = null;
try {
String fileName = "IMG_" + new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date()) + ".jpg";
File file = new File(mFile, fileName);
output = new FileOutputStream(file);
output.write(bytes);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (output != null) {
try {
output.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
};
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);
}
}
这是一个简单的Camera2 API示例应用程序,它可以启动相机并显示预览,还可以捕获图像并将其保存到设备上。当然,您可以根据需要进行更改和扩展,例如添加摄像头切换、闪光灯控制等功能。
Android开发,专注Camera领域.
欢迎大家交流~