android录音播放问题

本文详细介绍了在Android平台上实现录音和播放功能的实践经验。首先尝试使用MediaRecorder,然后转而采用AudioRecord结合系统AEC和BS进行回音和噪声消除,但效果不理想。最终决定继续使用MediaRecorder,因为它简洁易用。在播放过程中,涉及扬声器与听筒切换、耳机插拔状态判断、音频流类型设置、资源释放、息屏状态判断以及音量键管理等多个细节问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近要做一个录音并且播放的功能,开始用的系统自带的 MediaRecorder,效果一般。
尝试用AudioRecord,在用系统AEC,BS去回音去噪,结果发现效果也是差不多
尝试用WebRtc,结果发现效果也是差不多。
可能跟4.1之后的系统就已经把WebRtc带上了,所以最终还是 MediaRecorder,毕竟它最简单。

播放的时候:
1,需要扬声器和听筒切换,就需要监听距离感应器SensorManager;
2,需要判断耳机插拔状态;
需要注意:
1,mediaPlayer.setAudioStreamType(AudioManager.STREAM_VOICE_CALL); 
    audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
    始终用这个,因为不用通话模式,听筒的时候声音会很小;
2,需要去注册耳机插拔的广播,因为只是有些机子会插上耳机后会默认耳机播放;
3,最好播放完毕就mediaPlayer.release();mediaPlayer=null;释放资源;
4,部分机型息屏会调Activity的OnPause,所以可能要用到 isScreenOff()判断;
5,音量键调节,是根据audioManager.setMode()方法控制调哪种音量的。所以Activity的OnPause里面要释放到AudioManager.MODE_NORMAL;
     
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.AssetFileDescriptor;
import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Build;
import android.os.PowerManager;

import com.qihoo.litegame.BaseApplication;
import com.qihoo.utils.ToastUtil;

import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.IOException;

public class PlayerManager implements SensorEventListener {
    public static final int MODE_SPEAKER = 0;
    public static final int MODE_HEADSET = 1;
    public static final int MODE_EARPIECE = 2;

    private static PlayerManager playerManager;

    private Context context;
    private AudioManager audioManager;
    private MediaPlayer mediaPlayer;
    private PlayCallback callback;

    private PowerManager powerManager;
    private PowerManager.WakeLock wakeLock;
    private SensorManager sensorManager;
    private Sensor sensor;
    private HeadsetReceiver headsetReceiver;

    private boolean isPause = false;

    private String filePath;

    private int currentMode = MODE_SPEAKER;

    private boolean isScreenOff = false;

    public static PlayerManager getManager() {
        if (playerManager == null) {
            synchronized (PlayerManager.class) {
                playerManager = new PlayerManager();
            }
        }
        return playerManager;
    }

    private PlayerManager() {
        context = BaseApplication.applicationContext;
//    initMediaPlayer();
//    initAudioManager();
    }

    public String getFilePath() {
        return filePath;
    }

    public boolean isScreenOff() {
        return isScreenOff;
    }

