控制音量和播放

良好的用户体验是可预测的。 如果您的应用程式播放媒体,您的使用者必须使用装置,蓝牙耳机或耳机的硬体或软体音量控制来控制应用程式的音量。

类似地,在适当和可用的情况下,播放,停止,暂停,跳过和先前的媒体回放键应当对于由应用使用的音频流执行它们各自的动作。

标识要使用的音频流

创建可预测的音频体验的第一步是了解您的应用将使用哪个音频流。

Android维护一个单独的音频流,用于播放音乐,闹钟,通知,来电铃声,系统声音,通话音量和DTMF铃声。 这主要是为了允许用户独立地控制每个流的音量。

大多数这些流仅限于系统事件,因此除非您的应用程序是替换闹钟,否则您几乎肯定会使用STREAM_MUSIC流播放您的音频。

使用硬件音量键控制音量

默认情况下,按音量控制可修改Activity音频流的音量。如果您的应用程式目前没有播放任何内容,按下音量键即可调整铃声音量。

如果你有一个游戏或音乐应用程序,那么当用户点击音量键,他们想要控制游戏或音乐的音量,即使他们当前在歌曲之间或没有音乐在当前游戏位置。

你可能会试着尝试监听音量键按下并修改音频流的音量。不要慌, Android提供了方便的setVolumeControlStream()方法来将音量键降到您指定的音频流。

确定应用程序将使用的音频流后,应将其设置为音频流目标。您应该在应用程序的生命周期中提前进行此调用 - 因为您只需在Activity生命周期中调用一次,通常应在onCreate()方法(控制您的媒体的Activity或Fragment)中调用它。这确保了只要应用程序可见,音量控制功能就像用户期望的那样。

setVolumeControlStream(AudioManager.STREAM_MUSIC);

从这一点开始,只要目标Activity或Fragment可见,按设备上的音量键就会影响您指定的音频流(在本例中为“音乐”)。

使用硬件播放控制键控制音频播放

媒体播放按钮,如播放,暂停,停止,跳过和上一个在某些手机和许多连接或无线耳机可用。每当用户按下这些硬件键之一时,系统使用ACTION_MEDIA_BUTTON操作广播一个Intent。

要响应媒体按钮点击,您需要在您的清单中注册一个BroadcastReceiver,监听此操作广播,如下所示。

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

接收器实现本身需要提取哪个键被按下来引起广播。 Intent在EXTRA_KEY_EVENT键下包括此键,而KeyEvent类包括表示每个可能的媒体按钮的列表KEYCODE_MEDIA_ *静态常量,例如KEYCODE_MEDIA_PLAY_PAUSE和KEYCODE_MEDIA_NEXT。

以下代码片段显示如何提取按下的媒体按钮,并相应地影响媒体播放。

public class RemoteControlReceiver extends BroadcastReceiver {@Overridepublic 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注册和注销媒体按钮事件接收器。注册后,您的广播接收器是所有媒体按钮广播的专属接收器。

AudioManager am = mContext.getSystemService(Context.AUDIO_SERVICE);
//...// Start listening for button presses
am.registerMediaButtonEventReceiver(RemoteControlReceiver);
//...// Stop listening for button presses
am.unregisterMediaButtonEventReceiver(RemoteControlReceiver);

通常,当应用程序变为不活动或不可见时(例如在onStop()回调期间),应取消注册大多数接收者。然而,对于媒体播放应用程序来说并不简单,事实上,当应用程序不可见且无法通过屏幕上的用户界面控制时,响应媒体播放按钮是最重要的。

更好的方法是在应用程序获取并丢失音频焦点时注册和取消注册媒体按钮事件接收器。这将在下面详细介绍。

管理音频焦点

有多个应用程序可能播放音频,重要的是要考虑他们应该如何交互。为了避免每个音乐应用程序同时播放,Android使用音频焦点来控制音频播放 - 只有拥有音频焦点的应用程序才能播放音频。

在您的应用程序开始播放音频之前,应该请求并接收音频焦点。同样,它应该知道如何监听音频焦点的丢失,并在发生这种情况时适当地做出反应。

请求音频焦点

在您的应用开始播放任何音频之前,它应该保留将使用的流的音频焦点。这是通过调用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()。这会通知系统您不再需要焦点和注销相关联的AudioManager.OnAudioFocusChangeListener。在放弃瞬态焦点的情况下,这允许任何中断的应用程序继续播放。

// Abandon audio focus when playback complete
am.abandonAudioFocus(afChangeListener);

当请求瞬态音频焦点时,您有一个附加选项:是否要启用“低音”。通常,当良好的音频应用程序失去音频焦点时,它立即使其播放静音。通过请求一个允许回避的暂时音频焦点,你告诉其他音频应用程序它们可以接受他们继续播放,只要他们降低音量,直到焦点回到他们。

// 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.
}

