最近要做一个录音并且播放的功能,开始用的系统自带的 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();
}
}