android实现录音功能demo

  • 主要功能实现
  • 视频演示
  • 录音相关代码
  • 下载链接

主要功能实现

主要实现录音功能,录音,停止录音,保存录音,然后可以查看录音列表,还用sqlite数据库实现了用户的注册登录功能。

视频演示

视频

录音相关代码

录音fragment,RecordingFragment

package example.com.recording.fragments;import android.content.DialogInterface;
import android.media.MediaRecorder;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi;
import android.support.v4.app.Fragment;
import android.support.v7.app.AlertDialog;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;import de.greenrobot.event.EventBus;
import example.com.recording.R;
import example.com.recording.bean.ListChangeEvent;
import example.com.recording.util.date.DateFormatUtil;/*** 录音的fragment*/public class RecordingFragment extends Fragment implements View.OnClickListener {// 开始录音private Button start;// 重置private Button reset;// 录音类private MediaRecorder mediaRecorder;// 以文件的形式保存
//    private File recordFile;private TextView titleTv;//总的分钟、秒的显示TextViewprivate TextView timeTv1, timeTv2;//总秒private int seconds;//总分钟private int minute;//执行周期性或定时任务类private ScheduledExecutorService service;//线程是否停止的判断private boolean isStart = false;//是否重置的判断重置了handler就不在接收消息private boolean isReset = false;//handler接收线程传过来的消息显示当前定时时间private Handler handler = new Handler() {@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);switch (msg.what) {case 1:setData();break;}}};//文件路径private String fileName;//获取sd根目录public static final String ROOT_FILE = Environment.getExternalStorageDirectory().getAbsolutePath();private String path;@Nullable@Overridepublic View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {View view = LayoutInflater.from(getActivity()).inflate(R.layout.fragment_recording, null);initView(view);Listener();titleTv.setText("录音");return view;}private void initView(View view) {titleTv = (TextView) view.findViewById(R.id.base_title_tv);start = (Button) view.findViewById(R.id.start);reset = (Button) view.findViewById(R.id.reset);reset.setEnabled(false);timeTv1 = (TextView) view.findViewById(R.id.time_tv1);timeTv2 = (TextView) view.findViewById(R.id.time_tv2);path = ROOT_FILE + "/" + getActivity().getPackageName() + "/record";}private void Listener() {start.setOnClickListener(this);reset.setOnClickListener(this);}@RequiresApi(api = Build.VERSION_CODES.N)@Overridepublic void onClick(View v) {int Id = v.getId();switch (Id) {case R.id.start:isReset = false;if (isStart) {isStart = false;pauseRecording();reset.setEnabled(true);pauseTime();start.setText("开始");} else {isStart = true;start.setText("暂停");reset.setEnabled(false);startRecording();start();}break;case R.id.reset:isStop = true;isReset = true;isStart = false;start.setText("开始");if (service != null) {resetTime();}stopRecord();break;}}private boolean isStop = true;//录音完成保存或删除文件private void recordOver(String s) {final File recordFile = new File(s);if (recordFile != null && recordFile.exists()) {final EditText et = new EditText(getActivity());et.setText(recordFile.getName().substring(0, recordFile.getName().length() - 4));new AlertDialog.Builder(getActivity()).setTitle("文件名").setView(et).setCancelable(false).setPositiveButton("确定", new DialogInterface.OnClickListener() {public void onClick(DialogInterface dialog, int which) {String s = et.getText().toString();//文件名为空就按源文件保存if (s.isEmpty()) {Toast.makeText(getActivity(), "文件名不能为空", Toast.LENGTH_SHORT).show();} else {recordFile.renameTo(new File(path + "/" + s + ".amr"));EventBus.getDefault().post(new ListChangeEvent());}}}).setNegativeButton("删除", new DialogInterface.OnClickListener() {public void onClick(DialogInterface dialog, int which) {recordFile.delete();}}).show();} else {Toast.makeText(getActivity(), "还未录制", Toast.LENGTH_SHORT).show();}}//暂停计时private void pauseTime() {service.shutdown();}//重置后的操作private void resetTime() {service.shutdown();service = null;seconds = 0;minute = 0;setText();}//设置时间数据private void setData() {if (!isReset) {if (seconds == 59) {seconds = 0;minute = minute + 1;if (minute == 59) {minute = 0;Toast.makeText(getActivity(), "已是最大数值", Toast.LENGTH_SHORT).show();start.setText("开始");isStart = false;service.shutdown();}} else {seconds = seconds + 1;}setText();}}//显示时间private void setText() {timeTv1.setText(getNum(minute));timeTv2.setText(getNum(seconds));}//数据转换成两位Stringprivate String getNum(int num) {return String.format("%02d", num);}//保存每次录制的路径private List<String> mList = new ArrayList<>();//开始录音private void startRecording() {if(isStop){isStop = false;mList.clear();}File file = new File(path);if (!file.exists()) {file.mkdirs();}fileName = path + "/" + getTime() + ".amr";mediaRecorder = new MediaRecorder();mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);// 选择amr格式mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.RAW_AMR);mediaRecorder.setOutputFile(fileName);mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);try {// 准备好开始录音mediaRecorder.prepare();mediaRecorder.start();} catch (IllegalStateException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}//暂停录音private void pauseRecording() {try {mediaRecorder.stop();mediaRecorder.release();//录制的文件路径添加到列表mList.add(fileName);} catch (Exception e) {Log.e("Exception", e.getMessage(), e);Toast.makeText(getActivity(), "录制异常", Toast.LENGTH_SHORT).show();}}// 完成录音private void stopRecord() {reset.setEnabled(false);// 最后合成的音频文件fileName = path + "/" + getTime() + ".amr";FileOutputStream fileOutputStream = null;try {fileOutputStream = new FileOutputStream(fileName);} catch (FileNotFoundException e) {e.printStackTrace();}FileInputStream fileInputStream = null;try {for (int i = 0; i < mList.size(); i++) {Log.e("stopRecord",mList.get(i));File file = new File(mList.get(i));// 把因为暂停所录出的多段录音进行读取fileInputStream = new FileInputStream(file);byte[] mByte = new byte[fileInputStream.available()];int length = mByte.length;// 第一个录音文件的前六位是不需要删除的if (i == 0) {while (fileInputStream.read(mByte) != -1) {fileOutputStream.write(mByte, 0, length);}}// 之后的文件,去掉前六位else {while (fileInputStream.read(mByte) != -1) {fileOutputStream.write(mByte, 6, length - 6);}}}recordOver(fileName);} catch (Exception e) {// 这里捕获流的IO异常,万一系统错误需要提示用户e.printStackTrace();Toast.makeText(getActivity(), "录音合成出错,请重试!", Toast.LENGTH_LONG).show();} finally {try {fileOutputStream.flush();fileInputStream.close();} catch (Exception e) {e.printStackTrace();}}// 不管合成是否成功、删除录音片段for (int i = 0; i < mList.size(); i++) {File file = new File(mList.get(i));if (file.exists()) {file.delete();}}}//获取当前时间作为文件名private String getTime() {return DateFormatUtil.getDateFormat(System.currentTimeMillis(), "yyyyMMddHHmmss");}//启动倒计时private void start() {service = Executors.newScheduledThreadPool(1);service.scheduleAtFixedRate(new Runnable() {@Overridepublic void run() {handler.sendEmptyMessage(1);}}, 1, 1, TimeUnit.SECONDS);}}

相关xml界面
fragment_recording

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center_horizontal"android:orientation="vertical"><includeandroid:id="@+id/title"layout="@layout/base_title" /><LinearLayoutandroid:layout_width="200dp"android:layout_height="200dp"android:layout_marginTop="20dp"android:gravity="center"android:background="@drawable/shape_oval"android:orientation="horizontal"><TextViewandroid:id="@+id/time_tv1"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1.0"android:gravity="center"android:text="00"android:textSize="35sp" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text=":"android:textSize="35sp" /><TextViewandroid:id="@+id/time_tv2"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1.0"android:gravity="center"android:text="00"android:textSize="35sp" /></LinearLayout><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center"android:orientation="horizontal"><Buttonandroid:id="@+id/reset"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_below="@+id/start"android:layout_centerHorizontal="true"android:layout_marginTop="20dp"android:text="@string/reset" /><Buttonandroid:id="@+id/start"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerHorizontal="true"android:layout_marginTop="20dp"android:text="@string/start" /></LinearLayout>
</LinearLayout>

shape_oval

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"android:shape="oval"><solid android:color="@color/base_orange"/></shape>

下载链接

demo下载链接

android实现录音功能demo相关推荐

  1. android微信网页视频播放器代码下载,android微信中的录音功能 demo

    微信中的录音功能 demo 资源下载此资源下载价格为3D币,请先登录 资源文件列表 weixin_Record/res/values-v11/styles.xml , 324 weixin_Recor ...

  2. Android实现录音功能实现实例(MediaRecorder)

    Android实现录音功能实现实例(MediaRecorder) - 腾讯云开发者社区-腾讯云 本文介绍了Android实现录音的实例代码(MediaRecorder),分享给大家,具体如下: And ...

  3. Android之录音功能

    Android之录音功能 1.需要权限 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE ...

  4. QT 5.4.1 for Android Ubuntu QtWebView Demo

    QT 5.4.1 for Android Ubuntu QtWebView Demo 2015-5-15 目录 一.说明: 二.参考文章: 三.QtWebView Demo在哪里? 四.Qt Crea ...

  5. Android 抽屉效果Demo

    2019独角兽企业重金招聘Python工程师标准>>> Android 抽屉效果Demo. 转载:http://www.adobex.com/android/source/detai ...

  6. android 微信 demo,android微信分享demo

    [实例简介] android微信分享demo 开发实例源代码 [实例截图] [核心代码] android微信分享demo └── android微信分享demo └── wxshare ├── And ...

  7. Android学习小Demo(10)ToDoList的改进版之ViewPager显示多个图片

    在TodoList增强版的增加界面上,为了显示图片,我是挖了两块地方,放了两个ImageButton,来显示图片,而且限制了最多只能放两张图片.当两个View都放置图片之后,我就会把"Gal ...

  8. Android学习小Demo(10)ToDoList的加强版

    前两天去超市逛东西,问老板娘这个东西多少钱,那个东西多少钱,但是一两分钟后就搞混了,当时就想,我不是写了一个todo的吗,可以再拍照放上去,这样就有对比啦! 于是兴冲冲地赶回家,把功能给实现了,虽然这 ...

  9. Android学习小Demo(9)一个To Do List的实现

    记得看过一篇文章,是说一个人临走之前,列下了想做的最后100件事情,然后拿着这张便签,一件一件地去实现.又想起乔布斯说,如果今天是你的最后一天,你会怎么过? 我有很多事情想做,想写很多的文章,但是时间 ...

最新文章

  1. bash脚本之for语句if语句以及各种测试语句(2)
  2. uPC1677射频信号放大芯片
  3. Linux下用arptables防arp攻击
  4. oracle怎么关闭约束,Oracle约束enable/disablenovalidate
  5. ie禁止html复制元素,JavaScript_禁止选中文字兼容IE、Chrome、FF等,复制代码 代码如下: $(el).attr('u - phpStudy...
  6. zTree树形菜单使用实例
  7. Sublime优美设置(待续)
  8. 贪心算法—区间调度 电影节(POJ 4151)
  9. JavaEE Tutorials (7) - 在会话bean中使用异步方法调用
  10. 微信终于良心一回,更新了语音识别功能可识别粤语,广东人有福了
  11. 可编译运行:调用ffmpeg接口,将RTSP流保存为MP4的C代码
  12. java滥用接口_接口滥用问题
  13. 找了好久的数据库mysql中文乱码问题终于解决
  14. PAT简介和2019年秋季浙大PAT考试报名流程
  15. Facebook前身 哈佛大学“选美“网站核心算法 -- ELO等级分制度(附源码)
  16. 艺点动画-跟随原理讲解
  17. 关于NdFeB样品的测量阶段总结
  18. 字节跳动测试岗位面试题
  19. SQL 根据一个字段的一部分分组查询
  20. 【附源码】计算机毕业设计JAVA疫苗药品批量扫码识别追溯系统

热门文章

  1. TF卡/SD卡/U盘容量“变小”的问题
  2. 韩国两大火暴美女迪厅拼舞 精彩视频
  3. WebService为什么不如RESTful API流行
  4. am超外差收音机matlab,超外差式AM/FM收音机的调试
  5. 全国大学生电子设计竞赛
  6. 2021年美国大学生数学建模竞赛A题思路分析
  7. 腾讯云增值税发票OCR
  8. 电商平台-商品价格的设计与架构
  9. 北京高校大学期末试题试卷题库
  10. C语言 杨氏矩阵,二维数组查找数字。