为了账号安全,请及时绑定邮箱和手机立即绑定

长按然后就自动崩溃了,代码也对着视频看了几遍,问答区也经常来关注,就是解决不了我的问题,只能来求老师帮忙了!

http://img1.sycdn.imooc.com//5553ea6d00014ed810270467.jpg

package com.fy.recorder.view;

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

import android.media.MediaRecorder;

public class AudioManager
{
   private MediaRecorder mMediaRecorder;
   private String mDir;
   private String mCurrentFilePath;
   private static AudioManager mInstance;
   private AudioManager(String dir) 
   {
	   mDir=dir;
   }
 
public interface AudioStateListener
   {
	   void wellPrepared();
   }
   public AudioStateListener mListener;
   public boolean isPrepared;
public String getCurrentfilePath()
{
	return mCurrentFilePath;
	
}
   public void setOnAudioStateListener(AudioStateListener listener)
   {
	   mListener=listener;
   }
   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.setAudioSource(MediaRecorder.AudioSource.MIC);
	//设置音频格式
	mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.RAW_AMR);
	//设置音频编码
	mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
	//设置输出文件
	mMediaRecorder.setOutputFile(file.getAbsolutePath());
	mMediaRecorder.prepare();
	mMediaRecorder.start();

	isPrepared=true;
	
	
	
	if(mListener!=null)
	{
		mListener.wellPrepared();
		}
	   }catch(IllegalStateException|IOException e)
	   {
		   e.printStackTrace();
	   }
   }

   private String generateFileName() 
   
   {
	
	return UUID.randomUUID().toString()+".amr";
}
public int getVoiceLevel(int maxLevel)
   {
	  if(isPrepared)
	  {
		 try {
			 // maxLevel*mMediaRecorder.getMaxAmplitude() 1-32767
		  return maxLevel*mMediaRecorder.getMaxAmplitude()/32768+1;
		} catch (Exception e) 
		{
	
		}
	  }
	  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;
       }
   
   }
}

然后是Button的

package com.fy.recorder.view;

import com.fy.recorder.R;
import com.fy.recorder.view.AudioManager.AudioStateListener;

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 recorderButton extends Button implements AudioStateListener {

private static final int DISTANCE_Y_CANCEL=50;
private static final int STATE_NORMAL=1;
private static final int STATE_RECORDING=2;
private static final int STATE_WANT_TO_CANCEL=3;
private int mCurState=STATE_NORMAL;
private boolean isRecording=false;
private DialogManager mDialogManager;

private AudioManager mAudioManager;

private float mTime=0;
//
private boolean mReady;
public recorderButton(Context context) {
this(context,null);

}

public recorderButton(Context context, AttributeSet attrs) {
super(context, attrs);
mDialogManager=new DialogManager(getContext());
String dir=Environment.getExternalStorageState()+"/recorder_audios";
mAudioManager=AudioManager.getInstance(dir);
mAudioManager.setOnAudioStateListener(this);
setOnLongClickListener(new OnLongClickListener() {

@Override
public boolean onLongClick(View v)
{
mReady=true;
    mAudioManager.prepareAudio();
return false;
}


});
}
//回调
public interface AudioFinishRecorderListener
{
void onFinish(float seconds,String filePath);
}
private AudioFinishRecorderListener mListener;
public void setAudioFinishRecorderListener(AudioFinishRecorderListener listener)
{
mListener=listener;
}
//获取音量大小
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=0X111;
private static final int MSG_VOICE_CHANGED=0X112;
private static final int MSG_DIALOG_DIMSS=0X113;

private Handler mHandler=new Handler()
{
public void handleMessage(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_DIMSS:
mDialogManager.dimissDialog();
break;


}
}

};
 
@Override
public void wellPrepared() 
{

       mHandler.sendEmptyMessage(MSG_AUDIO_PREPARED);

}
@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(wangtToCancel(x,y))
{
changeState(STATE_WANT_TO_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_DIMSS, 1300);
}else if(mCurState==STATE_RECORDING)//正常录制结束
{

mDialogManager.dimissDialog();
mAudioManager.release();

if(mListener!=null)
{
mListener.onFinish(mTime, mAudioManager.getCurrentfilePath());
}
}else if(mCurState==STATE_WANT_TO_CANCEL)
{
mDialogManager.dimissDialog();
mAudioManager.cancel();
}
reset();
break;
}

return super.onTouchEvent(event);
}
private void reset() {

isRecording=false;
mReady=false;
mTime=0;
changeState(STATE_NORMAL);

}

private boolean wangtToCancel(int x, int y) {
// TODO Auto-generated method stub
if(x<0||x>getWidth())
{
return true;
}
if(y<-DISTANCE_Y_CANCEL||y>getHeight()+DISTANCE_Y_CANCEL)
{
return true;
}
return false;
}

private void changeState(int state) {
// TODO Auto-generated method stub
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_RECORDING:
            setBackgroundResource(R.drawable.btn_recording);
                setText(R.string.str_recorder_recording);
if(isRecording)
{
mDialogManager.recording();
}
                break;
            case STATE_WANT_TO_CANCEL:
            setBackgroundResource(R.drawable.btn_recording);
                setText(R.string.str_recorder_want_cancel);
          mDialogManager.wantToCancel();        
          break;

default:
break;
}
}
}


}


不知道怎么上传代码只能复制了,谢谢老师!!

正在回答

1 回答

首先感谢你对慕课的支持,我详细查看了你贴出的代码,没有发现问题。根据你贴出的异常信息,出错是因为MediaRecorder的状态转移出现的问题,建议你还是根据log排查下,ps:记得使用真机测试。

0 回复 有任何疑惑可以回复我~
#1

h0pe

我也是这个问题,最后发现是 自动补全的exception 是"IllegalStateException"就会松开后崩溃,该成 catch (Exception e) 就ok了 请问一下 IllegalStateException和Exception有什么区别? 谢谢
2015-10-14 回复 有任何疑惑可以回复我~
#2

h0pe

感觉问题在下面这个方法 public int getMaxAmplitude () the maximum absolute amplitude measured since the last call, or 0 when called for the first time Throws IllegalStateException if it is called before the audio source has been set. if it is called before the audio source has been set.是什么意思?
2015-10-14 回复 有任何疑惑可以回复我~

举报

0/150
提交
取消
Android-仿微信语音聊天
  • 参与学习       43200    人
  • 解答问题       220    个

结合自定义View和API,Dialog管理等实现实现微信语音

进入课程

长按然后就自动崩溃了,代码也对着视频看了几遍,问答区也经常来关注,就是解决不了我的问题,只能来求老师帮忙了!

我要回答 关注问题
意见反馈 帮助中心 APP下载
官方微信