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)相关推荐

  1. android 录音原始文件_Android 录音详解(一)—— MediaRecorder、AudioRecord、生成wav格式、边录边播...

    Android 录音详解(一)-- MediaRecorder.AudioRecord.生成wav格式.边录边播 越来越多的 APP 都用到了手机的录音功能,比如搜索.聊天.输入.K歌等... 本系列 ...

  2. Android app实现录播(边录边播)功能

    Android 原生系统中有播放和录音功能,也提供了相应的api, MediaRecorder和AudioRecord这两个api可以实现录音的功能,他们的区别是:MediaRecorder直接把麦克 ...

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

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

  4. Android录制音频方式AudioRecorder和MediaRecorder

    AudioRecorder和MediaRecorder AudioRecord和MediaRecorder两种都可以录制音频,MediaRecorder已实现大量的封装,操作起来更加简单,而Audio ...

  5. android 屏幕录制方案,ShareREC for Android全系统录屏原理解析

    本文是Mob开发者平台技术副总监余勋杰基于MediaProjection实现Android全系统录屏功能的原理解析,包括了结合MediaRecorder和MediaCodec两套方案. 文 / 余勋杰 ...

  6. Android 调用系统api录音的两种方式(MediaRecorder、AudioRecord)

    废话 权限.权限.权限,必须要先获取了录音权限,其他的事情晚点再说. 另外,新版本的Android 10系统会对录音有调整,引入了一个录音焦点的概念,也就是说以前的麦克风只能一个APP使用,必须要等它 ...

  7. Android 视频图片 轮播,详解android 视频图片混合轮播实现

    循环添加视频view  图片view for (int i = 0 ;i if (beansarraylist.get(i).gettype()==1){ videoplayer = new nice ...

  8. android 3d布局轮播,android 图片/视频混合轮播控件banner

    android 图片/视频混合轮播控件banner 在youth5201314的图片轮播控件做的修改 原作者github地址:https://github.com/youth5201314/banne ...

  9. android设计轮播功能按钮,Android TV HorizontalScrollView 图片轮播 遥控器上下按键的处理...

    当前位置:我的异常网» Android » Android TV HorizontalScrollView 图片轮播 遥控器 Android TV HorizontalScrollView 图片轮播 ...

最新文章

  1. 强化学习、联邦学习、图神经网络,飞桨全新工具组件详解
  2. 一张图解析如何让img垂直居中对齐
  3. C# Task 循环任务_C# Task.Run调用外部参数
  4. IDEA新项目代码上传到gitlab远程仓库
  5. oracle 同步索引,oracle全文索引之同步和优化索引做了什么
  6. IntelliJ IDEA2017创建web工程并实现远程部署tomcat
  7. Swift - 属性观察者(willSet与didSet)
  8. linux运行bak,linux 备份学习
  9. 阿里云ECS云服务器快照
  10. Neutron的Router简介
  11. java判断字符串是否是中文_Java检查字符串是否包含中文字符
  12. javascript汉字转拼音代码
  13. 虚拟主机,VPS,云主机之间的区别?
  14. 求:生意参谋 data 破解,最好是用php
  15. 做程序界中的死神,提升灵力上限
  16. 任天堂3D掌上游戏机3DS正式发布
  17. 解决手机端中文输入法中keyup不灵便的方法
  18. DataBinding快速入门(还在用findViewById?)
  19. cf 1168 C. And Reachability
  20. 福布斯评出十大热门创业公司

热门文章

  1. Redis的数据过期清除策略 与 内存淘汰策略
  2. 【Go 学习笔记】5 - Go 函数
  3. Spotify for Mac(流行音乐播放器)
  4. 【Docker】 Ubuntu 18.04 LTS 一键安装docker并优化配置
  5. 基于LVDS电平标准的Cameralink传输()
  6. [附源码]Java计算机毕业设计SSM高校心理咨询管理系统
  7. kdj超卖_KDJ指标的超买与超卖
  8. kdj超卖_kdj超卖是什么意思,kdi超卖的部分使用技巧
  9. 空气质量监测系统的组成和应用
  10. 过一点做两个点确定的直线的垂线,计算垂足坐标