    public void registerSensorListener() {
        initSensor();
        sensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_NORMAL);
    }

    public void unregisterSensorListener() {
        if (sensorManager != null) {
            sensorManager.unregisterListener(this);
        }
    }

    public void registerHeadsetReceiver() {
        if (headsetReceiver == null) {
            headsetReceiver = new HeadsetReceiver();
        }
        IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_HEADSET_PLUG);
        filter.addAction(AudioManager.ACTION_AUDIO_BECOMING_NOISY);
        context.registerReceiver(headsetReceiver, filter);
    }

    public void unregisterHeadsetReceiver() {
        if (headsetReceiver != null) {
            context.unregisterReceiver(headsetReceiver);
        }
    }

    private void initSensor() {
        if (sensorManager == null) {
            sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
            sensor = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
        }
    }

    private void initMediaPlayer() {
        if (mediaPlayer == null) {
            mediaPlayer = new MediaPlayer();
            mediaPlayer.setAudioStreamType(AudioManager.STREAM_VOICE_CALL);
        }
    }

    private void initAudioManager() {
        if (audioManager == null) {
            audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
        }
        if (Build.VERSION.SDK_INT >= 11) {
            audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
        } else {
            audioManager.setMode(AudioManager.MODE_IN_CALL);
        }
        resetPlayMode();
    }

    public void play(Context context, String path, finalPlayCallback callback) {
        FileInputStream is = null;
        try {
            File file = new File(path);
            if (file.exists()) {
                is = new FileInputStream(file);
                FileDescriptor fd = is.getFD();
                play(context, fd, 0, 0x7ffffffffffffffL, callback);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (is != null) {
                    is.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public void play(Context context, AssetFileDescriptor afd, final PlayCallback callback) {
        try {
            play(context, afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength(), callback);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (afd != null) {
                    afd.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public void play(Context context, FileDescriptor fd, longoffset, long length, final PlayCallback callback) {
        this.callback = callback;
        try {
            initMediaPlayer();
            initAudioManager();
            intcurrentValue = audioManager.getStreamVolume(AudioManager.STREAM_VOICE_CALL);
            if (currentValue == 0) {
                ToastUtil.show(R.string.voice_value_no);
            }

            mediaPlayer.reset();
            mediaPlayer.setDataSource(fd, offset, length);
            mediaPlayer.prepareAsync();
            mediaPlayer.setOnPreparedListener(new OnPreparedListener() {
                @Override
                public void onPrepared(MediaPlayer mp) {
                    if (callback != null) {
                        callback.onPrepared();
                    }
                    mediaPlayer.start();

                    if (TextUtil.isEmpty(SharePreferenceUtil.obtainSharePreference(null, BusinessConstant.Voice_First_Tip))) {
                        SharePreferenceUtil.commitSharePreference(null, BusinessConstant.Voice_First_Tip, "1");
                        ToastUtil.show(R.string.voice_first_tip);
                    }
                }
            });
            mediaPlayer.setOnCompletionListener(newMediaPlayer.OnCompletionListener() {
                @Override
                public void onCompletion (MediaPlayer mp){
                    resetPlayMode();
                    mediaPlayer.release();
                    mediaPlayer = null;
                    if (callback != null) {
                        callback.onComplete();
                    }
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public boolean isPause() {
        return isPause;
    }

    public void pause() {
        if (isPlaying()) {
            isPause = true;
            mediaPlayer.pause();
        }
    }

    public void resume() {
        if (isPause && mediaPlayer != null) {
            isPause = false;
            mediaPlayer.start();
        }
    }

    public int getCurrentMode() {
        return currentMode;
    }

    public void changeToEarpieceMode() {
        if (audioManager != null) {
            currentMode = MODE_EARPIECE;
// if (Build.VERSION.SDK_INT >= 11){
//audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
// } else {
// audioManager.setMode(AudioManager.MODE_IN_CALL);
// }
            audioManager.setSpeakerphoneOn(false);
        }
    }

    public void changeToHeadsetMode() {
        if (audioManager != null) {
            currentMode = MODE_HEADSET;
// audioManager.setMode(AudioManager.MODE_NORMAL);
            audioManager.setSpeakerphoneOn(false);
        }
    }

    public void changeToSpeakerMode() {
        if (audioManager != null) {
            currentMode = MODE_SPEAKER;
// audioManager.setMode(AudioManager.MODE_NORMAL);
            audioManager.setSpeakerphoneOn(true);
        }
    }

    public void resetPlayMode() {
        if (audioManager != null) {
            if (audioManager.isWiredHeadsetOn()) {
                changeToHeadsetMode();
            } else {
                changeToSpeakerMode();
            }
        }
    }

    public void stop() {
        if (isPlaying()) {
            try {
                mediaPlayer.stop();
                if (callback != null) {
                    callback.onStop();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public void stopAndDestroy() {
        if (isPlaying()) {
            mediaPlayer.stop();
            mediaPlayer.release();
            mediaPlayer = null;
            if (callback != null) {
                callback.onStop();
            }
        }
    }

    public void destroy() {
        stopAndDestroy();
        if (audioManager != null) {
            audioManager.setMode(AudioManager.MODE_NORMAL);
            audioManager = null;
        }
    }

    public boolean isPlaying() {
        return mediaPlayer != null && mediaPlayer.isPlaying();
    }

    @Override
    public void onSensorChanged(SensorEvent event) {
//耳机模式下直接返回
        if (currentMode == MODE_HEADSET) { // || audioManager == null|| audioManager.isWiredHeadsetOn()
            return;
        }

        float value = event.values[0];
        if (isPlaying()) {
            if (value == sensor.getMaximumRange()) {
                resetPlayMode();
                setScreenOn();
            } else {
                changeToEarpieceMode();
                setScreenOff();
            }
        } else {
            if (value == sensor.getMaximumRange()) {
                resetPlayMode();
                setScreenOn();
            }
        }
    }

    private void setScreenOff() {
        LogUtils.d("setScreenOff===");
        isScreenOff = true;
        if (wakeLock == null) {
            powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
            wakeLock = powerManager.newWakeLock(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK, "PlayerManager");
        }
        wakeLock.acquire();
    }

    private void setScreenOn() {
        LogUtils.d("setScreenOn===");
        isScreenOff = false;
        if (wakeLock != null) {
            wakeLock.setReferenceCounted(false);
            wakeLock.release();
            wakeLock = null;
        }
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {

    }

    class HeadsetReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            LogUtils.d("HeadsetReceiver===" + action);
            if (Intent.ACTION_HEADSET_PLUG.equals(action)) {
                int state = intent.getIntExtra("state", 0);
                if (state == 1) {
                    changeToHeadsetMode();
                } else if (state == 0) {
                    resume();
                }
            }
            elseif(AudioManager.ACTION_AUDIO_BECOMING_NOISY.equals(action)) {
//拔出耳机会触发此广播,拔出不会触发,且此广播比上一个早,故可在此暂停播放,收到上一个广播时在恢复播放
                pause();
                changeToSpeakerMode();
            }
        }
    }

    public interface PlayCallback {

        void onPrepared();

        void onComplete();

        void onStop();
    }


}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值