[置顶] Android仿微信语音聊天

1、项目界面展示:


2、项目代码整体结构简析:

   (1)AudioRecorderButton类(录音按钮)State:STATE_NORMAL【正常状态】、STATE_RECORDERING【正在录音的状态】、STATE_WANT_TO_CALCEL【想要放弃录音的装填】;

   (2)AudioDialogManage类(录音过程中的提示对话框)Style:RECORDERING【正在录音】、WANT_TO_CANCEL【取消提示对话框】、TOO_SHAORT【录音时间过短提醒对话框】;

   (3)AudioManage类(控制录音)prepare()(end prepare-—》callback)【去录音】, cancel()【取消录音】, release()【正常结束】(-—》callbackToActivity), getVoiceLevel()【获得音量大小】;

伪码展示:

class AudioRecorderButton
{
	onTouchEvent()
	{
		DOWN: // 按下
			changeButtonState(STATE_RECORDERING);
			onLongClick -> AudioManage.prepare() -> end prepare
			            -> AudioDialogManage.showDialog(RECORDERING)
					   
		MOVE: // 滑动
			if(wantCancel(x,y))
			{
				changeButtonState(STATE_WANT_TO_CALCEL);       //更新Button
				AudioDialogManage.showDialog(WANT_TO_CANCEL);  //更新Dialog
			}
			else
			{
				changeButtonState(STATE_RECORDERING);
				AudioDialogManage.showDialog(RECORDERING);
			}
			
		UP:   // 抬起
			if(wantCancel == curState)          //取消
			{
				AudioManage.cancel();
			}
			if(STATE_RECORDERING = curState)    //正常结束
			{
				AudioManage.release();
				callbackToActivity(path,time);
			}
			
			......
	}
}

1、主界面布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"  
    android:orientation="vertical" >

    <!-- 语音列表 -->
    <ListView
        android:id="@+id/voiceNotesListView"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:background="#ebebeb"
        android:divider="@null"
        android:dividerHeight="10dp" >
    </ListView>

    <!-- 底部按钮布局 -->
    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <songshi.suishou.tool.AudioRecorderButton
            android:id="@+id/recorderButton"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="50dp"
            android:layout_marginRight="50dp"
            android:layout_marginTop="6dp"
            android:layout_marginBottom="7dp"
            android:gravity="center"
            android:padding="5dp"
            android:minHeight="0dp"
            android:background="@drawable/btn_recorder_normal"
            android:text="@string/str_recorder_normal"
            android:textColor="#727272"
            >
        </songshi.suishou.tool.AudioRecorderButton>
        
        <View android:layout_width="match_parent"
            android:layout_height="1dp"
            android:background="#ccc"/>
    </FrameLayout>

</LinearLayout>

<string name="str_recorder_normal">按住 说话</string>
<string name="str_recorder_recording">松开 结束</string>
<string name="str_recorder_want_cancel">滑动手指,取消记录</string>

2、AudioRecorderButton类:

package com.example.voicenotes;

import com.example.voicenotes.AudioManage.AudioStateListenter;

import android.content.Context;
import android.os.Environment;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;

public class AudioRecorderButton extends Button implements AudioStateListenter {

	private static final int STATE_NORMAL = 1;           //默认状态
	private static final int STATE_RECORDERING = 2;      //录音状态
	private static final int STATE_WANT_TO_CALCEL = 3;   //取消状态

	private int mCurState = STATE_NORMAL;  //当前状态
	private boolean isRecordering = false; // 是否已经开始录音
	private boolean mReady; // 是否触发onLongClick

	private static final int DISTANCE_Y_CANCEL = 50;

	private AudioDialogManage audioDialogManage;

	private AudioManage mAudioManage;

	//构造方法
	public AudioRecorderButton(Context context) {
		super(context, null);
		// TODO Auto-generated constructor stub
	}
	
