eoe 移动开发者论坛

 找回密码
 加入eoe

QQ登录

只需一步,快速开始

查看: 782|回复: 6
收起左侧

[Android实例] android 录音与播放录音 带根据音频大小动态效果

[复制链接]

签到天数: 264 天

连续签到: 2 天

[LV.8]以坛为家I

7

主题

629

帖子

3280

e币
社区认证会员
发表于 2016-5-13 10:53:59 | 显示全部楼层 |阅读模式
先看看效果图:
            

首先是布局文件:
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3.     android:layout_width="match_parent"
  4.     android:layout_height="match_parent"
  5.     android:background="#FFFFFF"
  6.     android:orientation="vertical">

  7.     <RelativeLayout
  8.         android:layout_width="match_parent"
  9.         android:layout_height="wrap_content">

  10.         <TextView
  11.             android:id="@+id/voice_title"
  12.             android:layout_width="wrap_content"
  13.             android:layout_height="wrap_content"
  14.             android:layout_centerInParent="true"
  15.             android:layout_marginBottom="10dp"
  16.             android:layout_marginLeft="20dp"
  17.             android:layout_marginRight="40dp"
  18.             android:layout_marginTop="5dp"
  19.             android:text="录音"
  20.             android:textColor="#333333"
  21.             android:textSize="16sp" />

  22.     </RelativeLayout>

  23.     <RelativeLayout
  24.         android:layout_width="match_parent"
  25.         android:layout_height="40dp"
  26.         android:layout_marginTop="5dp">

  27.         <LinearLayout
  28.             android:id="@+id/voice_frequency"
  29.             android:layout_width="130dp"
  30.             android:layout_height="28dp"
  31.             android:layout_centerInParent="true"
  32.             android:background="@drawable/record_sound_bg"
  33.             android:visibility="gone">

  34.             <ProgressBar
  35.                 android:id="@+id/voice_progress_bar"
  36.                 style="?android:attr/progressBarStyleHorizontal"
  37.                 android:layout_width="match_parent"
  38.                 android:layout_height="match_parent"
  39.                 android:background="@drawable/bg_record_layer1"
  40.                 android:progressDrawable="@drawable/recorder_progress_bar_bg" />

  41.         </LinearLayout>

  42.         <TextView
  43.             android:id="@+id/voice_second"
  44.             android:layout_width="wrap_content"
  45.             android:layout_height="wrap_content"
  46.             android:layout_centerVertical="true"
  47.             android:layout_marginLeft="10dp"
  48.             android:layout_toRightOf="@id/voice_frequency"
  49.             android:textColor="#333333"
  50.             android:textSize="18sp"
  51.             android:visibility="gone" />


  52.     </RelativeLayout>

  53.     <RelativeLayout
  54.         android:layout_width="match_parent"
  55.         android:layout_height="match_parent"
  56.         android:layout_marginTop="5dp"
  57.         android:background="#FFFFFF"
  58.         android:gravity="center_vertical">

  59.         <ImageButton
  60.             android:id="@+id/voice_recorder"
  61.             android:layout_width="80dp"
  62.             android:layout_height="80dp"
  63.             android:layout_centerInParent="true"
  64.             android:layout_marginBottom="5dp"
  65.             android:layout_marginRight="10dp"
  66.             android:background="@drawable/chat_record_bg"
  67.             android:visibility="visible" />

  68.         <TextView
  69.             android:id="@+id/voice_label"
  70.             android:layout_width="wrap_content"
  71.             android:layout_height="wrap_content"
  72.             android:layout_marginBottom="20dp"
  73.             android:layout_below="@id/voice_recorder"
  74.             android:layout_centerHorizontal="true"
  75.             android:text="按住录音"
  76.             android:textColor="#333333"
  77.             android:textSize="16sp" />


  78.         <ImageButton
  79.             android:id="@+id/voice_delete"
  80.             android:layout_width="wrap_content"
  81.             android:layout_height="wrap_content"
  82.             android:layout_centerVertical="true"
  83.             android:layout_marginLeft="30dp"
  84.             android:layout_toRightOf="@id/voice_recorder"
  85.             android:background="@drawable/record_delete"
  86.             android:visibility="gone" />

  87.     </RelativeLayout>


  88. </LinearLayout>