低音尤其适用于间歇性使用音频流的应用程序,例如用于可听见的驾驶方向。

每当另一个应用程序请求音频焦点如上所述,其永久和瞬态(有或没有支持低音)之间的选择音频焦点由您在请求焦点时注册的侦听器接收。

处理音频焦点的丢失

如果您的应用程序可以请求音频焦点,那么当其他应用程序请求焦点时,它会反过来失去焦点。您的应用程序如何响应音频焦点的丢失取决于丢失的方式。

您请求音频焦点时注册的音频焦点更改侦听器的onAudioFocusChange()回调方法接收到描述焦点更改事件的参数。具体来说,可能的聚焦丢失事件镜像来自前一部分的聚焦请求类型 - 永久丢失,瞬时丢失和允许具有回避的瞬态。

一般来说,暂时的(临时的)音频焦点的丢失应导致您的应用程序使它的音频流静音,否则保持相同的状态。您应该继续监视音频焦点的变化,并准备在恢复焦点后暂停播放。

如果音频焦点丢失是永久性的,假设另一个应用程序现在正用于听音频,您的应用程序应该有效地结束自己。实际上,这意味着停止播放,删除媒体按钮侦听器 - 允许新的音频播放器专门处理这些事件 - 并放弃您的音频焦点。此时,您需要在恢复播放音频之前需要执行用户操作(在应用程序中按下播放)。

在下面的代码片段中,如果音频丢失是暂时的,我们暂停播放我们的媒体播放器对象,并在我们恢复焦点后重新开始播放。如果丢失是永久性的,它将取消注册我们的媒体按钮事件接收器,并停止监视音频焦点更改。

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}}};

在瞬时丢失音频焦点的情况下,允许duck(回避),而不是暂停回放。

如何Duck

低音是降低音频流输出音量的过程,使来自另一个应用程序的瞬态音频更容易听到,而不会完全中断您自己的应用程序的音频。

在以下代码段中,当我们暂时失去焦点时,降低媒体播放器对象上的音量,然后在我们重新获得焦点时将其返回到上一级。

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}}
};

丢失音频焦点是最重要的广播,但不是唯一的。 系统广播多个Intent,以提醒您用户的音频体验的变化。

处理音频输出硬件

当用户从他们的Android设备享受音频时,用户有很多选择。大多数设备都有内置扬声器,有线耳机的耳机插孔,许多设备还具有蓝牙连接和支持A2DP音频。

检查正在使用的硬件

您的应用程序的行为可能会受到输出路由到的硬件的影响。

您可以查询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_AUDIO_BECOMING_NOISY Intent。这是一个好的习惯,注册一个BroadcastReceiver监听这个Intent,无论你在播放音频。在音乐播放器的情况下,用户通常期望暂停播放,而对于游戏,可以选择显着降低音量。

private class NoisyAudioStreamReceiver extends BroadcastReceiver {@Overridepublic 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);
}