	public AudioRecorderButton(Context context, AttributeSet attrs) {
		super(context, attrs);
		audioDialogManage = new AudioDialogManage(getContext());

		String dir = Environment.getExternalStorageDirectory()
				+ "/VoiceRecorder";// 此处需要判断是否有存储卡
		mAudioManage = AudioManage.getInstance(dir);
		mAudioManage.setOnAudioStateListenter(this);

		setOnLongClickListener(new OnLongClickListener() {

			@Override
			public boolean onLongClick(View v) {
				// TODO Auto-generated method stub
				mReady = true;
				// 真正显示应该在audio end prepared以后
				mAudioManage.prepareAudio();
				//return true;
				return false;
			}
		});
		// TODO Auto-generated constructor stub
	}

	//录音完成后的回调
	public interface AudioFinishRecorderListenter{
		void onFinish(float seconds,String FilePath);
	}
	
	private AudioFinishRecorderListenter mListenter;
	
	public void setAudioFinishRecorderListenter(AudioFinishRecorderListenter listenter){
		this.mListenter=listenter;
	}
	
	//复写onTouchEvent
	@Override
	public boolean onTouchEvent(MotionEvent event) {

		int action = event.getAction();   //获取当前Action
		int x = (int) event.getX();
		int y = (int) event.getY();

		switch (action) {
		
		case MotionEvent.ACTION_DOWN:
			changeState(STATE_RECORDERING);
			break;

		case MotionEvent.ACTION_MOVE:

			// 根据X、Y的坐标,判断是否想要取消
			if (isRecordering) {
				if (wantToCancel(x, y)) {
					changeState(STATE_WANT_TO_CALCEL);
				} else {
					changeState(STATE_RECORDERING);
				}
			}
			break;

		case MotionEvent.ACTION_UP:
			if (!mReady) {   //没有触发onLongClick
				reset();
				return super.onTouchEvent(event);
			}

			if (!isRecordering || mTime < 0.5f) {
				audioDialogManage.tooShort();
				mAudioManage.cancel();
				mHandler.sendEmptyMessageDelayed(MSG_DIALOG_DIMISS, 1300);// 延迟,1.3秒以后关闭时间过短对话框
			} 
			/*else if (mTime < 0.5f) {
				audioDialogManage.tooShort();
				isRecordering=false;
				mAudioManage.cancel();
				mHandler.sendEmptyMessageDelayed(MSG_DIALOG_DIMISS, 1300);// 延迟
			}*/

			else if (mCurState == STATE_RECORDERING) { //正常录制结束
				
				audioDialogManage.dimissDialog();
				// release
				mAudioManage.release();
				// callbackToAct
				if(mListenter!=null){
					mListenter.onFinish(mTime, mAudioManage.getCurrentFilePath());
				}				
				
			} else if (mCurState == STATE_WANT_TO_CALCEL) {
				// cancel
				audioDialogManage.dimissDialog();
				mAudioManage.cancel();
			}

			reset();
			break;
		}
		return super.onTouchEvent(event);
	}

	// 恢复状态以及一些标志位
	private void reset() {
		isRecordering = false;
		mReady = false;
		mTime = 0;
		changeState(STATE_NORMAL);
	}

	private boolean wantToCancel(int x, int y) {
		// 判断手指的滑动是否超出范围
		if (x < 0 || x > getWidth()) {
			return true;
		}
		if (y < -DISTANCE_Y_CANCEL || y > getHeight() + DISTANCE_Y_CANCEL) {
			return true;
		}
		return false;
	}

	//改变Button的背景和文本
	private void changeState(int state) {
		if (mCurState != state) {
			mCurState = state;
			switch (state) {
			case STATE_NORMAL:
				setBackgroundResource(R.drawable.btn_recorder_normal);
				setText(R.string.str_recorder_normal);
				break;

			case STATE_RECORDERING:
				setBackgroundResource(R.drawable.btn_recorder_recordering);
				setText(R.string.str_recorder_recording);
				if (isRecordering) {
					// 更新Dialog.recording()
					audioDialogManage.recording();
				}
				break;

			case STATE_WANT_TO_CALCEL:
				setBackgroundResource(R.drawable.btn_recorder_recordering);
				setText(R.string.str_recorder_want_cancel);
				// 更新Dialog.wantCancel()
				audioDialogManage.wantToCancel();
				break;
			}
		}
	}

