package com.example.wechattest;
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 DialogManager {
private Dialog mDialog;
private ImageView mIcon;
private ImageView mVoice;
private TextView mLable;
private Context mContext;
public DialogManager(Context context) {
mContext = context;
}
public void showRecordingDialog() {
mDialog = new Dialog(mContext,R.style.AudioDialogTheme);
LayoutInflater inflater = LayoutInflater.from(mContext);
View view = inflater.inflate(R.layout.dialog_recorder, null);
mDialog.setContentView(view);
mIcon = (ImageView) mDialog.findViewById(R.id.iv_dialog_icon);
mVoice = (ImageView) mDialog.findViewById(R.id.iv_dialog_voice);
mLable = (TextView) mDialog.findViewById(R.id.tv_dialog_lable);
mDialog.show();
}
public void recording() {
if (mDialog != null && mDialog.isShowing()) {
mIcon.setVisibility(View.VISIBLE);
mVoice.setVisibility(View.VISIBLE);
mLable.setVisibility(View.VISIBLE);
mIcon.setImageResource(R.drawable.recorder);
mLable.setText(R.string.recorder_to_cancel);
}
}
public void wantToCancel() {
if (mDialog != null && mDialog.isShowing()) {
mIcon.setVisibility(View.VISIBLE);
mVoice.setVisibility(View.GONE);
mLable.setVisibility(View.VISIBLE);
mIcon.setImageResource(R.drawable.cancel);
mLable.setText(R.string.recorder_cancel);
}
}
public void tooShort() {
if (mDialog != null && mDialog.isShowing()) {
mIcon.setVisibility(View.VISIBLE);
mVoice.setVisibility(View.GONE);
mLable.setVisibility(View.VISIBLE);
mIcon.setImageResource(R.drawable.voice_to_short);
mLable.setText(R.string.recorder_too_short);
}
}
public void dimissDialog() {
if (mDialog != null && mDialog.isShowing()) {
mDialog.dismiss();
mDialog = null;
}
}
/**
* 通过level更新voice上的图片
* @param level
*/
public void updateVoiceLevel(int level) {
if (mDialog != null && mDialog.isShowing()) {
// mIcon.setVisibility(View.VISIBLE);
// mVoice.setVisibility(View.VISIBLE);
// mLable.setVisibility(View.VISIBLE);
int resid = mContext.getResources().getIdentifier("v" + level,
"drawable", mContext.getPackageName());
mIcon.setImageResource(resid);
mLable.setText(R.string.recorder_too_short);
}
}
}
/////////////////////////////////////////////////////////////////////
package com.example.wechattest;
import java.io.File;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.UUID;
import android.media.MediaRecorder;
public class AudioManager {
private MediaRecorder mMediaRecorder;
private String mCurrentFilePath;
private String mDir;
private static AudioManager mInstance;
private boolean isPrepared;
private AudioManager(String dir) {
mDir = dir;
}
public interface AudioStateListenner {
void wellPrepared();
}
public AudioStateListenner mListenner;
public void setOnAudioAudioStateListenner(AudioStateListenner listenner) {
mListenner = listenner;
}
public static AudioManager getInstance(String dir) {
if (mInstance == null) {
synchronized (AudioManager.class) {
if (mInstance == null) {
mInstance = new AudioManager(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);
// 音频的格式
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.RAW_AMR);
// 音频的编码
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
mMediaRecorder.prepare();
mMediaRecorder.start();
// 准备结束
isPrepared = true;
if (mListenner != null)
mListenner.wellPrepared();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private String generateFileName() {
return UUID.randomUUID().toString() + ".amr";
}
public int getVoiceLevel(int maxLevel) {
if (isPrepared) {
// mMediaRecorder.getMaxAmplitude()值在1-32767之间
try {
return maxLevel * mMediaRecorder.getMaxAmplitude() / 32768 + 1;
} catch (IllegalStateException e) {
}
}
return 1;
}
public void release() {
mMediaRecorder.stop();
mMediaRecorder.release();
mMediaRecorder = null;
}
public void cancel() {
release();
if (mCurrentFilePath != null) {
File f = new File(mCurrentFilePath);
f.delete();
mCurrentFilePath = null;
}
}
public String getCurrentFilePath() {
// TODO Auto-generated method stub
return mCurrentFilePath;
}
}
/////////////////////////////////////////////////////////////////////
package com.example.wechattest;
import com.example.wechattest.AudioManager.AudioStateListenner;
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 AudioButtonView extends Button implements AudioStateListenner {
private static final int DISTANCE = 50;
private static final int STATE_NORMAL = 1;
private static final int STATE_RECORDING = 2;
private static final int STATE_CANCEL = 3;
private int mState = STATE_NORMAL;
private boolean isRecording = false;
private DialogManager mDialogManager;
private AudioManager mAudioManager;
private float mTime;
// 是否出发长按
private boolean mReady = false;
public AudioButtonView(Context context, AttributeSet attrs) {
super(context, attrs);
mDialogManager = new DialogManager(getContext());
String dir = Environment.getDataDirectory() + "/wechat_self";
mAudioManager = AudioManager.getInstance(dir);
mAudioManager.setOnAudioAudioStateListenner(this);
setOnLongClickListener(new OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
mReady = true;
mAudioManager.prepareAudio();
return false;
}
});
}
/**
* 录音完成后的回调
*
* @author Administrator
*
*/
public interface audioFinishRecorderListener {
void onFinish(float seconds, String filePath);
}
private audioFinishRecorderListener mListener;
public void setAudioFinishRecorderListener(
audioFinishRecorderListener listener) {
mListener = listener;
}
/**
* 获取音量大小的Runnable
*/
private Runnable mGetVoiceLevelRunnable = new Runnable() {
@Override
public void run() {
while (isRecording) {
try {
Thread.sleep(100);
mTime += 0.1f;
mHandler.sendEmptyMessage(MSG_VOICE_CHANGED);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
private static final int MSG_AUDIO_PREPARED = 0X110;
private static final int MSG_VOICE_CHANGED = 0X111;
private static final int MSG_DIALOG_DIMISS = 0X112;
private Handler mHandler = new Handler() {
public void handlerMessage(android.os.Message msg) {
switch (msg.what) {
case MSG_AUDIO_PREPARED:
mDialogManager.showRecordingDialog();
isRecording = true;
new Thread(mGetVoiceLevelRunnable).start();
break;
case MSG_VOICE_CHANGED:
mDialogManager.updateVoiceLevel(mAudioManager.getVoiceLevel(7));
break;
case MSG_DIALOG_DIMISS:
break;
}
};
};
@Override
public void wellPrepared() {
mHandler.sendEmptyMessage(MSG_AUDIO_PREPARED);
}
public AudioButtonView(Context context) {
this(context, null);
// TODO Auto-generated constructor stub
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
int x = (int) event.getX();
int y = (int) event.getY();
switch (action) {
case MotionEvent.ACTION_DOWN:
changeState(STATE_RECORDING);
break;
case MotionEvent.ACTION_MOVE:
if (isRecording) {
if (wantToCancel(x, y)) {
changeState(STATE_CANCEL);
} else {
changeState(STATE_RECORDING);
}
}
break;
case MotionEvent.ACTION_UP:
if (!mReady) {
reset();
return super.onTouchEvent(event);
}
if (!isRecording || mTime < 0.6f) {
mDialogManager.tooShort();
mAudioManager.cancel();
mHandler.sendEmptyMessageDelayed(MSG_DIALOG_DIMISS, 1300);
} else if (mState == STATE_RECORDING) {
// 正常录制结束
mDialogManager.dimissDialog();
mAudioManager.release();
if (mListener != null) {
mListener.onFinish(mTime,
mAudioManager.getCurrentFilePath());
}
} else if (mState == STATE_CANCEL) {
mDialogManager.dimissDialog();
mAudioManager.cancel();
}
reset();
break;
}
return super.onTouchEvent(event);
}
private void reset() {
// TODO Auto-generated method stub
isRecording = false;
mReady = false;
changeState(STATE_NORMAL);
mTime = 0;
}
private boolean wantToCancel(int x, int y) {
if (x < 0 || x > getWidth()) {
return true;
} else if (y < -DISTANCE || y > getHeight() + DISTANCE) {
return true;
}
return false;
}
private void changeState(int state) {
// TODO Auto-generated method stub
if (mState != state) {
mState = state;
switch (state) {
case STATE_NORMAL:
setBackgroundResource(R.drawable.state_recorder_normal);
setText(R.string.recorder_normal);
break;
case STATE_RECORDING:
setBackgroundResource(R.drawable.state_recorder_pressed);
setText(R.string.recorder_recording);
if (isRecording) {
// todo show dialog.recording
mDialogManager.recording();
}
break;
case STATE_CANCEL:
setBackgroundResource(R.drawable.state_recorder_pressed);
setText(R.string.recorder_cancel);
if (isRecording) {
// todo show dialog.cancel
mDialogManager.wantToCancel();
}
break;
}
}
}
}
///////////////下面这是log日志/////////////////////////////
03-11 11:26:20.292: E/Trace(5189): error opening trace file: No such file or directory (2)
03-11 11:26:24.732: E/MediaRecorder(5189): stop called in an invalid state: 4
03-11 11:26:24.732: E/InputEventReceiver(5189): Exception dispatching input event.
03-11 11:26:24.732: E/MessageQueue-JNI(5189): Exception in MessageQueue callback: handleReceiveCallback
03-11 11:26:24.762: E/MessageQueue-JNI(5189): java.lang.IllegalStateException
03-11 11:26:24.762: E/MessageQueue-JNI(5189): at android.media.MediaRecorder.native_stop(Native Method)
03-11 11:26:24.762: E/MessageQueue-JNI(5189): at android.media.MediaRecorder.stop(MediaRecorder.java:777)
03-11 11:26:24.762: E/MessageQueue-JNI(5189): at com.example.wechattest.AudioManager.release(AudioManager.java:101)
03-11 11:26:24.762: E/MessageQueue-JNI(5189): at com.example.wechattest.AudioManager.cancel(AudioManager.java:108)
03-11 11:26:24.762: E/MessageQueue-JNI(5189): at com.example.wechattest.AudioButtonView.onTouchEvent(AudioButtonView.java:142)
03-11 11:26:24.762: E/MessageQueue-JNI(5189): at android.view.View.dispatchTouchEvent(View.java:7143)
03-11 11:26:24.762: E/MessageQueue-JNI(5189): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2176)
03-11 11:26:24.762: E/MessageQueue-JNI(5189): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1919)
03-11 11:26:24.762: E/MessageQueue-JNI(5189): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2176)
03-11 11:26:24.762: E/MessageQueue-JNI(5189): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1919)
03-11 11:26:24.762: E/MessageQueue-JNI(5189): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2176)
03-11 11:26:24.762: E/MessageQueue-JNI(5189): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1919)
03-11 11:26:24.762: E/MessageQueue-JNI(5189): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2176)
03-11 11:26:24.762: E/MessageQueue-JNI(5189): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1919)
03-11 11:26:24.762: E/MessageQueue-JNI(5189): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2176)
03-11 11:26:24.762: E/MessageQueue-JNI(5189): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1919)
03-11 11:26:24.762: E/MessageQueue-JNI(5189): at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1942)
03-11 11:26:24.762: E/MessageQueue-JNI(5189): at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1396)
03-11 11:26:24.762: E/MessageQueue-JNI(5189): at android.app.Activity.dispatchTouchEvent(Activity.java:2399)
03-11 11:26:24.762: E/MessageQueue-JNI(5189): at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1890)
03-11 11:26:24.762: E/MessageQueue-JNI(5189): at android.view.View.dispatchPointerEvent(View.java:7323)
03-11 11:26:24.762: E/MessageQueue-JNI(5189): at android.view.ViewRootImpl.deliverPointerEvent(ViewRootImpl.java:3200)
03-11 11:26:24.762: E/MessageQueue-JNI(5189): at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:3145)
03-11 11:26:24.762: E/MessageQueue-JNI(5189): at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:4181)
03-11 11:26:24.762: E/MessageQueue-JNI(5189): at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:4160)
03-11 11:26:24.762: E/MessageQueue-JNI(5189): at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:4252)
03-11 11:26:24.762: E/MessageQueue-JNI(5189): at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:171)
03-11 11:26:24.762: E/MessageQueue-JNI(5189): at android.os.MessageQueue.nativePollOnce(Native Method)
03-11 11:26:24.762: E/MessageQueue-JNI(5189): at android.os.MessageQueue.next(MessageQueue.java:125)
03-11 11:26:24.762: E/MessageQueue-JNI(5189): at android.os.Looper.loop(Looper.java:124)
03-11 11:26:24.762: E/MessageQueue-JNI(5189): at android.app.ActivityThread.main(ActivityThread.java:4825)
03-11 11:26:24.762: E/MessageQueue-JNI(5189): at java.lang.reflect.Method.invokeNative(Native Method)
03-11 11:26:24.762: E/MessageQueue-JNI(5189): at java.lang.reflect.Method.invoke(Method.java:511)
03-11 11:26:24.762: E/MessageQueue-JNI(5189): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:841)
03-11 11:26:24.762: E/MessageQueue-JNI(5189): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:608)
03-11 11:26:24.762: E/MessageQueue-JNI(5189): at dalvik.system.NativeStart.main(Native Method)
03-11 11:26:24.782: E/dalvikvm(5189): GC_CONCURRENT freed 343K, 8% free 8403K/9095K, paused 12ms+2ms, total 41ms