录音

MediaRecoder

Android有一个内置的麦克风,通过它可以捕获音频和存储,或在手机进行播放。

有很多方法可以做到这一点,但最常见的方法是通 过MediaRecorder类。

MediaRecoder常用方法

方法名

描述

setAudioSource()

指定声音源

setOutputFormat()

该方法规定了音频格式中的音频将被存储

setAudioEncoder()

该方法指定要使用的音频编码器

setOutputFile()

该方法配置文件路径到其中的记录的音频将被存储

stop()

该方法停止记录处理

release()

当需要在记录器实例这种方法应被调用

 

 

大致流程:

  • 长按事件:进行录音工作  初始化录音、设置参数、创建临时文件夹保存录音文件,将mic(麦克风录制)好的音频放到之前创建的临时文件中
  • touch抬手事件:录音自动播放(之前录制好的音频) 播放完毕停止、释放、删除资源
  • 单独点击 不起作用 添加标识符来控制

效果:

\"\"

布局文件:

<?  version=\"1.0\" encoding=\"utf-8\"?>
<RelativeLayout  ns:android=\"http://schemas.android.com/apk/res/android\"
     ns:app=\"http://schemas.android.com/apk/res-auto\"
     ns:tools=\"http://schemas.android.com/tools\"
    android:layout_width=\"match_parent\"
    android:layout_height=\"match_parent\"
    tools:context=\".MainActivity\">

    <Button
        android:id=\"@+id/id_btn\"
        android:layout_width=\"match_parent\"
        android:layout_height=\"wrap_content\"
        android:text=\"点击录音\"
        android:layout_alignParentBottom=\"true\" />

</RelativeLayout>

 清单文件: 添加权限

    <uses-permission android:name=\"android.permission.RECORD_AUDIO\" />

java代码 注意两个类 录音和播放类  注意:android 6.0 要动态申请权限 

//长按下按钮,开始录制(文本会变成\"请大声说话\")
//松开按钮,停止录制(文本复原),播放刚刚录制的声音
public class MainActivity extends AppCompatActivity {

    private Button mRecordBtn;
    private MediaRecorder mRecord;//录音
    private MediaP  mP ;//播放声音
    private File voiceFile;
    private int REQ_CODE = 1001;
    private volatile boolean flag = false; //权限标识符

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mRecordBtn = findViewById(R.id.id_btn);
        initEvents();
    }

    private void initEvents() {
        //长按按键的监听事件
        mRecordBtn.setOnLongClickListener(new View.OnLongClickListener() {
            @RequiresApi(api = Build.VERSION_CODES.O)
            @Override
            public boolean onLongClick(View v) {
                if (Build.VERSION.SDK_INT >= 23)
                    requestPermission();
                else {
                    flag = true;
                }
                //有权限才能操作
                if (flag) {
                    try {
                        //创建录音对象
                        mRecord = new MediaRecorder();
                        //设置声音来源  MIC 系统麦克风
                        mRecord.setAudioSource(MediaRecorder.AudioSource.MIC);
                        //设置声音格式  MPEG_4 音频、视频的标准格式
                        mRecord.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
                        //设置声音的编码格式
                        mRecord.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
                        //准备临时文件用于承载录制的声音
                        voiceFile = File.createTempFile(\"myvoice\", \"MP3\");
                        //将录制好的声音输出到创建好的临时文件中
                        mRecord.setOutputFile(voiceFile.getAbsoluteFile());

                        //准备录音
                        mRecord.prepare();
                        //开始录制
                        mRecord.start();
                        //更改文本
                        mRecordBtn.setText(\"录音中...\");

                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                return false;
            }

        });

        //手向上抬起的按键
        mRecordBtn.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(final View v, MotionEvent event) {
                if (flag) {
                    if (event.getAction() == MotionEvent.ACTION_UP) {
                        //停止录制
                        mRecord.stop();
                        //释放资源
                        mRecord.release();
                        //更改文本
                        mRecordBtn.setText(\"点击录音\");

                        try {
                            //播放录音
                            mP  = new MediaP ();
                            //设置播放源
                            mP .setDataSource(voiceFile.getAbsolutePath());
                            //准备
                            mP .prepare();
                            //开始
                            mP .start();
                            //播放结束后的监听
                            mP .setOnCompletionListener(new MediaP .OnCompletionListener() {
                                @Override
                                public void onCompletion(MediaP  mp) {
                                    mp.stop();
                                    mp.release();
                                    //删掉录音的文件
                                    voiceFile.delete();
                                    //重置
                                    flag = false;
                                }

                            });


                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }

                return false;
            }
        });
    }

    /**
     * android 6.0之后动态申请权限
     */
    private void requestPermission() {
        //如果权限没有被申请
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.RECORD_AUDIO}, REQ_CODE);
        } else {
            //如果已经申请了
            flag = true;
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == REQ_CODE) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                //权限申请成功
                flag = true;
            } else {
                //权限申请失败
                Toast.makeText(this, \"需要打开录音权限\", Toast.LENGTH_SHORT).show();
            }
        }
    }
}

简单的语音聊天案例:

长按发送语音

将语音保存起来,点击对话框播放语音

\"\"

布局文件省略了

注意要在清单文件中添加录音权限

    <uses-permission android:name=\"android.permission.RECORD_AUDIO\" />

Msg.java 消息封装类

package com.demo.voicerecorddemo;


import java.io.File;

public class Msg {
    //内容、涉及到 语音、发送/接受的标志
    private String txt;
    private File f;
    private int flag;   //1:本人   -1:对方