	private static final int MSG_AUDIO_PREPARED = 0x110;
	private static final int MSG_VOICE_CHANGE = 0x111;
	private static final int MSG_DIALOG_DIMISS = 0x112;

	private float mTime;

	// 获取音量大小的Runnable
	private Runnable mGetVoiceLevelRunnable = new Runnable() {

		@Override
		public void run() {
			// TODO Auto-generated method stub
			while (isRecordering) {
				try {
					Thread.sleep(100);
					mTime += 0.1f;
					mHandler.sendEmptyMessage(MSG_VOICE_CHANGE);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				
			}
		}
	};

	private Handler mHandler = new Handler() {
		public void handleMessage(android.os.Message msg) {
			switch (msg.what) {
			case MSG_AUDIO_PREPARED:
				audioDialogManage.showRecorderingDialog();
				isRecordering = true;

				new Thread(mGetVoiceLevelRunnable).start();
				break;

			case MSG_VOICE_CHANGE:
				audioDialogManage.updateVoiceLevel(mAudioManage
						.getVoiceLevel(7));
				break;

			case MSG_DIALOG_DIMISS:
				audioDialogManage.dimissDialog();
				break;
			}
		};
	};

	@Override
	public void wellPrepared() {
		// TODO Auto-generated method stub
		mHandler.sendEmptyMessage(MSG_AUDIO_PREPARED);
	}
}

3、AudioDialogManage类:

Dialog布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/dialog_loading_bg"
    android:gravity="center"
    android:orientation="vertical"
    android:padding="20dp" >

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <ImageView
            android:id="@+id/recorder_dialog_icon"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/recorder"
            android:visibility="visible" />

        <ImageView
            android:id="@+id/recorder_dialog_voice"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/v1"
            android:visibility="visible" />
    </LinearLayout>

    <TextView
        android:id="@+id/recorder_dialog_label"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dp"
        android:text="手指滑动,取消录音"
        android:textColor="#FFFFFFFF" />

</LinearLayout>
AudioDialogManage类:
package com.example.voicenotes;


import android.app.Dialog;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;

public class AudioDialogManage {
	private Dialog mDialog;

	private ImageView mIcon;
	private ImageView mVoice;

	private TextView mLabel;

	private Context mContext;

	public AudioDialogManage(Context context) {
		this.mContext = context;
	}

	//默认的对话框的显示
	public void showRecorderingDialog() {
		mDialog = new Dialog(mContext, R.style.Theme_AudioDialog);

		LayoutInflater inflater = LayoutInflater.from(mContext);
		View view = inflater.inflate(
				R.layout.tools_voice_notes_dialog_recorder, null);
		mDialog.setContentView(view);

		mIcon = (ImageView) mDialog.findViewById(R.id.recorder_dialog_icon);
		mVoice = (ImageView) mDialog.findViewById(R.id.recorder_dialog_voice);
		mLabel = (TextView) mDialog.findViewById(R.id.recorder_dialog_label);

		mDialog.show();
	}

	//正在录音时,Dialog的显示
	public void recording() {
		if (mDialog != null && mDialog.isShowing()) {
			mIcon.setVisibility(View.VISIBLE);
			mVoice.setVisibility(View.VISIBLE);
			mLabel.setVisibility(View.VISIBLE);

			mIcon.setImageResource(R.drawable.recorder);
			mLabel.setText("手指滑动,取消录音");
		}
	}

	public void wantToCancel() {
		if (mDialog != null && mDialog.isShowing()) {
			mIcon.setVisibility(View.VISIBLE);
			mVoice.setVisibility(View.GONE);
			mLabel.setVisibility(View.VISIBLE);

			mIcon.setImageResource(R.drawable.cancel);
			mLabel.setText("松开手指,取消录音");
		}
	}

