思路:定义一个SurfaceView用来显示预览,在SurfaceHolder的回调中用Camera对象启动预览。然后调用MediaRecorder来录像。仅仅是实现了简单的录像開始和停止功能。顶部能显示显示录像的时间,还有待完好。

代码例如以下:

在AndroidManifest.xml加入以下的权限:

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<!-- 硬件支持 -->
<uses-feature android:name="android.hardware.camera"/>
<uses-feature android:name="android.hardware.camera.autofocus"/>

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" > <SurfaceView
android:id="@+id/camera_preview"
android:layout_width="match_parent"
android:layout_height="match_parent" /> <LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:orientation="horizontal"> <TextView
android:id="@+id/timestamp_minute_prefix"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#7F00FF"
android:textSize="30sp"
android:text="0"/> <TextView
android:id="@+id/timestamp_minute_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#7F00FF"
android:textSize="30sp"
android:text="0"/> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#7F00FF"
android:textSize="30sp"
android:text=":"/> <TextView
android:id="@+id/timestamp_second_prefix"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#7F00FF"
android:textSize="30sp"
android:text="0"/> <TextView
android:id="@+id/timestamp_second_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#7F00FF"
android:textSize="30sp"
android:text="0"/>
</LinearLayout> <ImageButton
android:id="@+id/record_shutter"
android:layout_width="64dp"
android:layout_height="64dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="15dp"
android:background="@android:color/transparent"
android:scaleType="centerCrop"
android:src="@drawable/recording_shutter" /> </RelativeLayout>

MainActivity.java

package com.jackie.videorecorder;

import java.io.File;

