Android4.4实现简单的录像功能
一、前言
在Android中实现录像功能,高版本Android和低版本Android的API使用方式不同。本文以Android4.4系统为基础,简单的列举一下实现过程。
二、步骤
要在 Android 4.4 中实现录像功能,可按照以下步骤进行操作:
-
在布局文件中添加一个 SurfaceView 控件,作为预览画面的容器。
-
获取 Camera 对象,并设置参数配置和预览界面。
-
创建一个 MediaRecorder 对象,并设置相关参数,如编码方式、分辨率、帧率等。同时,还需要指定输出文件的路径和格式。
-
在录像开始前,先调用 Camera 的 stopPreview() 方法停止预览,然后调用 MediaRecorder 的 prepare() 方法进行初始化。
-
开始录像,调用 MediaRecorder 的 start() 方法开始录制视频。
-
结束录像,调用 MediaRecorder 的 stop() 方法停止录制。然后记得要释放 MediaRecorder 对象。
-
最后,再调用 Camera 的 startPreview() 方法重新开始预览。
三、代码实现
-
布局等相关文件实现
布局里面包含一个SurfaceView组件和Button组件,activity_main.xml文件如下:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/container"android:layout_width="match_parent"android:layout_height="match_parent"><SurfaceViewandroid:id="@+id/surface_view"android:layout_width="match_parent"android:layout_height="match_parent" /><Buttonandroid:id="@+id/btn_record"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentBottom="true"android:layout_centerHorizontal="true"android:layout_marginBottom="16dp"android:text="@string/record_start"android:onClick="onClick"/>RelativeLayout>strings.xml文件,用于字符串操作,实现如下:
<resources><string name="app_name">Recordstring><string name="record_start">录制string><string name="record_stop">停止string> resources> -
具体代码实现
新建一个MainActivity.java文件,实现如下:
package com.example.record;import android.annotation.SuppressLint; import android.app.Activity; import android.hardware.Camera; import android.media.MediaRecorder; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.os.Message; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.widget.Button;import java.io.File; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date;public class MainActivity extends Activity implements SurfaceHolder.Callback {private static final String TAG = "MainActivity";// 默认为trueprivate static boolean mIsRecording = false;private Button mRecordButton = null;private SurfaceView mSurfaceView = null;private SurfaceHolder mSurfaceHolder = null;private MediaRecorder mMediaRecorder = null;private Camera mCamera = null;private static final int MSG_UPDATE_BUTTON_TEXT = 0x00;@SuppressLint("HandlerLeak")private Handler mHandler = new Handler() {@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);switch (msg.what) {case MSG_UPDATE_BUTTON_TEXT:if (mRecordButton != null) {mRecordButton.setText(String.valueOf(msg.obj));}break;default:break;}}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);Log.d(TAG, "onCreate");setContentView(R.layout.activity_main);initView();}@Overrideprotected void onResume() {super.onResume();Log.d(TAG, "onDestroy");}@Overrideprotected void onDestroy() {super.onDestroy();Log.d(TAG, "onDestroy");if (mIsRecording) {stopRecording();}}// 初始化View 组件private void initView() {Log.d(TAG, "initView");if (mRecordButton == null) {mRecordButton = (Button) findViewById(R.id.btn_record);}if (mSurfaceView == null) {mSurfaceView = (SurfaceView) findViewById(R.id.surface_view);if (mSurfaceHolder == null) {mSurfaceHolder = mSurfaceView.getHolder();mSurfaceHolder.addCallback(this);}}}public void onClick(View view) {// 开始录制if (!mIsRecording) {mIsRecording = true;if (mHandler != null) {Message msg = new Message();msg.what = MSG_UPDATE_BUTTON_TEXT;msg.obj = getText(R.string.record_stop);mHandler.dispatchMessage(msg);startRecording();}} else { // 停止录制mIsRecording = false;if (mHandler != null) {Message msg = new Message();msg.what = MSG_UPDATE_BUTTON_TEXT;msg.obj = getText(R.string.record_start);mHandler.dispatchMessage(msg);stopRecording();}}}@Overridepublic void surfaceCreated(SurfaceHolder holder) {Log.d(TAG, "surfaceCreated");mCamera = openCamera();}@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {Log.d(TAG, "surfaceChanged");if (mCamera != null && mSurfaceHolder != null) {try {mCamera.stopPreview();} catch (Exception e) {e.printStackTrace();}Camera.Parameters parameters = mCamera.getParameters();mCamera.setParameters(parameters);try {mCamera.setPreviewDisplay(mSurfaceHolder);mCamera.startPreview();} catch (IOException e) {e.printStackTrace();}}}@Overridepublic void surfaceDestroyed(SurfaceHolder holder) {Log.d(TAG, "surfaceDestroyed");releaseCamera();}// 打开相机private Camera openCamera() {Camera camera;try {camera = Camera.open(0);} catch (Exception e) {e.printStackTrace();Log.e(TAG, "open camera failed!!");return null;}Log.d(TAG, "open camera success!!");return camera;}// 销毁相机private void releaseCamera() {if (mCamera != null) {mCamera.stopPreview();mCamera.release();mCamera = null;}}private void startRecording() {if (mCamera == null) {Log.e(TAG, "startRecording, mCamera is null");return;}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.AAC);mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);mMediaRecorder.setVideoEncodingBitRate(3 * 1024 * 1024);mMediaRecorder.setVideoFrameRate(30);mMediaRecorder.setVideoSize(1280, 960);String saveName = getOutputMediaFileName();if (saveName == null) {Log.e(TAG, "save media file error: " + saveName);return;}mMediaRecorder.setOutputFile(saveName);try {mMediaRecorder.prepare();mMediaRecorder.start();} catch (IOException e) {e.printStackTrace();}}private void stopRecording() {if (mMediaRecorder != null) {try {mMediaRecorder.stop();mMediaRecorder.release();} catch (Exception e) {e.printStackTrace();}mMediaRecorder = null;mCamera.lock();}mIsRecording = false;}private String getOutputMediaFileName() {String state = Environment.getExternalStorageState();// Check if external storage is mountedif (!Environment.MEDIA_MOUNTED.equals(state)) {Log.e(TAG, "External storage is not mounted!");return null;}File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM), "");// Create the storage directory if it does not existif (!mediaStorageDir.exists()) {if (!mediaStorageDir.mkdirs()) {Log.e(TAG, "Failed to create directory " + mediaStorageDir.getPath()+ " for pictures/video!");return null;}}// Create a media file name@SuppressLint("SimpleDateFormat") String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());String mediaFileName = mediaStorageDir.getPath() + File.separator +"VID_" + timeStamp + ".mp4";return mediaFileName;} } -
AndroidManifest.xml文件
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.example.record"><uses-permission android:name="android.permission.CAMERA" /><uses-permission android:name="android.permission.RECORD_AUDIO" /><uses-feature android:name="android.hardware.camera" /><uses-feature android:name="android.hardware.camera.autofocus" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /><applicationandroid:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:supportsRtl="true"android:theme="@style/AppTheme"><activity android:name=".MainActivity"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.DEFAULT" /><category android:name="android.intent.category.LAUNCHER" />intent-filter>activity>application>manifest> -
Android.mk文件
有时候需要将apk放置AOSP源码中编译,Android.mk文件如下:
LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS)LOCAL_SRC_FILES := $(call all-java-files-under, java)LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/resLOCAL_MANIFEST_FILE := AndroidManifest.xmlLOCAL_PACKAGE_NAME := Record ALL_DEFAULT_INSTALLED_MODULES += $(LOCAL_PACKAGE_NAME)#LOCAL_SDK_VERSION := currentLOCAL_CERTIFICATE := platform#LOCAL_PRIVILEGED_MODULE := trueinclude $(BUILD_PACKAGE)
四、注意事项
-
在使用 Camera 时,必须在 AndroidManifest.xml 文件中添加 CAMERA、存储等相关 权限。
-
在录像结束后,需要及时释放资源,避免占用过多的系统资源。
-
由于不同设备品牌的摄像头硬件和软件实现有所差异,因此在不同设备上的录像效果可能会有所不同。
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