    public Msg(String txt, File f, int flag) {
        this.txt = txt;
        this.f = f;
        this.flag = flag;
    }

    public String getTxt() {
        return txt;
    }

    public void setTxt(String txt) {
        this.txt = txt;
    }

    public File getF() {
        return f;
    }

    public void setF(File f) {
        this.f = f;
    }

    public int getFlag() {
        return flag;
    }

    public void setFlag(int flag) {
        this.flag = flag;
    }
}

适配器类 ChattingAdapter.java

根据不同的标识来显示不同的布局

//适配器:处理聊天记录样式
public class ChattingAdapter extends  Adapter {
    private List<Msg> data;
    private Context ctx;

    public ChattingAdapter(List<Msg> data,Context ctx) {
        this.data = data;
        this.ctx = ctx;
    }

    @Override
    public int getCount() {
        return data.size();
    }

    @Override
    public   getItem(int i) {
        return null;
    }

    @Override
    public long getItemId(int i) {
        return 0;
    }

    @Override
    public View getView(int i, View view, ViewGroup viewGroup) {
        Msg g = data.get(i);
//        if(view == null){ }
            if(g.getFlag() == 1) {
                view = LayoutInflater.from(ctx).inflate(R.layout.to_msg,null);
            }else{
                view = LayoutInflater.from(ctx).inflate(R.layout.from_msg,null);
            }

        TextView msg = (TextView) view.findViewById(R.id.msg);
        msg.setText(g.getTxt());
        return view;
    }
}

注意聊天类: ChattingActivity.java

声音的录制 与播放 存储逻辑 和权限申请

public class ChattingActivity extends AppCompatActivity {

    private Button voiceBtn;
    private ListView msgList;
    private ChattingAdapter adapter;
    private List<Msg> datas = new ArrayList<>();
    private MediaRecorder recorder;
    private List<File> voices = new ArrayList<>();
    private int REQ_CODE = 1001;
    private volatile boolean flag = false; //权限标识符

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_chatting);
        initView();
    }

    private void initView() {
        voiceBtn = findViewById(R.id.vice_btn);
        msgList = findViewById(R.id.msg_list);
        adapter = new ChattingAdapter(datas, this);
        msgList.setAdapter(adapter);

        //长按按钮,开始录音,松开按钮,录音结束
        //发送语音的效果
        //未来在点击了聊天气泡后才播放对应的语音
        voiceBtn.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View view) {
                //android 6.0 之后才需要动态申请权限
                if (Build.VERSION.SDK_INT >= 23)
                    requestPermission();
                else {
                    flag = true;
                }
                if (flag) {
                    voiceBtn.setText(\"请开始说话...\");
                    //录音
                    //一系列特性的设置
                    try {
                        recorder = new MediaRecorder();
                        recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
                        recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
                        recorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
                        //指定语音文件
                        File tempFile = File.createTempFile(\"temp\", \"mp3\");
                        recorder.setOutputFile(tempFile.getAbsolutePath());

                        //保存语音文件
                        voices.add(tempFile);

                        //开始录音
                        recorder.prepare();
                        recorder.start();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                return false;
            }
        });
        voiceBtn.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                if (flag) {//如果没授予权限
                    if (motionEvent.getAction() == MotionEvent.ACTION_UP) {
                        voiceBtn.setText(\"按住说话\");
                        //停止录音
                        recorder.stop();
                        recorder.release();
                        flag = false;
                        //更新聊天界面
                        datas.add(new Msg(\"           \", voices.get(voices.size() - 1), 1));
                        datas.add(new Msg(\"哈哈哈哈\", null, -1));        //伪造一条跟随着的收到的信息
                        adapter.notifyDataSetChanged();
                        //让listView一直滚动到底部
                        msgList.setTran Mode(ListView.TRAN _MODE_ALWAYS_SCROLL);
                    }
                } else {
                    if (ContextCompat.checkSelfPermission(ChattingActivity.this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED)
                        Toast.makeText(ChattingActivity.this, \"需要打开录音权限\", Toast.LENGTH_SHORT).show();
                    else {
                        Toast.makeText(ChattingActivity.this, \"长按说话\", Toast.LENGTH_SHORT).show();
                    }
                }
                return false;
            }
        });

        msgList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                Msg m = datas.get(i);
                try {
                    if (m.getFlag() == 1) {
                        final MediaP  p  = new MediaP ();
                        p .setDataSource(m.getF().getAbsolutePath());
                        p .prepare();
                        p .start();

                        //录音播放完毕
                        p .setOnCompletionListener(new MediaP .OnCompletionListener() {
                            @Override
                            public void onCompletion(MediaP  mediaP ) {
                                p .stop();
                                p .release();
                            }
                        });
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * 销毁后删除之前保留的录音
     */
    @Override
    protected void onDestroy() {
        super.onDestroy();
        for (int i = 0; i < voices.size(); i++) {
            voices.get(i).delete();
        }
    }

    /**
     * android 6.0之后动态申请权限
     */
    private void requestPermission() {
        //如果权限没有被申请
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.RECORD_AUDIO}, REQ_CODE);
        } else {
            //如果已经申请了
            flag = true;
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == REQ_CODE) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                //权限申请成功
                flag = true;
            } else {
                //权限申请失败
                Toast.makeText(this, \"需要打开录音权限\", Toast.LENGTH_SHORT).show();
            }
        }
    }
}

了解更多权限请看:动态获取权限的封装

收藏 打印