长按按钮后退出,报错setAudioSource failed.
public class AudioManager {
private MediaRecorder mMediaRecorder;
private String mDir;
private String mCurrentFilePath;
private boolean isPrepared;
private static AudioManager mInstance;
private AudioManager(String dir) {
this.mDir = dir;
}
/*
* 回调准备完毕
* */
public interface AudioStateListener{
void wellPrepared();
}
public AudioStateListener mListener;
public void setOnAudioStateListener(AudioStateListener listener){
this.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.setOutputFile( file.getAbsolutePath() );
// 设置MediaRecorder的音频源为麦克风
mMediaRecorder.setAudioSource( MediaRecorder.AudioSource.MIC );
// 设置音频的格式
mMediaRecorder.setOutputFormat( MediaRecorder.OutputFormat.AMR_NB );
// 设置音频的编码为amr
mMediaRecorder.setAudioEncoder( MediaRecorder.AudioEncoder.AMR_NB );
mMediaRecorder.prepare();
mMediaRecorder.start(); // 可以开始录制了
// 准备结束
isPrepared = true;
if (mListener != null){
mListener.wellPrepared();
}
} catch (IOException e) {
e.printStackTrace();
}
}
// 随机生成文件的名称
private String generateFileName() {
return UUID.randomUUID().toString()+".amr";
}
// 获取voice等级
public int getVoiceLevel(int maxLevel){
if (isPrepared){
try {
// mMediaRecorder.getMaxAmplitude()的值为 1-32768
return maxLevel * mMediaRecorder.getMaxAmplitude() / 32768 + 1;
}catch (Exception e){
}
}
return 1;
}
// 释放
public void release(){
mMediaRecorder.stop();
mMediaRecorder.reset();
mMediaRecorder = null;
}
// 取消
public void cancel(){
release();
if (mCurrentFilePath != null){
File file = new File( mCurrentFilePath );
file.delete();
mCurrentFilePath = null;
}
}
public String getCurrentFilePath() {
return mCurrentFilePath;
}
————————————————————————————————————————————
public class RecorderBtn extends Button implements AudioManager.AudioStateListener {
private static final int STATE_NORMAL = 1; // 默认状态
private static final int STATE_RECORDING = 2; // 开始录音
private static final int STATE_WANT_TO_CANCEL = 3; // 取消录音
private static final int DISTANCE_Y_CANCEL = 50; // 根据坐标改变dialog
private int mCurState = STATE_NORMAL; // 当前默认状态
private RecorderDialog mDialog; // 创建dialog对象
private boolean isRecording = false; // 已经开始录音
private AudioManager mAudioManager;
private float mTime; // 用于计时
private boolean mReady; // 是否出发longclick
/*
* 获取音量大小的Runnble
* */
private Runnable mGetVoiceLevelRunnble = 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();
}
}
}
};
public RecorderBtn(Context context) {
this( context, null );
}
// 初始化按钮和按钮的长按事件
public RecorderBtn(Context context, AttributeSet attrs) {
super( context, attrs );
mDialog = new RecorderDialog( getContext() );
String dir = Environment.getExternalStorageDirectory()+"/recorder_audios";
mAudioManager = AudioManager.getInstance(dir);
mAudioManager.setOnAudioStateListener( this );
setOnLongClickListener( new OnLongClickListener() {
@Override
public boolean onLongClick(View view) {
mReady = true;
mAudioManager.prepareAudio();
return false;
}
} );
}
/*
* 录音完成后的回调
* */
public interface AudioFinishRecorderListener{
void onFinish(float seconds,String filePath);
}
private AudioFinishRecorderListener mListener;
public void setAudioFinishRecorderListener(AudioFinishRecorderListener listener) {
this.mListener = listener;
}
private static final int MSG_AUDIO_PREPARED = 001;
private static final int MSG_VOICE_CHANGED = 002;
private static final int MSG_DIALOG_DIMISS = 003;
private static final int VOICE_LEVEL = 7;
private Handler mHandler = new Handler( ){
@Override
public void handleMessage(Message msg) {
switch (msg.what){
case MSG_AUDIO_PREPARED:
// 真正显示在音频结束准备之后
mDialog.shouRecordingDialog();
isRecording = true;
// 开启线程
new Thread( mGetVoiceLevelRunnble ).start();
break;
case MSG_VOICE_CHANGED:
mDialog.updateVoiveLevel( mAudioManager.getVoiceLevel( VOICE_LEVEL ) );
break;
case MSG_DIALOG_DIMISS:
break;
}
super.handleMessage( msg );
}
};
@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 (wantToCancel( 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){
mDialog.tooShort();
mAudioManager.cancel();
mHandler.sendEmptyMessageDelayed( MSG_DIALOG_DIMISS,1300 );
}else if (mCurState == STATE_RECORDING){
// 正常录制结束
mDialog.dimssDialog();
mAudioManager.release();
if (mListener != null ){
mListener.onFinish( mTime, mAudioManager.getCurrentFilePath());
}
}else if (mCurState == STATE_WANT_TO_CANCEL){
mDialog.dimssDialog();
mAudioManager.cancel();
}
reset();
break;
}
return super.onTouchEvent( event );
}
// 设置最开始按钮的默认状态
private void reset() {
isRecording = 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;
}
// 改变按钮的内容
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_RECORDING:
setBackgroundResource( R.drawable.btn_recorder_recording );
setText( R.string.str_recorder_recording );
if(isRecording){
mDialog.recording();
}
break;
case STATE_WANT_TO_CANCEL:
setBackgroundResource( R.drawable.btn_recorder_recording );
setText( R.string.str_recorder_want_cancel );
mDialog.wantToCancel();
break;
}
————————————————————————————————————————————
权限也加过了啊,为什么会这样,求解