复制代码
最主要的 RecorderDialog.java 文件一、创建builder 和show方法


  1. public RecorderDialog(Context context) {
  2.         this.context = context;
  3.         WindowManager windowManager = (WindowManager) context
  4.                 .getSystemService(Context.WINDOW_SERVICE);
  5.         display = windowManager.getDefaultDisplay();
  6.     }

  7.     public RecorderDialog builder() {
  8.         // 获取Dialog布局
  9.         View view = LayoutInflater.from(context).inflate(
  10.                 R.layout.chat_recorder_dialog, null);

  11.         // 设置Dialog最小宽度为屏幕宽度
  12.         view.setMinimumWidth(display.getWidth());

  13.         // 获取自定义Dialog布局中的控件
  14.         second = (TextView) view.findViewById(R.id.voice_second);
  15.         lable = (TextView) view.findViewById(R.id.voice_label);
  16.         recorder = (ImageButton)view.findViewById(R.id.voice_recorder);
  17.         delete = (ImageButton)view.findViewById(R.id.voice_delete);
  18.         frequency = (View) view.findViewById(R.id.voice_frequency);
  19.         voiceProgressBar = (ProgressBar) view.findViewById(R.id.voice_progress_bar);

  20.         //事件
  21.         recorderListener();

  22.         //删除
  23.         delete.setOnClickListener(new View.OnClickListener() {
  24.             @Override
  25.             public void onClick(View v) {
  26.                 //删除文件
  27.                 file = null;
  28.                 voiceProgressBar.setProgress(0);
  29.                 voiceProgressBar.setMax(0);
  30.                 frequency.setVisibility(View.GONE);
  31.                 second.setVisibility(View.GONE);
  32.                 second.setText("");
  33.                 delete.setVisibility(View.GONE);
  34.                 recorder.setBackgroundResource(R.drawable.chat_record_bg);
  35.                 lable.setText("按住录音");

  36.             }
  37.         });


  38.         // 定义Dialog布局和参数
  39.         dialog = new Dialog(context, R.style.ActionSheetDialogStyle);
  40.         dialog.setContentView(view);
  41.         Window dialogWindow = dialog.getWindow();
  42.         dialogWindow.setGravity(Gravity.LEFT | Gravity.BOTTOM);
  43.         WindowManager.LayoutParams lp = dialogWindow.getAttributes();
  44.         lp.x = 0;
  45.         lp.y = 0;
  46.         dialogWindow.setAttributes(lp);

  47.         return this;
  48.     }

  49.     public void show() {
  50.         dialog.show();
  51.     }
复制代码
重点录音事件,我们重写onTouch()  当按下的时候,我们判断是录音还是播放,如果是播放则调用播放playVoice(),如果是录音则调用startRecorder();

当监听到手指离开的时候,先判断是否是滑动,如果是滑动则取消录音,如果不是则停止录音
  1. /**
  2.      * 录音事件
  3.      */
  4.     private void recorderListener(){
  5.         recorder.setOnTouchListener(new View.OnTouchListener() {
  6.             @Override
  7.             public boolean onTouch(View v, MotionEvent event) {
  8.                 switch (event.getAction()) {
  9.                     case MotionEvent.ACTION_DOWN:// 按下

  10.                         if (delete.getVisibility() == View.VISIBLE) {

  11.                             //在播放
  12.                             if (isPlay) {
  13.                                 isPlay = false;
  14.                                 recorder.setBackgroundResource(R.drawable.record_play);
  15.                                 lable.setText("按下播放");
  16.                                 playVoice();
  17.                             }
  18.                             //不在播放,则播放
  19.                             else {
  20.                                 isPlay = true;
  21.                                 recorder.setBackgroundResource(R.drawable.record_pause);
  22.                                 lable.setText("按下暂停");
  23.                                 playVoice();
  24.                             }

  25.                         } else {
  26.                             lable.setText("松开结束");
  27.                             y1 = event.getY();
  28.                             // 如果当前不是正在录音状态,开始录音
  29.                             if (RECODE_STATE != RECORD_ING) {
  30.                                 startRecorder();
  31.                             }
  32.                         }
  33.                         break;

  34.                     case MotionEvent.ACTION_UP:// 离开

  35.                         if (delete.getVisibility() == View.VISIBLE) {

  36.                         } else {
  37.                             y2 = event.getY();
  38.                             //向上
  39.                             if (y1 - y2 > 100) {
  40.                                 //放弃
  41.                                 abandonRecorder();
  42.                             } else {
  43.                                 //停止录音
  44.                                 stopRecorder();
  45.                             }
  46.                         }
  47.                         break;
  48.                 }
  49.                 return false;
  50.             }
  51.         });
  52.     }
