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

长按按钮后退出,报错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;
           }
————————————————————————————————————————————

权限也加过了啊,为什么会这样,求解

正在回答

1 回答

如果是电脑上用的虚拟机那就是虚拟机没有麦克风导致

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

举报

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

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

进入课程

长按按钮后退出,报错setAudioSource failed.

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