import android.app.Activity;
import android.hardware.Camera;
import android.hardware.Camera.Parameters;
import android.hardware.Camera.Size;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageButton;
import android.widget.TextView; import org.w3c.dom.Text; public class MainActivity extends Activity implements OnClickListener {
private SurfaceView mCameraPreview;
private SurfaceHolder mSurfaceHolder;
private ImageButton mShutter;
private TextView mMinutePrefix;
private TextView mMinuteText;
private TextView mSecondPrefix;
private TextView mSecondText; private Camera mCamera;
private MediaRecorder mRecorder; private final static int CAMERA_ID = 0; private boolean mIsRecording = false;
private boolean mIsSufaceCreated = false; private static final String TAG = "Jackie"; private Handler mHandler = new Handler(); @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); mCameraPreview = (SurfaceView) findViewById(R.id.camera_preview);
mMinutePrefix = (TextView) findViewById(R.id.timestamp_minute_prefix);
mMinuteText = (TextView) findViewById(R.id.timestamp_minute_text);
mSecondPrefix = (TextView) findViewById(R.id.timestamp_second_prefix);
mSecondText = (TextView) findViewById(R.id.timestamp_second_text); mSurfaceHolder = mCameraPreview.getHolder();
mSurfaceHolder.addCallback(mSurfaceCallback);
mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); mShutter = (ImageButton) findViewById(R.id.record_shutter);
mShutter.setOnClickListener(this);
} @Override
protected void onPause() {
super.onPause();
if (mIsRecording) {
stopRecording();
}
stopPreview();
} private SurfaceHolder.Callback mSurfaceCallback = new SurfaceHolder.Callback() { @Override
public void surfaceDestroyed(SurfaceHolder holder) {
mIsSufaceCreated = false;
} @Override
public void surfaceCreated(SurfaceHolder holder) {
mIsSufaceCreated = true;
} @Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
startPreview();
}
}; //启动预览
private void startPreview() {
//保证仅仅有一个Camera对象
if (mCamera != null || !mIsSufaceCreated) {
Log.d(TAG, "startPreview will return");
return;
} mCamera = Camera.open(CAMERA_ID); Parameters parameters = mCamera.getParameters();
Size size = getBestPreviewSize(CameraUtils.PREVIEW_WIDTH, CameraUtils.PREVIEW_HEIGHT, parameters);
if (size != null) {
parameters.setPreviewSize(size.width, size.height);
} parameters.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
parameters.setPreviewFrameRate(20); //设置相机预览方向
mCamera.setDisplayOrientation(90); mCamera.setParameters(parameters); try {
mCamera.setPreviewDisplay(mSurfaceHolder);
// mCamera.setPreviewCallback(mPreviewCallback);
} catch (Exception e) {
Log.d(TAG, e.getMessage());
} mCamera.startPreview();
} private void stopPreview() {
//释放Camera对象
if (mCamera != null) {
try {
mCamera.setPreviewDisplay(null);
} catch (Exception e) {
Log.e(TAG, e.getMessage());
} mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
} private Camera.Size getBestPreviewSize(int width, int height, Camera.Parameters parameters) {
Camera.Size result = null; for (Camera.Size size : parameters.getSupportedPreviewSizes()) {
if (size.width <= width && size.height <= height) {
if (result == null) {
result = size;
} else {
int resultArea = result.width * result.height;
int newArea = size.width * size.height; if (newArea > resultArea) {
result = size;
}
}
}
} return result;
} @Override
public void onClick(View v) {
if (mIsRecording) {
stopRecording();
} else {
initMediaRecorder();
startRecording(); //開始录像后,每隔1s去更新录像的时间戳
mHandler.postDelayed(mTimestampRunnable, 1000);
}
} private void initMediaRecorder() {
mRecorder = new MediaRecorder();//实例化
mCamera.unlock();
//给Recorder设置Camera对象,保证录像跟预览的方向保持一致
mRecorder.setCamera(mCamera);
mRecorder.setOrientationHint(90); //改变保存后的视频文件播放时是否横屏(不加这句。视频文件播放的时候角度是反的)
mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); // 设置从麦克风採集声音
mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); // 设置从摄像头採集图像
mRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); // 设置视频的输出格式 为MP4
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT); // 设置音频的编码格式
mRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); // 设置视频的编码格式
mRecorder.setVideoSize(176, 144); // 设置视频大小
mRecorder.setVideoFrameRate(20); // 设置帧率
// mRecorder.setMaxDuration(10000); //设置最大录像时间为10s
mRecorder.setPreviewDisplay(mSurfaceHolder.getSurface()); //设置视频存储路径
File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES) + File.separator + "VideoRecorder");
if (!file.exists()) {
//多级目录的创建
file.mkdirs();
}
mRecorder.setOutputFile(file.getPath() + File.separator + "VID_" + System.currentTimeMillis() + ".mp4");
} private void startRecording() {
if (mRecorder != null) {
try {
mRecorder.prepare();
mRecorder.start();
} catch (Exception e) {
mIsRecording = false;
Log.e(TAG, e.getMessage());
}
} mShutter.setImageDrawable(getResources().getDrawable(R.drawable.recording_shutter_hl));
mIsRecording = true;
} private void stopRecording() {
if (mCamera != null) {
mCamera.lock();
} if (mRecorder != null) {
mRecorder.stop();
mRecorder.release();
mRecorder = null;
} mShutter.setImageDrawable(getResources().getDrawable(R.drawable.recording_shutter));
mIsRecording = false; mHandler.removeCallbacks(mTimestampRunnable); //将录像时间还原
mMinutePrefix.setVisibility(View.VISIBLE);
mMinuteText.setText("0");
mSecondPrefix.setVisibility(View.VISIBLE);
mSecondText.setText("0"); //重新启动预览
startPreview();
} private Runnable mTimestampRunnable = new Runnable() {
@Override
public void run() {
updateTimestamp();
mHandler.postDelayed(this, 1000);
}
}; private void updateTimestamp() {
int second = Integer.parseInt(mSecondText.getText().toString());
int minute = Integer.parseInt(mMinuteText.getText().toString());
second++;
Log.d(TAG, "second: " + second); if (second < 10) {
mSecondText.setText(String.valueOf(second));
} else if (second >= 10 && second < 60) {
mSecondPrefix.setVisibility(View.GONE);
mSecondText.setText(String.valueOf(second));
} else if (second >= 60) {
mSecondPrefix.setVisibility(View.VISIBLE);
mSecondText.setText("0"); minute++;
mMinuteText.setText(String.valueOf(minute));
} else if (minute >= 60) {
mMinutePrefix.setVisibility(View.GONE);
}
}
}

效果例如以下:

