录音时候音频的外放
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了录音时候音频的外放相关的知识,希望对你有一定的参考价值。
参考技术A AVAudiosession*audioSession=[AVAudioSessionsharedInstance];//1.设置为播放和录音状态,以便可以在录制完之后播放录音AVAudioSessionCategoryAmbient AVAudioSessionCategoryPlayAndRecord
[audioSessionsetCategory:AVAudioSessionCategoryPlayAndRecorderror:nil];
[audioSessionsetActive:isActiveerror:nil];
[audioSessionoverrideOutputAudioPort:AVAudioSessionPortOverrideSpeakererror:nil];
//2.这个方法相当于上面方法的和但是比overrideOutputAudioPort时效性更长
//[audioSession setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker error:nil];
UInt32doChangeDefaultRoute =1;
//3.下面方法相当于overrideOutputAudioPort但实效性更长会影响其他应用音频的使用
//kAudioSessionProperty_OverrideAudioRoute kAudioSessionProperty_OverrideCategoryDefaultToSpeaker
AudioSessionSetProperty(
kAudioSessionProperty_OverrideCategoryDefaultToSpeaker,
sizeof(doChangeDefaultRoute),
&doChangeDefaultRoute
);
//加两个地址
http://blog.csdn.net/xy5811/article/details/8563137
https://developer.apple.com/library/content/qa/qa1754/_index.html
Android MediaPlayer播放 听筒外放切换
Android MediaPlayer播放 听筒外放切换,通过注册监听,来判断是否靠近听筒。
结合mediaplayer坐音频播放,Android hardware搞一个根据光感听筒外放切换。
MediaManager是播放器构建模式,维护了一个MediaPlayer,用来重新处理播放器。
MediaManager.builder()
.setContext(MainActivity.this)
.setDebugModel(true)
.setMediaListener(new MediaCallBack() {
@Override
public void progress(int i, int max) {
}
@Override
public void prepare(int duration, String time) {
}
@Override
public void start() {
}
@Override
public void end() {
}
@Override
public void stop() {
}
})
.setUrl("https://96.f.1ting.com/local_to_cube_202004121813/96kmp3/2020/09/21/21e_wc/01.mp3")
.build();
开始播放
MediaManager.start();
停止
MediaManager.stop();
是否正在播放
MediaManager.isPlaying();
暂停
MediaManager.pause();
继续
MediaManager.resume();
销毁当前的mediaplayer destory时候调用
MediaManager.removeAll();
AudioManager
Android为我们提供的(音量大小控制)的API: AudioManager(音频管理器)了,该类位于Android.Media包下,提供了音量控制与铃声模式相关操作。
获得AudioManager对象实例
AudioManager am = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
PowerManager
Android系统为我们提供的电源管理的一个API,其相关接口与设备电池的续航能力有很大的关联, 官方也说了,除非是迫不得已吧,不然的话,应该尽量避免使用这个类,并且使用完以后一定要及时释放。所谓的电源管理包括:CPU运行,键盘或者屏幕亮起来!核心其实就是wakelock锁机制,只要我们拿着这个锁, 那么系统就无法进入休眠状态,可以给用户态程序或内核获取到。锁可以是:”有超时的“或者 “没有超时“,超时的锁到时间后会自动解锁,如果没有了锁或超时,内核会启动休眠机制来进入休眠。
添加权限
<uses-permission android:name="android.permission.WAKE_LOCK"></uses-permission>
获取PowerManager对象实例
powerManager = (PowerManager) getActivity().getSystemService(POWER_SERVICE);
整体的代码如下:
/**
* Created by SHICHENG
* <p>
* Time on 2021/11/08
*/
public class AudioSensorBinder implements LifecycleObserver, SensorEventListener {
public final String TAG = this.getClass().getSimpleName();
private final AudioManager audioManager;
private final PowerManager powerManager;
@Nullable
private WeakReference<AppCompatActivity> activity;
private SensorManager sensorManager;
private Sensor sensor;
private PowerManager.WakeLock wakeLock;
@RequiresApi(api = Build.VERSION_CODES.M)
public AudioSensorBinder(@Nullable AppCompatActivity mActivity) {
this.activity = new WeakReference<>(mActivity);
//可以监听生命周期
if (getActivity()!=null){
getActivity().getLifecycle().addObserver(this);
}
audioManager = (AudioManager) getActivity().getSystemService(AUDIO_SERVICE);
powerManager = (PowerManager) getActivity().getSystemService(POWER_SERVICE);
registerProximitySensorListener();
}
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
public void onResume() {
}
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
public void onDestroy() {
sensorManager.unregisterListener(this);
sensorManager = null;
wakeLock = null;
activity = null;
}
/**
* 注册距离感应器监听器,监测用户是否靠近手机听筒
*/
@RequiresApi(api = Build.VERSION_CODES.M)
private void registerProximitySensorListener() {
if ( getActivity() == null) {
return;
}
sensorManager = (SensorManager) getActivity().getSystemService(SENSOR_SERVICE);
if (sensorManager == null) {
return;
}
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
sensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_NORMAL);
}
private AppCompatActivity getActivity() {
if (activity != null) {
return activity.get();
}
return null;
}
@Override
public void onSensorChanged(SensorEvent event) {
if (audioManager == null) {
return;
}
if (isHeadphonesPlugged()) {
// 如果耳机已插入,设置距离传感器失效
return;
}
if (true) {
Log.i(TAG, "onSensorChanged: " + MediaManager.isPlaying() + " event.values[0]: " + event.values[0]);
}
if (MediaManager.isPlaying()) {
// 如果音频正在播放
float distance = event.values[0];
if (distance >= sensor.getMaximumRange()) {
// 用户远离听筒,音频外放,亮屏
changeToSpeaker();
if (true) {
Log.i(TAG, "onSensorChanged: 外放");
}
} else {
MediaManager.resume();
// 用户贴近听筒,切换音频到听筒输出,并且熄屏防误触
changeToReceiver();
if (true) {
Log.i(TAG, "onSensorChanged: 听筒");
}
audioManager.setSpeakerphoneOn(false);
}
} else {
// 音频播放完了
changeToSpeaker();
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
@SuppressLint("WrongConstant")
private boolean isHeadphonesPlugged() {
if (audioManager == null) {
return false;
}
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
AudioDeviceInfo[] audioDevices = audioManager.getDevices(AudioManager.GET_DEVICES_ALL);
for (AudioDeviceInfo deviceInfo : audioDevices) {
if (deviceInfo.getType() == AudioDeviceInfo.TYPE_WIRED_HEADPHONES
|| deviceInfo.getType() == AudioDeviceInfo.TYPE_WIRED_HEADSET) {
return true;
}
}
return false;
} else {
return audioManager.isWiredHeadsetOn();
}
}
/**
* 切换到外放
*/
public void changeToSpeaker() {
setScreenOn();
if (audioManager == null) {
return;
}
audioManager.setMode(AudioManager.MODE_NORMAL);
audioManager.setSpeakerphoneOn(true);
}
/**
* 切换到耳机模式
*/
public void changeToHeadset() {
if (audioManager == null) {
return;
}
audioManager.setSpeakerphoneOn(false);
}
/**
* 切换到听筒
*/
public void changeToReceiver() {
setScreenOff();
if (audioManager == null) {
return;
}
audioManager.setSpeakerphoneOn(false);
audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
}
private void setScreenOff() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Log.i(TAG, "setScreenOff: 熄灭屏幕");
if (wakeLock == null) {
wakeLock = powerManager.newWakeLock(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK, TAG);
}
wakeLock.acquire(10 * 60 * 1000L /*10 minutes*/);
}
}
private void setScreenOn() {
if (wakeLock != null) {
wakeLock.setReferenceCounted(false);
wakeLock.release();
wakeLock = null;
}
}
}
MediaManager
/**
* Created by SHICHENG
* <p>
* Time on 2021/11/08
*/
public class MediaManager {
private static MediaManagerBuilder mediaManagerBuilder;
public static MediaManagerBuilder builder() {
mediaManagerBuilder = new MediaManagerBuilder();
return mediaManagerBuilder;
}
public static void start(){
mediaManagerBuilder.start();
}
public static boolean isPlaying(){
if (mediaManagerBuilder!=null){
return mediaManagerBuilder.isPlaying();
}
return false;
}
public static void stop(){
if (mediaManagerBuilder!=null){
mediaManagerBuilder.stop();
}
}
public static void pause(){
if (mediaManagerBuilder!=null){
mediaManagerBuilder.pause();
}
}
public static void resume(){
if (mediaManagerBuilder!=null){
mediaManagerBuilder.resume();
}
}
public static void removeAll(){
if (mediaManagerBuilder!=null){
mediaManagerBuilder.removeAll();
}
}
public static class MediaManagerBuilder{
public final String TAG = this.getClass().getSimpleName();
private Handler handler = new Handler();
private boolean isSeekBarChanging;//互斥变量,防止进度条与定时器冲突。
private Context context;
private MediaConfig config;
private MediaCallBack mediaListener;
private MediaPlayer mediaPlayer;
private boolean DEBUG = false;
private SimpleDateFormat format;
private Timer timer;
private TimerTask timerTask;
private SeekBar seekBar;
private MediaManagerBuilder() {
this.config = new MediaConfig();
this.mediaPlayer = new MediaPlayer();
this.format = new SimpleDateFormat("mm:ss");
}
/**
* 当前Activity的上下文
*
* @param context
* @return
*/
public MediaManagerBuilder setContext(Context context){
this.context = context;
return this;
}
/**
* 设置MediaPlayer Url链接
*
* @param url
* @return
*/
public MediaManagerBuilder setUrl(String url){
this.config.url = url;
return this;
}
/**
* 设置播放进度监听回调
*
* @param mediaListener
* @return
*/
public MediaManagerBuilder setMediaListener(MediaCallBack mediaListener){
this.mediaListener = mediaListener;
return this;
}
/**
* 设置是否是debug
*
* @param b
* @return
*/
public MediaManagerBuilder setDebugModel(boolean b){
this.DEBUG = b;
return this;
}
/**
* 设置进度条
*/
public MediaManagerBuilder setProgressSeek(SeekBar seek){
this.seekBar = seek;
return this;
}
/**
* 初始化MediaPlayer
*/
public MediaManagerBuilder build(){
Uri uri = Uri.parse(config.url);
//播放器不能为空
if (mediaPlayer!=null){
//如果是正在播放的状态 需要暂停上一个
if (mediaPlayer.isPlaying()){
mediaPlayer.stop();
}
//重置播放器
mediaPlayer.release();
}
//创建新的播放器
mediaPlayer = new MediaPlayer();
try {
mediaPlayer.setDataSource(config.url); //指定音频文件的路径
mediaPlayer.prepare();//让mediaplayer进入准备状态
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
if (seekBar!=null){
seekBar.setMax(mediaPlayer.getDuration());
}
mediaListener.prepare(mediaPlayer.getDuration(),format.format(mediaPlayer.getDuration()) + "");
}
});
// 监听音频播放完的代码,实现音频的自动循环播放
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer arg0) {
mediaListener.end();
}
});
} catch (IOException e) {
e.printStackTrace();
}
timerTask = new TimerTask() {
Runnable updateUI = new Runnable(怎么给录音降噪处理