原文地址:http://android.xsoftlab.net/training/managing-audio/index.html

引言

如果APP需要播放音频,允许用户可以控制音频的播放状态是很重要的一点。为了保证有极佳的用户体验,还有很重要的一点就是,APP需要管理音频的焦点来确保不会有多个APP同时播放音频。

在稍后的课程中,将会学习如何使APP响应物理按键的按下事件,这需要在播放音频时,请求音频的焦点,以及需要适当的响应由系统或者其它应用程序引起的音频焦点改变。

控制APP的音量以及播放状态

一个良好的用户体验是可预测的。如果APP可以播放媒体,那么用户可以通过设备上的物理按键或者虚拟按键来控制APP的音量是非常重要的一点。比如蓝牙耳机或者头戴式耳机。

同样,在适当的情况下,通过APP所使用的音频流基础之上来控制播放,停止,暂停,跳过,以及原始的媒体播放按键都应该执行其各自的行为和功能。

识别所用的音频流

创建可预测的音频体验的第一步是理解APP将使用的音频流。

Android对播放音乐、闹钟、通知以及电话铃声、系统声音、呼叫音量和DTMF铃声都维护了单独的音频流。这么做主要是允许用户可以控制每个流各自的音频。

大部分流都会受限于系统事件,所以除非APP是个闹钟应用,否则,几乎可以确定APP播放音频所使用的就是STREAM_MUSIC流。

使用物理按键控制APP声音的音量

默认情况下,按下音量键会修改当前正在活动的音频流的音量。如果APP当前没有播放任何东西,按下音量键只会调整铃声的音量。

如果正在使用一款游戏APP或者音乐APP,那么当用户按下音量键的时候调整音量是极好的,因为用户想要控制游戏或者音乐的音量,即使现在在两首歌之间或者当前的游戏界面上没有播放音乐。

你可能想试着监听音量按键的按下事件,然后修改音频流的音量。忍住这股冲动吧。Android提供了更方便的setVolumeControlStream()方法来让音量键直接用于到你所指定的音频流。

如果已经确认使用的音频流类型,你应该将其设置为音量流的目标。你应该确保这个调用在APP的生命周期之前,因为只需要在Activity的生命周期中调用一次,你应该在具有代表性的方法中调用它,比如onCreate()方法。这可以确保每当APP处于可见状态时,音量控制功能可用更符合用户的期望。

setVolumeControlStream(AudioManager.STREAM_MUSIC);

从这点往后,每当目标activity或者fragment可见时,按下设备上的音量键会影响你所指定的音频流(在这个例子中是”音乐”)。

使用物理播放控制键来控制APP的音频播放

媒体播放按钮,如播放、暂停、停止、跳跃,和以前的一些手机和许多有线连接或无线连接的耳机。当用户按下了其中的某个键时,系统会广播一个ACTION_MEDIA_BUTTON行为的意图。

为了响应媒体按钮的点击事件,你需要在清单文件中注册一个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.}}}
}

因为可能存在多个程序想要监听媒体按钮的按下事件,所以APP应该接收媒体按钮按下事件时,你还必须通过编程来进行动态的控制。

下面的代码可以直接应用到APP中去,它可以通过AudioManager来注册与解注媒体按钮事件接收器。当被注册后,广播接收器会专门接收所有的媒体按钮广播。

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

从通常情况上讲,APP应该在不活动时或者不可见时解注其它的接收器(比如onStop()回调方法)。然而,对媒体播放APP来说没有那么简单,实际上,当程序不可见以及不能够屏幕上的UI来控制媒体播放时,这时,通过广播响应媒体播放按钮事件就非常重要了。

更进一步的方法就是当程序获取或者失去音频焦点时注册或者解注媒体按钮事件接收器。这些知识将会在下节课详细讨论。