复制代码
开始录音中,我们另外开一个线程取统计录音时间及录音。
  1. /**
  2.      * 开始录音
  3.      */
  4.     private void startRecorder(){
  5.         fileName = String.valueOf(System.currentTimeMillis());
  6.         recorderUtil = new RecorderUtil(voice_folder,fileName);  //文件名voice
  7.         RECODE_STATE = RECORD_ING;
  8.         // 显示录音情况
  9.         showVoiceDialog();
  10.         // 开始录音
  11.         recorderUtil.start();
  12.         // 计时线程
  13.         timeThread();
  14.     }

  15. /**
  16.      * 显示正在录音的图标
  17.      *
  18.      */
  19.     private void showVoiceDialog() {
  20.         dialog = new Dialog(context, R.style.DialogStyle);
  21.         dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
  22.         dialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
  23.                 WindowManager.LayoutParams.FLAG_FULLSCREEN);
  24.         dialog.setContentView(R.layout.chat_record_dialog);
  25.         dialog_image = (ImageButton) dialog.findViewById(R.id.record_dialog_log);
  26.         dialog.show();
  27.     }

  28. /**
  29.      * 录音计时线程
  30.      */
  31.     private void timeThread() {
  32.         timeThread = new Thread(ImageThread);
  33.         timeThread.start();
  34.     }

  35.     /**
  36.      * 录音线程
  37.      */
  38.     private Runnable ImageThread = new Runnable() {

  39.         @Override
  40.         public void run() {
  41.             recodeTime = 0.0f;
  42.             // 如果是正在录音状态
  43.             while (RECODE_STATE == RECORD_ING) {
  44.                 if (recodeTime >= MAX_TIME && MAX_TIME != 0) {
  45.                     handler.sendEmptyMessage(0);
  46.                 } else {
  47.                     try {
  48.                         Thread.sleep(200);

  49.                         recodeTime += 0.2;
  50.                         if (RECODE_STATE == RECORD_ING) {
  51.                             voiceValue = recorderUtil.getAmplitude();
  52.                             handler.sendEmptyMessage(1);
  53.                         }
  54.                     } catch (InterruptedException e) {
  55.                         e.printStackTrace();
  56.                     }

  57.                 }
  58.             }

  59.         }

  60.         Handler handler = new Handler() {
  61.             public void handleMessage(android.os.Message msg) {
  62.                 switch (msg.what) {
  63.                     case 0:
  64.                         // 录音超过60秒自动停止,录音状态设为语音完成
  65.                         if (RECODE_STATE == RECORD_ING) {
  66.                             RECODE_STATE = RECODE_ED;
  67.                             // 如果录音图标正在显示的话,关闭显示图标
  68.                             if (dialog.isShowing()) {
  69.                                 dialog.dismiss();
  70.                             }

  71.                             // 停止录音
  72.                             recorderUtil.stop();
  73.                             voiceValue = 0.0;

  74.                             // 如果录音时长小于1秒,显示录音失败的图标
  75.                             if (recodeTime < 1.0) {
  76. //                                showWarnToast();
  77.                                 RECODE_STATE = RECORD_NO;
  78.                             } else {
  79.                             }
  80.                         }
  81.                         break;

  82.                     case 1:
  83.                         setDialogImage();
  84.                         break;
  85.                 }
  86.             }
  87.         };
  88.     };
