Android中AudioManager之StreamType

文章讲述了作者在项目中遇到的问题,即在插入耳机后来电铃声不再通过扬声器播放,通过查阅AudioManager的音频流类型,发现将音频流类型设置为STREAM_RING可以确保在任何情况下铃声都通过扬声器播放。
摘要由CSDN通过智能技术生成

        近期工作中,突然发现之前一直使用的来电铃声播放类在插入耳机后,铃声会从耳机中播放,而正常的逻辑是需要任何时候来电铃声都应由扬声器来播放的,故此回顾了下AudioManager的音频流类型知识,解决了此问题。(在此做个记录,避免若干时间后遗忘,也希望看到的朋友别踩坑了)~

OK,先看下之前的来电铃声播放类关键代码。如下,用的SoundPool来做播放:


/**
 * 来电铃声播放控制
 */
public class IncomeRingUtil {

    ...

    /**
     * 初始化,在app启动时调用
     *
     * @param context
     */
    public void init(Context context) {
        if (Build.VERSION.SDK_INT >= 21) {
            SoundPool.Builder builder = new SoundPool.Builder();
            builder.setMaxStreams(1);
            AudioAttributes.Builder attrBuilder = new AudioAttributes.Builder();
            attrBuilder.setLegacyStreamType(AudioManager.STREAM_MUSIC);
            builder.setAudioAttributes(attrBuilder.build());
            soundPool = builder.build();
        } else {
            soundPool = new SoundPool(1, AudioManager.STREAM_MUSIC, 5);
        }
        lastStreamId = soundPool.load(context, R.raw.phone_ring, 1);
    }

  ...

}

以前呢,该代码一直运行在特制的Android终端上,没有接耳机使用的情况,所以一直相安无事。后来放到手机上跑,插入耳机后,声音就跑到耳机里了。查了一圈资料,思路一直是想在播放时设置成免提应该就好了,然并卵,没有任何效果。

最后,发现仅仅只需简单修改下StreamType就完事了~

AudioManager中音频流的类型
  • STREAM_MUSIC:用于音乐播放的音频流。
  • STREAM_SYSTEM:用于系统声音的音频流。
  • STREAM_RING:用于电话铃声的音频流。
  • STREAM_VOICE_CALL:用于电话通话的音频流。
  • STREAM_ALARM:用于警报的音频流。
  • STREAM_NOTIFICATION:用于通知的音频流。
  • STREAM_BLUETOOTH_SCO:用于连接到蓝牙电话时的手机音频流。
  • STREAM_SYSTEM_ENFORCED:在某些国家实施的系统声音的音频流。
  • STREAM_DTMF:DTMF音调的音频流。
  • STREAM_TTS:文本到语音转换(TTS)的音频流。

 其中,只有把类型设置成STREAM_VOICE_CALL,才可以通过setSpeakerphoneOn()实现免提/耳机等通道切换;

STREAM_SYSTEMSTREAM_MUSIC这两个类型,插上耳机后声音会自动从耳机中播放;

STREAM_RINGSTREAM_ALARMSTREAM_NOTIFICATION这几个类型,插上耳机声音也依旧会从扬声器中播放;

剩余几个类型如其字面意思理解即可!

所以,要想实现任意时候来电铃声都从扬声器中播放,直接在初始化SoundPool时将音频流类型设置成STREAM_RINGSTREAM_ALARMSTREAM_NOTIFICATION中的一种即可修改后的完成代码如下:

import android.content.Context;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.SoundPool;
import android.os.Build;


/**
 * 来电铃声播放控制
 */
public class IncomeRingUtil {
    private static SoundPool soundPool;
    private int lastStreamId;

    private IncomeRingUtil() {
    }

    private static IncomeRingUtil mInstance = null;

    public static IncomeRingUtil getInstance() {
        if (mInstance == null) {
            synchronized (IncomeRingUtil.class) {
                if (mInstance == null) {
                    mInstance = new IncomeRingUtil();
                }
            }
        }
        return mInstance;
    }

    /**
     * 初始化,在app启动时调用
     * 声音流类型设置为铃声类型:STREAM_RING,这样在接入耳机的情况下来电铃声也会通过扬声器播放
     *
     * @param context
     */
    public void init(Context context) {
        if (Build.VERSION.SDK_INT >= 21) {
            SoundPool.Builder builder = new SoundPool.Builder();
            builder.setMaxStreams(1);
            AudioAttributes.Builder attrBuilder = new AudioAttributes.Builder();
            attrBuilder.setLegacyStreamType(AudioManager.STREAM_RING);
            builder.setAudioAttributes(attrBuilder.build());
            soundPool = builder.build();
        } else {
            soundPool = new SoundPool(1, AudioManager.STREAM_RING, 5);
        }
        lastStreamId = soundPool.load(context, R.raw.phone_ring, 1);
    }

    /**
     * 播放来电铃声
     */
    public void playSound() {
        //每次播放时,先停止上次的音频播放
        stopLastStreamId();
        lastStreamId = poolPlay();
        //播放失败时,重新设置streamId为1
        if (lastStreamId == 0) {
            lastStreamId = 1;
            lastStreamId = poolPlay();
        }
    }

    private int poolPlay() {
        //离线推送拉起app来电界面时,等待资源加载完成再播放,否则会没声音
        soundPool.setOnLoadCompleteListener(new SoundPool.OnLoadCompleteListener() {
            @Override
            public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
                lastStreamId = soundPool.play(sampleId, 1, 1, 0, -1, 1);
            }
        });
        return soundPool.play(lastStreamId, 1, 1, 0, -1, 1);
    }

    /**
     * 停止来电铃声播放
     */
    public void stopSound() {
        soundPool.stop(lastStreamId);
    }

    /**
     * 停止上一次播放
     */
    private void stopLastStreamId() {
        if (lastStreamId != -1) {
            soundPool.stop(lastStreamId);
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值