Android音频播放配置

本文介绍了在Android中如何使用音量键控制app播放音量,并详细讲解了如何注册多媒体按钮接收者以及如何处理音频焦点。在播放音频前,app需要请求音频焦点,根据返回值决定是否播放。当焦点丢失时,app需要根据情况暂停播放或完全停止,并适时调整注册的媒体按钮接收者和音频焦点监听器。此外,还涉及了如何判断音频输出设备。

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

Android系统封装了许多音频流类型,如多媒体,铃声,闹钟等,一般来说音频播放app使用的是STREAM_MUSIC流。

一、使用音量键控制app的播放音量:

setVolumeControlStream(AudioManager.STREAM_MUSIC);

二、使用耳机的实体按键控制app音频的播放(play,pause,stop,skip,previous):
当用户按下其中一个按键时,系统会发出广播,action为 ACTION_MEDIA_BUTTON,
所以为了让你的app能够相应相应的广播,应该在注册一个广播接收者,如:

<receiver android:name=".RemoteControlReceiver">
    <intent-filter>
        <action android:name="android.intent.action.MEDIA_BUTTON" />
    </intent-filter>
</receiver>


广播接收者必须能对不同的按键做出正确的响应,具体是哪个按键按下的信息包含在了广播Intent的 EXTRA_KEY_EVENT键值对中,
可以从该键值对中获取相应信息,如:

public class RemoteControlReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (Intent.ACTION_MEDIA_BUTTON.equals(intent.getAction())) {
            KeyEvent event = (KeyEvent)intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
            if (KeyEvent.KEYCODE_MEDIA_PLAY == event.getKeyCode()) {
                // Handle key press.
            }
        }
    }
}

三、注册多媒体按钮接收者:

AudioManager am = mContext.getSystemService(Context.AUDIO_SERVICE);
...

// Start listening for button presses
am.registerMediaButtonEventReceiver(RemoteControlReceiver);
...

// Stop listening for button presses
am.unregisterMediaButtonEventReceiver(RemoteControlReceiver);


四、音频焦点的获取

为了防止多个音频播放app同时播放音频,Android使用音频焦点(Audio Focus)机制,只有拥有音频焦点的app才能播放音频。

请求音频焦点:
在你的app开始播放前,需要请求对应音频流的音频焦点,可以调用requestAudioFocus()方法,如果返回值为 AUDIOFOCUS_REQUEST_GRANTED,
则请求成功,可以指定请求的音频焦点是暂时的或永久的。如请求永久音频焦点:

AudioManager am = mContext.getSystemService(Context.AUDIO_SERVICE);
...

// Request audio focus for playback
int result = am.requestAudioFocus(afChangeListener,
                                 // Use the music stream.
                                 AudioManager.STREAM_MUSIC,
                                 // Request permanent focus.
                                 AudioManager.AUDIOFOCUS_GAIN);

if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
    am.registerMediaButtonEventReceiver(RemoteControlReceiver);
    // Start playback.
}

当播放结束的时候记得调用abandonAudioFocus()方法,这个方法告诉系统你不在使用音频焦点了,如:
// Abandon audio focus when playback complete
am.abandonAudioFocus(afChangeListener);

注:afChangeListener是 AudioManager.OnAudioFocusChangeListener类.

在请求暂时的音频焦点时,可以选择是否激活"ducking"功能,通常来说,当一个app失去音频焦点时,应该停止音频的播放,
而通过请求允许"ducking"的暂时焦点,可以允许app在失去焦点只时减小音量,如:

// Request audio focus for playback
int result = am.requestAudioFocus(afChangeListener,
                             // Use the music stream.
                             AudioManager.STREAM_MUSIC,
                             // Request permanent focus.
                             AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);

if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
    // Start playback.
}


五、处理音频焦点的丢失

焦点丢失可分为暂时焦点丢失和永久焦点丢失,当只是暂时失去了焦点时,我们应该暂停播放,这样当再次获得焦点时可以继续播放,

如果是永久的失去了焦点,说明用户开启了其他的app进行音频播放,这时就应该取消注册的媒体按钮接受者和音频焦点的监听,如:

AudioManager.OnAudioFocusChangeListener afChangeListener =
    new AudioManager.OnAudioFocusChangeListener() {
        public void onAudioFocusChange(int focusChange) {
            if (focusChange == AUDIOFOCUS_LOSS_TRANSIENT) {
                // Pause playback
            } else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {
                // Resume playback
            } else if (focusChange == AudioManager.AUDIOFOCUS_LOSS) {
                am.unregisterMediaButtonEventReceiver(RemoteControlReceiver);
                am.abandonAudioFocus(afChangeListener);
                // Stop playback
            }
        }
    };

当获得的焦点具有"ducking"功能,则当失去暂时焦点时可以只是降低音量,如:

OnAudioFocusChangeListener afChangeListener = new OnAudioFocusChangeListener() {
    public void onAudioFocusChange(int focusChange) {
        if (focusChange == AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK) {
            // Lower the volume
        } else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {
            // Raise it back to normal
        }
    }
};

六、协调音频输出的硬件(内置扬声器,耳机插孔,蓝牙等):

判断音频输出到哪个硬件上,通过AudioManager,如:

if (isBluetoothA2dpOn()) {
    // Adjust output for Bluetooth.
} else if (isSpeakerphoneOn()) {
    // Adjust output for Speakerphone.
} else if (isWiredHeadsetOn()) {
    // Adjust output for headsets
} else {
    // If audio plays and noone can hear it, is it still playing?
}

处理音频输出硬件的改变:当耳机拔出,蓝牙不再连接时,音频自动输出到内置扬声器上,如果
扬声器的音量很大,就可能造成意外的噪音,此时系统会发出action为 ACTION_AUDIO_BECOMING_NOISY
的广播,如果能够注册一个广播接受者对该广播进行处理,如暂停播放,会提高用户体验,如:

private class NoisyAudioStreamReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (AudioManager.ACTION_AUDIO_BECOMING_NOISY.equals(intent.getAction())) {
            // Pause the playback
        }
    }
}

private IntentFilter intentFilter = new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY);

private void startPlayback() {
    registerReceiver(myNoisyAudioStreamReceiver(), intentFilter);
}

private void stopPlayback() {
    unregisterReceiver(myNoisyAudioStreamReceiver);
}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值