复制代码
停止录音时,直接停止并保存录音文件
  1. /**
  2.      * 停止录音
  3.      */
  4.     private void stopRecorder(){
  5.         // 如果是正在录音
  6.         if (RECODE_STATE == RECORD_ING) {
  7.             RECODE_STATE = RECODE_ED;
  8.             // 如果录音图标正在显示,关闭
  9.             if (dialog.isShowing()) {
  10.                 dialog.dismiss();
  11.             }

  12.             // 停止录音
  13.             recorderUtil.stop();
  14.             voiceValue = 0.0;

  15.             if (recodeTime < MIX_TIME) {
  16.                 showWarnToast();
  17.                 RECODE_STATE = RECORD_NO;
  18.                 lable.setText("按住录音");
  19.             } else {
  20.                 MediaPlayer player = new MediaPlayer();
  21.                 file = new File(Environment
  22.                         .getExternalStorageDirectory(), voice_folder+"/"+fileName+".amr");
  23.                 try {
  24.                     player.setDataSource(file.getAbsolutePath());
  25.                 } catch (IllegalArgumentException e) {
  26.                     e.printStackTrace();
  27.                 } catch (SecurityException e) {
  28.                     e.printStackTrace();
  29.                 } catch (IllegalStateException e) {
  30.                     e.printStackTrace();
  31.                 } catch (IOException e) {
  32.                     e.printStackTrace();
  33.                 }

  34.                 frequency.setVisibility(View.VISIBLE);
  35.                 second.setVisibility(View.VISIBLE);
  36.                 second.setText(String.valueOf((int)recodeTime) + "s");
  37.                 delete.setVisibility(View.VISIBLE);
  38.                 recorder.setBackgroundResource(R.drawable.record_play);
  39.                 lable.setText("按下播放");
  40.             }
  41.         }
  42.     }
复制代码
播放录音
  1. /**
  2.      * 播放录音
  3.      */
  4.     private void playVoice() {

  5.         // 如果不是正在播放
  6.         if (!playState) {
  7.             // 实例化MediaPlayer对象
  8.             media = new MediaPlayer();
  9. //          File file = new File(Environment.getExternalStorageDirectory(), voice_folder + "/" + fileName + ".amr");
  10.             try {
  11.                 // 设置播放资源
  12.                 media.setDataSource(file.getAbsolutePath());
  13.                 // 准备播放
  14.                 media.prepare();
  15.                 // 开始播
  16.                 media.start();
  17.                 // 改变播放的标志位
  18.                 playState = true;
  19.                 voiceProgressBar.setMax(((int) media.getDuration()));
  20.                 barUpdate();

  21.                 // 设置播放结束时监
  22.                 media.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
  23.                     @Override
  24.                     public void onCompletion(MediaPlayer mp) {
  25.                         if (playState) {
  26.                             playState = false;
  27.                             isPlay = false;
  28.                             recorder.setBackgroundResource(R.drawable.record_play);
  29.                             lable.setText("按下播放");
  30.                         }
  31.                     }
  32.                 });
  33.             } catch (Exception e) {
  34.                 e.printStackTrace();
  35.             }
  36.         } else {
  37.             // 如果正在播放
  38.             if (media.isPlaying()) {
  39.                 media.stop();
  40.                 playState = false;
  41.             } else {
  42.                 playState = false;
  43.             }

  44.         }
  45.     }