	//录音时间过短
	public void tooShort() {
		if (mDialog != null && mDialog.isShowing()) {
			
			mIcon.setVisibility(View.VISIBLE);
			mVoice.setVisibility(View.GONE);
			mLabel.setVisibility(View.VISIBLE);
			
			mIcon.setImageResource(R.drawable.voice_to_short);
			mLabel.setText("录音时间过短");
		}
	}

	public void dimissDialog() {
		if (mDialog != null && mDialog.isShowing()) {
			mDialog.dismiss();
			mDialog = null;
		}	
	}

	//通过Level更新Voice的图片V1——V7
	public void updateVoiceLevel(int level) {
		if (mDialog != null && mDialog.isShowing()) {
			//mIcon.setVisibility(View.VISIBLE);
			//mVoice.setVisibility(View.VISIBLE);
			//mLabel.setVisibility(View.VISIBLE);
			
			int resId=mContext.getResources().getIdentifier("v"+level, "drawable", mContext.getPackageName());
			mVoice.setImageResource(resId);
		}
	}
}

4、AudioManage类:

MediaRecorder:http://developer.android.com/reference/android/media/MediaRecorder.html

MediaRecorder状态转换图:

[置顶] Android仿微信语音聊天_第1张图片

AudioManage类:

package com.example.voicenotes;

import java.io.File;
import java.io.IOException;
import java.util.UUID;

import android.media.MediaRecorder;

public class AudioManage {

	private MediaRecorder mMediaRecorder;
	private String mDir; // 文件夹的名称
	private String mCurrentFilePath;

	private static AudioManage mInstance;

	private boolean isPrepared; // 标识MediaRecorder准备完毕

	private AudioManage(String dir) {
		mDir = dir;
	}

	// 回调准备完毕
	public interface AudioStateListenter {
		void wellPrepared(); // prepared完毕
	}

	public AudioStateListenter mListenter;

	public void setOnAudioStateListenter(AudioStateListenter audioStateListenter) {
		mListenter = audioStateListenter;
	}

	// 单例实现 AudioManage
	
	//DialogManage主要管理Dialog,Dialog主要依赖Context,而且此Context必须是Activity的Context,
	//DialogManage写成单例实现,将是Application级别的,将无法释放,容易造成内存泄露,甚至导致错误
	public static AudioManage getInstance(String dir) {
		if (mInstance == null) {
			synchronized (AudioManage.class) { // 同步
				if (mInstance == null) {
					mInstance = new AudioManage(dir);
				}
			}
		}

		return mInstance;
	}

	// 准备
	public void prepareAudio() {

		try {
			isPrepared = false;

			File dir = new File(mDir);
			if (!dir.exists()) {
				dir.mkdirs();
			}

			String fileName = GenerateFileName(); // 文件名字
			File file = new File(dir, fileName); // 路径+文件名字

			mCurrentFilePath = file.getAbsolutePath();

			mMediaRecorder = new MediaRecorder();
			mMediaRecorder.setOutputFile(file.getAbsolutePath());// 设置输出文件
			mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);// 设置MediaRecorder的音频源为麦克风
			mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.AMR_NB);// 设置音频的格式
			mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);// 设置音频的编码为AMR_NB

			mMediaRecorder.prepare();

			mMediaRecorder.start();
			isPrepared = true; // 准备结束

			if (mListenter != null) {
				mListenter.wellPrepared();
			}
		} catch (IllegalStateException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	// 随机生成文件名称
	private String GenerateFileName() {
		// TODO Auto-generated method stub
		return UUID.randomUUID().toString() + ".amr"; // 音频文件格式
	}

	// 获得音量等级
	public int getVoiceLevel(int maxLevel) {
		if (isPrepared) {
			try {
				return maxLevel * mMediaRecorder.getMaxAmplitude() / 32768 + 1;
			} catch (Exception e) {
				// TODO Auto-generated catch block
				// e.printStackTrace();
			}
		}
		return 1;
	}

	// 释放
	public void release() {
		mMediaRecorder.stop();
		mMediaRecorder.release();
		mMediaRecorder = null;
	}

	// 取消
	public void cancel() {

		release();

		if (mCurrentFilePath != null) {
			File file = new File(mCurrentFilePath);
			file.delete();    //删除录音文件
			mCurrentFilePath = null;
		}
	}

	public String getCurrentFilePath() {
		// TODO Auto-generated method stub
		return mCurrentFilePath;
	}
}

