📅  最后修改于: 2023-12-03 14:59:16.672000             🧑  作者: Mango
Android 中的相机是一个非常重要的功能,可以让我们的应用程序有更多的互动性和创造力。在本教程中,我们将介绍如何使用Android相机实现拍照,录制视频等功能。
首先,在使用相机之前,我们需要在AndroidManifest.xml文件中声明相应的权限。针对不同的功能,我们需要不同的权限:
<uses-permission android:name="android.permission.CAMERA" /> <!-- 相机 -->
<uses-permission android:name="android.permission.RECORD_AUDIO" /> <!-- 录音 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!-- 写入SD卡 -->
在使用相机之前,我们需要先获取相机预览。相机预览需要SurfaceView(或者TextureView)来进行展示。我们需要实现SurfaceHolder.Callback接口来控制SurfaceView的生命周期。具体代码如下:
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
public CameraPreview(Context context, Camera camera) {
super(context);
mCamera = camera;
// 添加SurfaceHolder回调
mHolder = getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
// 在surface被创建时打开相机预览
try {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e) {
Log.e(TAG, "相机预览失败: " + e.getMessage());
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// 在销毁surface之前,停止相机预览
mCamera.stopPreview();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
// 在surface尺寸被改变时,更新相机预览尺寸
if (mHolder.getSurface() == null) {
return;
}
try {
mCamera.stopPreview();
} catch (Exception e) {
// 忽略异常
}
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e) {
Log.e(TAG, "预览尺寸更改失败: " + e.getMessage());
}
}
}
在预览界面中添加一个按钮,点击按钮即可拍照。具体代码如下:
public class MainActivity extends AppCompatActivity {
private Camera mCamera;
private CameraPreview mPreview;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 创建相机实例
mCamera = getCameraInstance();
// 创建相机预览
mPreview = new CameraPreview(this, mCamera);
FrameLayout preview = findViewById(R.id.preview);
preview.addView(mPreview);
// 拍照按钮
Button captureButton = findViewById(R.id.capture);
captureButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mCamera.takePicture(null, null, mPicture);
}
});
}
/** 获取相机实例 */
public static Camera getCameraInstance() {
Camera c = null;
try {
c = Camera.open();
} catch (Exception e) {
Log.e(TAG, "相机打开失败: " + e.getMessage());
}
return c;
}
// 拍照回调
private Camera.PictureCallback mPicture = new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
// 处理照片数据,保存到文件或者显示在界面上
}
};
}
同样是在预览界面中添加一个按钮,点击按钮即可开始、暂停、停止录制视频。具体代码如下:
public class MainActivity extends AppCompatActivity {
private Camera mCamera;
private CameraPreview mPreview;
private MediaRecorder mMediaRecorder;
private boolean isRecording = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 创建相机实例
mCamera = getCameraInstance();
// 创建相机预览
mPreview = new CameraPreview(this, mCamera);
FrameLayout preview = findViewById(R.id.preview);
preview.addView(mPreview);
// 录制视频按钮
Button captureButton = findViewById(R.id.capture);
captureButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (isRecording) {
stopRecording();
} else {
startRecording();
}
}
});
}
/** 获取相机实例 */
public static Camera getCameraInstance() {
Camera c = null;
try {
c = Camera.open();
} catch (Exception e) {
Log.e(TAG, "相机打开失败: " + e.getMessage());
}
return c;
}
/** 开始录制视频 */
private void startRecording() {
// 准备MediaRecorder
mMediaRecorder = new MediaRecorder();
mCamera.unlock();
mMediaRecorder.setCamera(mCamera);
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);
mMediaRecorder.setVideoSize(640, 480);
mMediaRecorder.setVideoFrameRate(30);
mMediaRecorder.setPreviewDisplay(mPreview.getHolder().getSurface());
mMediaRecorder.setOutputFile(getOutputMediaFile(MEDIA_TYPE_VIDEO).toString());
// 开始录制
try {
mMediaRecorder.prepare();
mMediaRecorder.start();
isRecording = true;
} catch (Exception e) {
Log.e(TAG, "录制视频失败: " + e.getMessage());
releaseMediaRecorder();
}
}
/** 停止录制视频 */
private void stopRecording() {
// 停止录制
try {
mMediaRecorder.stop();
} catch (Exception e) {
Log.e(TAG, "停止录制视频失败: " + e.getMessage());
}
releaseMediaRecorder();
mCamera.lock();
isRecording = false;
}
/** 释放MediaRecorder */
private void releaseMediaRecorder() {
if (mMediaRecorder != null) {
mMediaRecorder.reset();
mMediaRecorder.release();
mMediaRecorder = null;
}
}
/** 获取输出媒体文件 */
private static Uri getOutputMediaFileUri(int type) {
return Uri.fromFile(getOutputMediaFile(type));
}
/** 获取输出媒体文件 */
private static File getOutputMediaFile(int type) {
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES), "MyCameraApp");
if (!mediaStorageDir.exists() && !mediaStorageDir.mkdirs()) {
return null;
}
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File mediaFile;
if (type == MEDIA_TYPE_VIDEO) {
mediaFile = new File(mediaStorageDir.getPath() + File.separator + "VID_" + timeStamp + ".mp4");
} else {
return null;
}
return mediaFile;
}
}
通过本教程,我们了解了在Android中使用相机的方法。我们实现了相机预览,拍照以及录制视频三个功能。根据自己的需求,我们可以选择相应的实现。同时,在实际开发中,我们还需要注意相机资源的释放和异常处理等问题。