复制代码
根据音频大小动态显示和录音太短的提示
  1. // 录音Dialog图片随声音大小切换
  2.     private void setDialogImage() {
  3.         if (voiceValue < 200.0) {
  4.             dialog_image.setImageResource(R.drawable.record_animate_01);
  5.         }else if (voiceValue > 200.0 && voiceValue < 400) {
  6.             dialog_image.setImageResource(R.drawable.record_animate_02);
  7.         }else if (voiceValue > 400.0 && voiceValue < 800) {
  8.             dialog_image.setImageResource(R.drawable.record_animate_03);
  9.         }else if (voiceValue > 800.0 && voiceValue < 1600) {
  10.             dialog_image.setImageResource(R.drawable.record_animate_04);
  11.         }else if (voiceValue > 1600.0 && voiceValue < 3200) {
  12.             dialog_image.setImageResource(R.drawable.record_animate_05);
  13.         }else if (voiceValue > 3200.0 && voiceValue < 5000) {
  14.             dialog_image.setImageResource(R.drawable.record_animate_06);
  15.         }else if (voiceValue > 5000.0 && voiceValue < 7000) {
  16.             dialog_image.setImageResource(R.drawable.record_animate_07);
  17.         }else if (voiceValue > 7000.0 && voiceValue < 10000.0) {
  18.             dialog_image.setImageResource(R.drawable.record_animate_08);
  19.         }else if (voiceValue > 10000.0 && voiceValue < 14000.0) {
  20.             dialog_image.setImageResource(R.drawable.record_animate_09);
  21.         }else if (voiceValue > 14000.0 && voiceValue < 17000.0) {
  22.             dialog_image.setImageResource(R.drawable.record_animate_10);
  23.         }else if (voiceValue > 17000.0 && voiceValue < 20000.0) {
  24.             dialog_image.setImageResource(R.drawable.record_animate_11);
  25.         }else if (voiceValue > 20000.0 && voiceValue < 24000.0) {
  26.             dialog_image.setImageResource(R.drawable.record_animate_12);
  27.         }else if (voiceValue > 24000.0 && voiceValue < 28000.0) {
  28.             dialog_image.setImageResource(R.drawable.record_animate_13);
  29.         }
  30.     }

  31.     /**
  32.      * 语音太短Toast
  33.      */
  34.     private void showWarnToast(){
  35.         Toast toast = new Toast(context);
  36.         LinearLayout linearLayout = new LinearLayout(context);
  37.         linearLayout.setOrientation(LinearLayout.VERTICAL);
  38.         linearLayout.setPadding(20, 20, 20, 20);

  39.         // 定义一个ImageView
  40.         ImageView imageView = new ImageView(context);
  41.         imageView.setImageResource(R.drawable.icon_chat_talk_no); // 图标

  42.         // 将ImageView和ToastView合并到Layout中
  43.         linearLayout.addView(imageView);
  44.         linearLayout.setGravity(Gravity.CENTER);// 内容居中

  45.         toast.setView(linearLayout);
  46.         toast.setGravity(Gravity.CENTER, 0, 0);// 起点位置为中间 100为向下移100dp
  47.         toast.show();
  48.     }
复制代码
最后要在AndroidManifest.xml 加上权限 <uses-permission  android:name="android.permission.RECORD_AUDIO"/>  

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?加入eoe

x

点评

我支持: 5.0
上海酒店上门,足不出户就能体验高品味享受,我们全天候准备为您服务!使您全身活力再现!把轻松`舒适`和快乐带给您!官网taosilespa.com电话/微信1:13370271997微信2:shanmo12580,务必同时加,qq:80   发表于 2016-8-13 22:23
我支持: 5
赞一个  发表于 2016-6-12 14:55

签到天数: 78 天

连续签到: 1 天

[LV.6]常住居民II

8

主题

209

帖子

1011

e币
发表于 2016-8-10 09:20:17 | 显示全部楼层

签到天数: 24 天

连续签到: 6 天

[LV.4]偶尔看看III

0

主题

34

帖子

228

e币
发表于 2016-8-11 18:13:28 | 显示全部楼层

签到天数: 69 天

连续签到: 2 天

[LV.6]常住居民II

30

主题

601

帖子

1754

e币
圣诞限量勋章
发表于 2016-8-16 14:43:28 | 显示全部楼层

该用户从未签到

2

主题

996

帖子

1543

e币
发表于 2017-3-15 10:19:07 | 显示全部楼层
好,够二十个字符了吧
*滑动验证:
您需要登录后才可以回帖 登录 | 加入eoe

本版积分规则

推荐阅读
赞助商们

QQ|联系我们|小黑屋|手机版|eoe 移动开发者论坛 ( 京ICP备11018032 京公网安11010802020210  

GMT+8, 2017-3-28 19:54 , Processed in 0.599027 second(s), 25 queries , Memcache On.

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表
关闭

扫一扫 关注eoe官方微信