Android官方开发文档Training系列课程中文版:管理音频播放之控制APP的音量与播放相关推荐

  1. Android官方开发文档Training系列课程中文版:调用相机之控制相机

    原文地址:http://android.xsoftlab.net/training/camera/cameradirect.html 在这节课,我们会讨论如何使用Android框架API来直接控制相机 ...

  2. Android官方开发文档Training系列课程中文版:目录

    原文地址 : http://android.xsoftlab.net/training/index.html 引言 在翻译了一篇安卓的官方文档之后,我觉得应该做一件事情,就是把安卓的整篇训练课程全部翻 ...

  3. Android官方开发文档Training系列课程中文版:创建自定义View之View的创建

    原文地址:http://android.xsoftlab.net/training/custom-views/index.html 引言 Android框架含有大量的View类,这些类用来显示各式各样 ...

  4. Android官方开发文档Training系列课程中文版:OpenGL绘图之图形绘制

    原文地址:http://android.xsoftlab.net/training/graphics/opengl/draw.html 如果你还不清楚如何定义图形及坐标系统,请移步:Android官方 ...

  5. Android官方开发文档Training系列课程中文版:使用Fragment构建动态UI之Fragment创建

    原文地址:http://android.xsoftlab.net/training/basics/fragments/index.html 导言 为了在Android中创建动态的多面板用户界面,你需要 ...

  6. Android官方开发文档Training系列课程中文版:打印内容之图像打印

    原文地址:http://android.xsoftlab.net/training/printing/index.html 引言 Android用户会很频繁的浏览设备上的内容,但是有部分情况例外,当屏 ...

  7. Android官方开发文档Training系列课程中文版:Android的安全建议 .

    转载:http://blog.csdn.net/sahadev_/article/details/52949855 原文地址:http://android.xsoftlab.net/training/ ...

  8. Android官方开发文档Training系列课程中文版:Android的安全建议

    原文地址:http://android.xsoftlab.net/training/articles/security-tips.html Android系统内置的安全策略可以有效的降低应用程序的安全 ...

  9. Android官方开发文档Training系列课程中文版:APP的内存管理

    写在开头的话: 如果有同学对Android性能比较关注的,可以阅读这篇文章:Android性能优化建议 原文地址:http://android.xsoftlab.net/training/articl ...

最新文章

  1. java问题:错误: 找不到或无法加载主类 HelloWorld
  2. C++学习路线(最全资源整合)
  3. 【bzoj4399】魔法少女LJJ 并查集+权值线段树合并
  4. 去苹果浏览器默认样式
  5. HexorBase 登陆、执行语句、数据库帐号密码破解
  6. web前端从无到有html标签,.NET MVC 扩展 HtmlHelper 从无到有(一)
  7. kafka1.0+ 集群搭建
  8. 文本主题发现(一)-- 数据预处理
  9. 最小公倍数和最大公约数的简洁写法
  10. 初学JAVA随记——8bit(1byte)的取值范围是+127到—128
  11. python scipy.signal 包络_python scipy signal.freqz用法及代码示例
  12. VisualStudio2017编写masm32汇编程序以及语法高亮配置
  13. ps和计算机一样吗,ps分辨率和电脑显示不一样怎么办
  14. OpenCV:图像锐化
  15. linux 学习感悟
  16. 图灵测试其实已经过时了
  17. 安装mysq的时候执行mysqld --initialize --console时候报错:can not create directory data文件夹需要把分隔符改成反方向
  18. 青春,让人想念,却再也闻不到了
  19. 记一次系统重装后电脑的优化设置
  20. 什么是ANC主动降噪技术?

热门文章

  1. Android 如何退出整个应用程序?
  2. ​CPU单挑到群架发展史
  3. C++ —— C++类
  4. mysql kafka binlog_为什么使用kafka处理mysql binlog?
  5. 在统计学中参数的含义是指_《统计学》名词解释及公式
  6. JSX详解React的事件绑定事件参数的传递
  7. 1+X web中级 Laravel学习笔记——blade模版
  8. 九、ES6的箭头函数
  9. LeetCode 290. 单词规律(哈希)
  10. LeetCode 289. 生命游戏(位运算)