5、MediaManage类:主要管理语音的播放、暂停、恢复、停止

[置顶] Android仿微信语音聊天_第2张图片

package com.example.voicenotes;

import java.io.IOException;

import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnErrorListener;

public class MediaManage {
	
	private static MediaPlayer mMediaPlayer;
	private static boolean isPause;
	
	public static void playSound(String filePath,MediaPlayer.OnCompletionListener onCompletionListenter){
		if(mMediaPlayer==null){
			mMediaPlayer=new MediaPlayer();
			mMediaPlayer.setOnErrorListener( new OnErrorListener() {
				
				@Override
				public boolean onError(MediaPlayer mp, int what, int extra) {
					// TODO Auto-generated method stub
					mMediaPlayer.reset();
					return false;
				}
			});
		}else{
			mMediaPlayer.reset();
		}
		
		try {
			mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
			mMediaPlayer.setOnCompletionListener(onCompletionListenter);
			mMediaPlayer.setDataSource(filePath);
			mMediaPlayer.prepare();
			mMediaPlayer.start();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalStateException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	
	public static void pause(){
		if(mMediaPlayer!=null && mMediaPlayer.isPlaying()){
			mMediaPlayer.pause();
			isPause=true;
		}
	}
	
	public static void resume(){
		if(mMediaPlayer!=null && isPause){
			mMediaPlayer.start();
			isPause=false;
		}
	}
	
	public static void release(){
		if(mMediaPlayer!=null){
			mMediaPlayer.release();
			mMediaPlayer=null;
		}
	}
}

6、MainActivity:

ListView布局:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="60dp"
    android:layout_marginTop="5dp" >

    <ImageView
        android:id="@+id/voice_robot"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:layout_alignParentLeft="true"
        android:layout_centerVertical="true"
        android:layout_marginLeft="5dp"
        android:src="@drawable/robot" />

    <FrameLayout
        android:id="@+id/recorder_length"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_toRightOf="@id/voice_robot"
        android:background="@drawable/popup_inline_error" >
        
        <View android:id="@+id/recorder_anim"
            android:layout_width="25dp"
            android:layout_height="25dp"
            android:layout_gravity="center_vertical|left"
            android:background="@drawable/presence_audio_online"/>
        
    </FrameLayout>

    <TextView android:id="@+id/recorder_time"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_toRightOf="@id/recorder_length"
        android:text=""
        android:layout_marginLeft="3dp"
        android:textColor="#ff777777"/>
</RelativeLayout>
AudioRecorderAdapter:

package com.example.voicenotes;

import java.util.List;

import android.content.Context;
import android.util.DisplayMetrics;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.ArrayAdapter;
import android.widget.TextView;

import com.example.voicenotes.MainActivity.Recorder;

public class AudioRecorderAdapter extends ArrayAdapter<Recorder> {

        private List<Recorder> mDatas;
<span style="white-space:pre">	</span>private Context mContext;

	private int mMinItemWidth;
	private int mMaxItemWidth;

	private LayoutInflater mInflater;

	public AudioRecorderAdapter(Context context, List<Recorder> datas) {
		super(context, -1, datas);
		
<span style="white-space:pre">		</span>mContext=context;
<span style="white-space:pre">		</span>mDatas=datas;
<span style="white-space:pre">		</span>
<span style="white-space:pre">		</span>mInflater=LayoutInflater.from(context);

		WindowManager windowManager = (WindowManager) context
				.getSystemService(Context.WINDOW_SERVICE);
		DisplayMetrics outMetrics = new DisplayMetrics();
		windowManager.getDefaultDisplay().getMetrics(outMetrics);

		mMaxItemWidth = (int) (outMetrics.widthPixels * 0.7f);
		mMinItemWidth = (int) (outMetrics.widthPixels * 0.15f);
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		// TODO Auto-generated method stub
		ViewHolder holder = null;
		if (convertView == null) {
			convertView = mInflater.inflate(R.layout.tools_voice_notes_recorder_item, parent, false);
			holder=new ViewHolder();
			holder.seconds=(TextView) convertView.findViewById(R.id.recorder_time);
			holder.mLength=convertView.findViewById(R.id.recorder_length);
			
			convertView.setTag(holder);
		}else{
			holder=(ViewHolder) convertView.getTag();
		}
		
		holder.seconds.setText(Math.round(getItem(position).getTime())+"\"");
		ViewGroup.LayoutParams lp=holder.mLength.getLayoutParams();
		lp.width=(int) (mMinItemWidth+(mMaxItemWidth/60f * getItem(position).getTime()));
		return convertView;
	}

	private class ViewHolder {
		TextView seconds;
		View mLength;

	}
}
MainActivity:

package com.example.voicenotes;

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.graphics.drawable.AnimationDrawable;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;

import com.example.voicenotes.AudioRecorderButton.AudioFinishRecorderListenter;

public class MainActivity extends Activity {

	private ListView mListView;
	private ArrayAdapter<Recorder> mAdapter;
	private List<Recorder> mDatas = new ArrayList<Recorder>();

	private AudioRecorderButton mAudioRecorderButton;
	private View mAnimView;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		mListView = (ListView) findViewById(R.id.voiceNotesListView);
		mAudioRecorderButton = (AudioRecorderButton) findViewById(R.id.recorderButton);
		mAudioRecorderButton
				.setAudioFinishRecorderListenter(new AudioFinishRecorderListenter() {

					@Override
					public void onFinish(float seconds, String FilePath) {
						// TODO Auto-generated method stub
						Recorder recorder = new Recorder(seconds, FilePath);
						mDatas.add(recorder);
						mAdapter.notifyDataSetChanged();
						mListView.setSelection(mDatas.size() - 1);
					}
				});

		mAdapter = new AudioRecorderAdapter(this, mDatas);
		mListView.setAdapter(mAdapter);

		mListView.setOnItemClickListener(new OnItemClickListener() {

			@Override
			public void onItemClick(AdapterView<?> parent, View view,
					int position, long id) {
				if (mAnimView != null) {
					mAnimView.setBackgroundResource(R.drawable.adj);
					mAnimView = null;
				}
				// 播放动画
				mAnimView = view.findViewById(R.id.recorder_anim);
				mAnimView.setBackgroundResource(R.drawable.audio_play_anim);
				AnimationDrawable anim = (AnimationDrawable) mAnimView
						.getBackground();
				anim.start();
				// 播放音频
				MediaManage.playSound(mDatas.get(position).filePath,
						new MediaPlayer.OnCompletionListener() {

							@Override
							public void onCompletion(MediaPlayer mp) {
								mAnimView.setBackgroundResource(R.drawable.adj);

							}
						});

			}

		});
	}

	public class Recorder {
		float time;
		String filePath;

		public Recorder(float time, String filePath) {
			super();
			this.time = time;
			this.filePath = filePath;
		}

		public float getTime() {
			return time;
		}

		public void setTime(float time) {
			this.time = time;
		}

		public String getFilePath() {
			return filePath;
		}

		public void setFilePath(String filePath) {
			this.filePath = filePath;
		}

	}
	
	@Override
	protected void onPause() {
		// TODO Auto-generated method stub
		super.onPause();
		MediaManage.pause();
	}
	
	@Override
	protected void onResume() {
		// TODO Auto-generated method stub
		super.onResume();
		MediaManage.resume();
	}
	
	@Override
	protected void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();
		MediaManage.release();
	}
}
全部代码:https://github.com/songshimvp/VoiceNotes

你可能感兴趣的:(android,MediaRecorder,仿微信语音聊天,语音备忘录)