1.MediaRecorder
2.MediaRecorder类的生命周期
2.一个录音的案例
1、定义列表的布局
创建布局文件recode_files.xml
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TableRow>
<ImageView
android:id="@+id/icon"
android:src="@drawable/mic"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/filename"
android:textSize="16px"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</TableRow>
</TableLayout>
2、主布局文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageButton
android:id="@+id/reord"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/play"/>
<ImageButton
android:id="@+id/stop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/stop"/>
</LinearLayout>
<TextView
android:id="@+id/info"
android:text="文字提示信息"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<ListView
android:id="@+id/reclist"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
3、设置操作权限
android6以后权限需要在程序中动态引用 private String permssionRequestCode []={Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.RECORD_AUDIO,Manifest.permission.MODIFY_AUDIO_SETTINGS};
//动态请求各种权限
ActivityCompat.requestPermissions(this,permssionRequestCode, 0);
ActivityCompat.requestPermissions(this,permssionRequestCode, 1);
ActivityCompat.requestPermissions(this,permssionRequestCode,2);
3、主布局文件
public class MainActivity extends AppCompatActivity {
private ImageButton recode,stop;
private ListView relist=null;
private TextView info=null;
private SimpleAdapter adapter=null;
private MediaRecorder mediaRecorder=null;
private boolean sdcardExists=false;
private File recordAudioSaveFileDir=null;//音频文件目录
private File recordAudioSaveFile=null;//音频文件名称
private String recordAudioSaveFileName=null;
private String redDict="fengray";//目录名称
private boolean isRecode=false;
private List<Map<String,Object>> recordList=null;
private String permssionRequestCode []={Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.RECORD_AUDIO,Manifest.permission.MODIFY_AUDIO_SETTINGS};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recode=findViewById(R.id.reord);
stop=findViewById(R.id.stop);
info=findViewById(R.id.info);
relist=findViewById(R.id.reclist);
//动态请求各种权限
ActivityCompat.requestPermissions(this,permssionRequestCode, 1);
ActivityCompat.requestPermissions(this,permssionRequestCode, 1);
ActivityCompat.requestPermissions(this,permssionRequestCode,1);
if (sdcardExists= Environment.getExternalStorageState()
.equals(Environment.MEDIA_MOUNTED)){//判断sd卡是否存在
recordAudioSaveFileDir=new File(Environment.getExternalStorageDirectory().toString()+File.separator
+redDict+File.separator);
Toast.makeText(this, "have dict", Toast.LENGTH_SHORT).show();
if (!recordAudioSaveFileDir.exists()){
recordAudioSaveFileDir.mkdirs();
}
}
getRecordFiles();
stop.setEnabled(false);
recode.setOnClickListener( new RecorderOnclickListenerImpl());
stop.setOnClickListener(new StopOnclickListenerImpl());
relist.setOnItemClickListener(new OnItemClickListenerImpl());
}
private class RecorderOnclickListenerImpl implements View.OnClickListener{
@Override
public void onClick(View v) {
if (sdcardExists){
recordAudioSaveFileName=recordAudioSaveFileDir.toString()+File.separator+"myrecode"+System.currentTimeMillis()+".3gp";//每次录音的文件名都不一样
recordAudioSaveFile=new File(recordAudioSaveFileName);
mediaRecorder=new MediaRecorder();//实例化对象
//录制前,必须配置若干参数
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);//音频来源是MIC
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
mediaRecorder.setOutputFile(recordAudioSaveFileName);
try {
mediaRecorder.prepare();//进入就绪状态
} catch (IOException e) {
e.printStackTrace();
}
mediaRecorder.start();
info.setText("正在录音中……");
stop.setEnabled(true);//停止按钮可用
recode.setEnabled(false);
isRecode=true;
}
Toast.makeText(MainActivity.this, "start recode", Toast.LENGTH_SHORT).show();
}
}
private class StopOnclickListenerImpl implements View.OnClickListener{
@Override
public void onClick(View v) {
if (isRecode){
mediaRecorder.stop();;
mediaRecorder.release();//释放资源
stop.setEnabled(false);//停止按钮可用
recode.setEnabled(true);
info.setText("停止录音……,文件路径为"+recordAudioSaveFileName);
}
getRecordFiles();
Toast.makeText(MainActivity.this, "stop Button is disabled", Toast.LENGTH_SHORT).show();
}
}
private void getRecordFiles(){//将一个文件夹中的全部文件列出
recordList=new ArrayList<>();
if (sdcardExists){
File files[]=recordAudioSaveFileDir.listFiles();
for (int i = 0; i <files.length ; i++) {
Map<String, Object> map = new HashMap<>();
map.put("filename", files[i].getName());
recordList.add(map);
}
adapter=new SimpleAdapter(this,recordList,R.layout.recode_files,new String[]{"filename"},new int []{R.id.filename});
relist.setAdapter(adapter);
}
}
//实现播放音频
private class OnItemClickListenerImpl implements AdapterView.OnItemClickListener{
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (adapter.getItem(position) instanceof Map){
Map<?,?> map= (Map<?, ?>) adapter.getItem(position);
Uri uri= android.net.Uri.fromFile(new File(recordAudioSaveFileDir.toString()+File.separator+map.get("filename")));
Intent intent=new Intent(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setDataAndType(uri,"audio/mp3");
startActivity(intent);
}
}
}
}
结果: