Android实现边录边播(MediaRecorder和AudioRecord)
Android可以通过MediaRecorder和AudioRecord这两个工具来实现录音,MediaRecorder直接把麦克风的数据存到文件,并且能够直接进行编码(如AMR,MP3等),而AudioRecord则是读取麦克风的音频流。本文使用AudioRecord读取音频流,使用AudioTrack播放音频流,通过“边读边播放”以及增大音量的方式来实现一个简单的助听器程序。
PS:由于目前的Android模拟器还不支持AudioRecord,因此本程序需要编译之后放到真机运行。
Activity_layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="fill_parent"android:layout_height="fill_parent"android:orientation="vertical" ><Buttonandroid:id="@+id/bt_yinpinhuilu_testing_exit"android:layout_width="fill_parent"android:layout_height="wrap_content"android:text="Close"/></LinearLayout>
MainActivity:
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;import android.Manifest;
import android.content.pm.PackageManager;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioRecord;
import android.media.AudioTrack;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;import java.util.LinkedList;public class MainActivity extends AppCompatActivity implements View.OnClickListener {private static final String TAG = "ktv";/*** 按钮*/private Button bt_exit;/*** AudioRecord 写入缓冲区大小*/protected int m_in_buf_size;/*** 录制音频对象*/private AudioRecord m_in_rec;/*** 录入的字节数组*/private byte[] m_in_bytes;/*** 存放录入字节数组的大小*/private LinkedList<byte[]> m_in_q;/*** AudioTrack 播放缓冲大小*/private int m_out_buf_size;/*** 播放音频对象*/private AudioTrack m_out_trk;/*** 播放的字节数组*/private byte[] m_out_bytes;/*** 录制音频线程*/private Thread record;/*** 播放音频线程*/private Thread play;/*** 让线程停止的标志*/private boolean flag = true;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);this.setTitle("音频回路");requestAllPower();Log.d("dfdfd", "333333333333");init();record = new Thread(new recordSound());play = new Thread(new playRecord());// 启动录制线程record.start();// 启动播放线程play.start();}private void init() {bt_exit = findViewById(R.id.bt_yinpinhuilu_testing_exit);Log.i(TAG, "bt_exit====" + bt_exit);bt_exit.setOnClickListener(this);// AudioRecord 得到录制最小缓冲区的大小m_in_buf_size = AudioRecord.getMinBufferSize(8000,AudioFormat.CHANNEL_CONFIGURATION_MONO,AudioFormat.ENCODING_PCM_16BIT);// 实例化播放音频对象m_in_rec = new AudioRecord(MediaRecorder.AudioSource.MIC, 8000,AudioFormat.CHANNEL_CONFIGURATION_MONO,AudioFormat.ENCODING_PCM_16BIT, m_in_buf_size);// 实例化一个字节数组,长度为最小缓冲区的长度m_in_bytes = new byte[m_in_buf_size];// 实例化一个链表,用来存放字节组数m_in_q = new LinkedList<byte[]>();// AudioTrack 得到播放最小缓冲区的大小m_out_buf_size = AudioTrack.getMinBufferSize(8000,AudioFormat.CHANNEL_CONFIGURATION_MONO,AudioFormat.ENCODING_PCM_16BIT);// 实例化播放音频对象m_out_trk = new AudioTrack(AudioManager.STREAM_MUSIC, 8000,AudioFormat.CHANNEL_CONFIGURATION_MONO,AudioFormat.ENCODING_PCM_16BIT, m_out_buf_size,AudioTrack.MODE_STREAM);// 实例化一个长度为播放最小缓冲大小的字节数组m_out_bytes = new byte[m_out_buf_size];}public void onClick(View v) {// TODO Auto-generated method stubswitch (v.getId()) {case R.id.bt_yinpinhuilu_testing_exit:flag = false;m_in_rec.stop();m_in_rec = null;m_out_trk.stop();m_out_trk = null;this.finish();}}/*** 录音线程*/class recordSound implements Runnable {@Overridepublic void run() {Log.i(TAG, "........recordSound run()......");byte[] bytes_pkg;// 开始录音m_in_rec.startRecording();while (flag) {m_in_rec.read(m_in_bytes, 0, m_in_buf_size);bytes_pkg = m_in_bytes.clone();Log.i(TAG, "........recordSound bytes_pkg==" + bytes_pkg.length);if (m_in_q.size() >= 2) {m_in_q.removeFirst();}m_in_q.add(bytes_pkg);}}}/*** 播放线程*/class playRecord implements Runnable {@Overridepublic void run() {// TODO Auto-generated method stubLog.i(TAG, "........playRecord run()......");byte[] bytes_pkg = null;// 开始播放m_out_trk.play();while (flag) {try {m_out_bytes = m_in_q.getFirst();bytes_pkg = m_out_bytes.clone();m_out_trk.write(bytes_pkg, 0, bytes_pkg.length);} catch (Exception e) {e.printStackTrace();}}}}/*** 录音哦动态权限*/public void requestAllPower() {if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {if (ActivityCompat.shouldShowRequestPermissionRationale(this,Manifest.permission.RECORD_AUDIO)) {} else {ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.RECORD_AUDIO,Manifest.permission.READ_EXTERNAL_STORAGE}, 1);}}}@Overridepublic void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {super.onRequestPermissionsResult(requestCode, permissions, grantResults);if (requestCode == 1) {for (int i = 0; i < permissions.length; i++) {Toast.makeText(this, "" + "权限" + permissions[i] + "申请成功", Toast.LENGTH_SHORT).show();}}}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.test.speex"><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.RECORD_AUDIO" /><applicationandroid:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"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.LAUNCHER" /></intent-filter></activity></application></manifest>
Android实现边录边播(MediaRecorder和AudioRecord)相关推荐
- android 录音原始文件_Android 录音详解(一)—— MediaRecorder、AudioRecord、生成wav格式、边录边播...
Android 录音详解(一)-- MediaRecorder.AudioRecord.生成wav格式.边录边播 越来越多的 APP 都用到了手机的录音功能,比如搜索.聊天.输入.K歌等... 本系列 ...
- Android app实现录播(边录边播)功能
Android 原生系统中有播放和录音功能,也提供了相应的api, MediaRecorder和AudioRecord这两个api可以实现录音的功能,他们的区别是:MediaRecorder直接把麦克 ...
- Android实现录音功能实现实例(MediaRecorder)
Android实现录音功能实现实例(MediaRecorder) - 腾讯云开发者社区-腾讯云 本文介绍了Android实现录音的实例代码(MediaRecorder),分享给大家,具体如下: And ...
- Android录制音频方式AudioRecorder和MediaRecorder
AudioRecorder和MediaRecorder AudioRecord和MediaRecorder两种都可以录制音频,MediaRecorder已实现大量的封装,操作起来更加简单,而Audio ...
- android 屏幕录制方案,ShareREC for Android全系统录屏原理解析
本文是Mob开发者平台技术副总监余勋杰基于MediaProjection实现Android全系统录屏功能的原理解析,包括了结合MediaRecorder和MediaCodec两套方案. 文 / 余勋杰 ...
- Android 调用系统api录音的两种方式(MediaRecorder、AudioRecord)
废话 权限.权限.权限,必须要先获取了录音权限,其他的事情晚点再说. 另外,新版本的Android 10系统会对录音有调整,引入了一个录音焦点的概念,也就是说以前的麦克风只能一个APP使用,必须要等它 ...
- Android 视频图片 轮播,详解android 视频图片混合轮播实现
循环添加视频view 图片view for (int i = 0 ;i if (beansarraylist.get(i).gettype()==1){ videoplayer = new nice ...
- android 3d布局轮播,android 图片/视频混合轮播控件banner
android 图片/视频混合轮播控件banner 在youth5201314的图片轮播控件做的修改 原作者github地址:https://github.com/youth5201314/banne ...
- android设计轮播功能按钮,Android TV HorizontalScrollView 图片轮播 遥控器上下按键的处理...
当前位置:我的异常网» Android » Android TV HorizontalScrollView 图片轮播 遥控器 Android TV HorizontalScrollView 图片轮播 ...
最新文章
- 强化学习、联邦学习、图神经网络,飞桨全新工具组件详解
- 一张图解析如何让img垂直居中对齐
- C# Task 循环任务_C# Task.Run调用外部参数
- IDEA新项目代码上传到gitlab远程仓库
- oracle 同步索引,oracle全文索引之同步和优化索引做了什么
- IntelliJ IDEA2017创建web工程并实现远程部署tomcat
- Swift - 属性观察者(willSet与didSet)
- linux运行bak,linux 备份学习
- 阿里云ECS云服务器快照
- Neutron的Router简介
- java判断字符串是否是中文_Java检查字符串是否包含中文字符
- javascript汉字转拼音代码
- 虚拟主机,VPS,云主机之间的区别?
- 求:生意参谋 data 破解,最好是用php
- 做程序界中的死神,提升灵力上限
- 任天堂3D掌上游戏机3DS正式发布
- 解决手机端中文输入法中keyup不灵便的方法
- DataBinding快速入门(还在用findViewById?)
- cf 1168 C. And Reachability
- 福布斯评出十大热门创业公司