亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定

長按然后就自動崩潰了,代碼也對著視頻看了幾遍,問答區也經常來關注,就是解決不了我的問題,只能來求老師幫忙了!

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-仿微信語音聊天
  • 參與學習       43189    人
  • 解答問題       248    個

結合自定義View和API,Dialog管理等實現實現微信語音

進入課程

長按然后就自動崩潰了,代碼也對著視頻看了幾遍,問答區也經常來關注,就是解決不了我的問題,只能來求老師幫忙了!

我要回答 關注問題
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號