用MediaRecorder实现简单的录像功能的更多相关文章

  1. Android 开发 MediaRecorder视频录制入门

    前言 MediaRecorder是Android SDK提供用于录制音视频,关于音频的录制在我另一篇博客里已经介绍.传送门: https://www.cnblogs.com/guanxinjing/p ...

  2. Android 开发 Camera类的拍照与录像

    前言 在开发Android应用的时候,如果需要调用摄像头拍照或者录像,除了通过Intent调用系统现有相机应用进行拍照录像之外,还可以通过直接调用Camera硬件去去获取摄像头进行拍照录像的操作.本篇 ...

  3. Android简单的利用MediaRecorder进行录音的实例代码

    MainActivity.java package com.example.soundrecord_demo; import java.io.IOException; import android.m ...

  4. Android使用MediaRecorder和Camera实现视频录制及播放功能整理

    转载请注明出处:http://blog.csdn.net/woshizisezise/article/details/51878566 这两天产品经理向我丢来一个新需求,需要在项目里添加一个视频录制的 ...

  5. Android音视频之MediaRecorder音视频录制

    前言: 公司产品有很多地方都需要上传音频视频,今天抽空总结一下音频视频的录制.学习的主角是MediaRecorder类. MediaRecorder类介绍: MediaRecorder类是Androi ...

  6. 通过Android录音进行简单音频分析

    Android录音有MediaRecorder和AudioRecord两种方式,前者使用方便,可以直接生成录音文件,但是录音格式为aac和amr等等,都经过压缩处理,不方便进行音频分析. 而用Audi ...

  7. Android 学习笔记之如何实现简单相机功能

    PS:看来算法和数据结构还是非常有用的,以后每天都练习两道算法题目...这次忘了对代码进行折叠了..导致篇幅过长... 学习内容: 1.Android如何实现相机功能... 2.如何实现音频的录制.. ...

  8. Android多媒体录制--MediaRecorder视频录制

    Android使用MediaRecorder类进行视频的录制. 需要注意,使用MediaRecorder 录音录像 的设置代码步骤一定要按照API指定的顺序来设置,否则报错 步骤为: 1.设置视频源, ...

  9. MediaRecorder类介绍

    audiocallbackvideojavadescriptorencoding 目录(?)[+] 找到个MediaRecorder类介绍和大家分享一下. Mediarecorder类在官网的介绍和在 ...

随机推荐

  1. 【DNN引用包】

    <%@ Register TagPrefix="dnn" TagName="address" Src="~/controls/address.a ...

  2. Edge浏览器开发人员工具

    UserAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Ch ...

  3. The IDL compiler

    The IDL compiler or bindings generator transcompiles Web IDL to C++ code, specifically bindings betw ...

  4. BZOJ 3277/3473 广义后缀自动机

    说实话没啥难的. 建一棵广义后缀自动机,暴力自底向上更新即可. 时间复杂度非常玄学,但据说是可以过的. 要注意每个串中相同的子串的贡献是都要加进去的,开始因为这个被坑了好久 QAQ Code: #in ...

  5. [BJWC2011]禁忌 AC 自动机 概率与期望

    #include<cstdio> #include<algorithm> #include<cstring> #include<string> #inc ...

  6. [NOIP2016普及组]魔法阵

    题目:洛谷P2119.Vijos P2012.codevs5624. 题目大意:有n件物品,每件物品有个魔法值.要求组成魔法阵(Xa,Xb,Xc,Xd),该魔法阵要满足Xa<Xb<Xc&l ...

  7. zabbix4.0 使用nginx前端安装

    注:环境需求:centos7 1.安装阿里云yum源: rpm -ivh https://mirrors.aliyun.com/zabbix/zabbix/4.1/rhel/7/x86_64/zabb ...

  8. 删除小脚本 srm

    提示:只能删除当前路径下的目录或文件 #!/bin/bash #将测试好的脚本,拷贝到 $PATH 能够搜索到目录下.并且改名 例如: /usr/local/bin cp /test/srm.sh / ...

  9. HDU 4939 Stupid Tower Defense 简单DP

    题意: 地图为长为n个单位长度的直线,每通过一个单位长度需要t秒. 有3种塔,红塔可以在当前格子每秒造成x点伤害,绿塔可以在之后格子造成y点伤害,蓝塔可以使通过单位长度的时间增加z秒. 让你安排塔的排 ...

  10. Unity 设置窗体透明

    设置窗口透明.窗口置顶.鼠标穿透    方法一. 缺点:边缘不平滑,有毛边 参考博客: 1.https://alastaira.wordpress.com/2015/06/15/creating-wi ...