Android播放音频之按钮控制相关推荐

  1. 基于swiper使用vue-awesome-swiper 实现鼠标移入暂停自动播放、左右按钮控制前进后退、常见避坑、API中文文档地址

    vue 中使用swiper/vue-awesome-swiper 鼠标移入暂停自动播放,左右按钮控制前进后退,常见避坑 swiper对应vue-awesome-swiper版本会带来很多坑点,推荐下面 ...

  2. android: 播放音频

    在 Android 中播放音频文件一般都是使用 MediaPlayer 类来实现的,它对多种格式的音 频文件提供了非常全面的控制方法,从而使得播放音乐的工作变得十分简单.下表列出了 MediaPlay ...

  3. android怎么播放音频,Android播放音频的两种方式

    一种使用MediaPlayer,使用这种方式通常是播放比较长的音频,如游戏中的背景音乐. 代码如下: private MediaPlayer mPlayer = null; mPlayer = Med ...

  4. android 播放声音文件,AudioPlayerDemo android 播放音频文件

    [实例简介] 该PCM 参数如下: rm-channels_2 frame_4096(纯PCM数据每帧长度4096) freq_44100 bits_16 480X234_1700kbps.rm是源音 ...

  5. Android播放音频到耳机,Android音乐播放模式切换-外放、听筒、耳机

    初始化音频管理器 /** * 初始化音频管理器 */ private void initAudioManager() { audioManager = (AudioManager) context.g ...

  6. Android播放音频工具类

    播放完毕重置mediaplayer,播放完毕才能播放下一次.播放小音频建议使用soundpool(音频大小不超过900k) public class PlayMusicUtils {private s ...

  7. Ffmpeg + OpenSL ES + Android 播放音频

    一 拿到音频的 路径 ,然后根据 jni 发送数据到C语言的方法 然后,开始解析 avcodec_register_all();avformat_network_init();pPlayer-> ...

  8. html按钮控制播放暂停,外部按钮控制video视频的播放暂停

    .stop { background-color: #FF2D2D; width: 80px; height: 30px; line-height: 30px; text-align: center; ...

  9. Android多媒体功能开发(6)——使用MediaPlayer类播放音频

    Android播放音频资源主要有两个类:MediaPlayer和SoundPool. MediaPlayer用于实现对一个音频的播放控制,侧重于启动.停止.暂停.位置控制等操作.不支持同时播放多个音频 ...

最新文章

  1. 科研与爱情选谁?中科院教授教你平衡!
  2. NeurIPS2021 注意事项以及往年投稿、接受率回顾
  3. Tips_发送请求时添加一个随机数参数,让浏览器每次都重新发请求到服务器
  4. javascript闭包-全局变量与局部变量
  5. Ehcache 缓存
  6. Spring Boot微信点餐——实战开发DAO层
  7. 学习笔记之-MySql高级之sql优化
  8. 【Statistics】10g中 Automatic Statistics Collection维护窗口之探查
  9. UITableView+UITableViewStyleGrouped 处理section之间间隙
  10. webpack项目篇(六十六):react 全家桶 和 webpack 开发 h5 商城项目的整体思路
  11. chrome/firefox插件ie tab,解决无法使用网银的问题
  12. UI设计课EDC研究所1期 Part 9 -“特殊的字体”
  13. springboot版的微信公众号,订阅号
  14. sass实现前端页面基础框架布局
  15. 设置低电平有效,即取反
  16. 通用计算机指令,计算机移位指令
  17. 03、STM8程序下载方法
  18. Android 接入阿里实人认证
  19. 西门子三菱台达PLC读取国网DLT645协议电表数据方案
  20. Firefly-rk3288 开发板Linux系统编译

热门文章

  1. java 生成字体文件,java使用itext生成pdf文件-设置字体,itextpdf,import com.l
  2. 华为内部深度解读,关于5G发展的28个核心问题
  3. java远程文件下载到本地
  4. foobar 2000适合用来听无损音乐的原因
  5. VMware Workstation 下载和安装
  6. 【十一、wordpress优化之六:CDN加速,以腾讯CDN为例】2021最详细wordpress博客建站教程(2021.03.03更新)
  7. 相对论中的光速c不变,这么讲!你总能理解了吧!
  8. ...... 处有未经处理的异常: 0xC0000005: 读取位置 0xcccccccc 时发生访问冲突
  9. 利用计算机形考试二,国开电大21年计算机应用基础形考任务二答案
  10. 友友车友软件 android,友友车友模拟学车软件2013 v4.0最新版(图文)