作者:郭孝星
微博:郭孝星的新浪微博
邮箱:allenwells@163.com
博客:http://blog.csdn.net/allenwells
Github:https://github.com/AllenWells

【Android应用开发技术:媒体开发】章节列表

Android为播放音乐、闹铃、通知铃、来电声音、系统声音、打电话声音和DTMF频道都分别维护了一个隔离的音频流,这是我们能够控制不同音频的前提,这其中大多数的音频流都是被系统限制的,不能胡乱使用。

一 音频控制

默认情况下,按下音量控制键会调节当前被激活的音频流,如果我们的App没有播放任何声音,则会调节闹铃的声音。如果是一个游戏或音乐程序,则需要不管是否正在播放歌曲或者游戏目前是否发出声音,按硬件的音量键都会有相应的音量调节。

Android提供了setVolumeControlStream()的方法来直接控制指定的音频流,我们需要在鉴别出App使用了哪个音频流之后,在Activity或Fragment创建的时候就设置音量控制,这样保证App是否可见,音频功能都能正常工作,如下所示:

setVolumeControlStream(AudioManager.STREAM_MUSIC);

常见的媒体播放控制如下所示:

  • play
  • pause
  • stop
  • skip
  • previous

当我们在软件或者硬件(耳麦线控等)进行上述操作时,系统都会广播一个ACTION_MEDIA_BUTTON的Intent,为了响应那些操作,需要在AndroidManifest.xml文件中注册一个BroadcastReceiver,如下所示:

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

Receiver需要判断这个广播是来自哪个按钮的操作,Intent在 EXTRA_KEY_EVENT 中包含了KEY的信息,同样KeyEvent类包含了一列 KEYCODE_MEDIA_ 的静态变量来表示不同的媒体按钮,如下所示:

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

因为可能有多个程序都同样监听了哪些控制按钮,那么必须在代码中特意控制当前哪个Receiver会进行响应,就就是需要进行适时的注册监听和取消监听,如下所示:

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来控制音频播放,只有获得Audio Focus的App才能播放音频,App 播放音频的过程如下所示:

  • 发出请求
  • 接受请求
  • 音频焦点锁定

2.1 请求获取音频焦点

在App播放音频之前。我们需要获取它将要使用的音频流的音频焦点。通过使用requsetAudioFocus()方法来获取想要的音频焦点,如果请求成功,该方法会返回AUDIOFOCUS_REQUEST_GRANTED。

请求焦点的时候,我们需要确定请求的是哪种焦点类型,如下所示:

  • 短暂的焦点锁定:当期待播放一个短暂的音频的时候,例如,播放导航提示。
  • 开启Ducking的短暂焦点锁定:当请求短暂音频焦点的时候,我们可以选择是否开启Ducking。

Ducking是一个特殊的机制使得允许音频间歇性的短暂播放。 通常情况下,一个好的App在失去音频焦点的时候它会立即保持安静。如果我们选择在请求短暂音频焦点的时候开启了Ducking,那意味着其它App可以继续播放,仅仅是在这一刻降低自己的音量,在短暂重新获取到音频焦点后恢复正常音量。

也就是说,不用理会这个请求短暂焦点的请求,这并不会导致目前在播放的音频受到牵制,比如在播放音乐的时候突然出现一个短暂的短信提示声音,这个时候仅仅是把播放歌曲的音量暂时调低,好让短信声能够让用户听到,之后立马恢复正常播放。

  • 永久的焦点锁定:当计划播放可预期到的较长的音频的时候,例如播放音乐。

举例1

在播放音乐的时候请求永久的音频焦点,如下所示:

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的监听。在释放短暂音频焦点的情况下,这会允许任何被打断的App继续播放。

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

举例2

开启Ducking的短暂焦点锁定,如下所示:

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

2.2 处理失去音频焦点

在音频焦点的监听器里面,当接受到描述焦点改变的事件时会触发onAudioFocusChange()回调方法,对于失去焦点有三种类型,如下所示:

  • 短暂的失去焦点:通常在失去焦点的情况下,我们会暂停当前音频的播放或者降低音量,同时需要准备在重新获取焦点之后恢复播放。
  • 开启Ducking的短暂的失去焦点:Ducking是一个特殊的机制使得允许音频间歇性的短暂播放。在Ducking的情况下,正常播放的歌曲会降低音量来凸显**这个短暂的音频声音,这样既让这个短暂的声音比较突出,又不至于打断正常的声音。
  • 永久的失去焦点:假设另外一个程序开始播放音乐,那么我们的程序就应该有效的结束自己。常见的做法是:移除Button监听,允许新的音频播放器独占监听那些按钮时间,并且放弃自己的音频焦点,这种情况下,重新播放你的音频之前。我们需要确保用户重新点击了App的播放按钮。

举例1

短暂的失去焦点,如下所示:

OnAudioFocusChangeListener afChangeListener = new 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}}
};

举例2

播放器在暂时失去焦点时降低音量,并在重新获得音频焦点之后恢复原来的音量,如下所示:

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

三 音频设备

用户在播放音乐时有多个选择,可以使用内置的扬声器,有线耳机或者A2DP蓝牙耳机。

A2DP(Advanced Audio Distribution Profile)即蓝牙音频传输模型协定,A2DP是能够采用耳机内的芯片来堆栈数据,达到声音的高清晰度。有A2DP的耳机就是蓝牙立体声耳机。声音能达到44.1kHz,一般的耳机只能达到8kHz。如果手机支持蓝牙,只要装载A2DP协议,就能使用A2DP耳机了。

3.1 检测音频输出设备

选择音频输出设备会影响App的行为,可以使用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?
}

2.2 处理音频设备的改变

当有线耳机被拔出或者蓝牙设备断开连接的时候,音频流会自动输出到内置的扬声器上。假设之前播放声音很大,这个时候突然转到扬声器播放会显得非常嘈杂。Android系统会在那种事件发生时会广播带有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. Android网络开发技术实战详解

    <Android网络开发技术实战详解> 基本信息 作者: 朱桂英 丛书名: Android移动开发技术丛书 出版社:电子工业出版社 ISBN:9787121173493 上架时间:2012 ...

  2. 【Android应用开发技术:用户界面】界面导航设计

    作者:郭孝星 微博:郭孝星的新浪微博 邮箱:allenwells@163.com 博客:http://blog.csdn.net/allenwells Github:https://github.co ...

  3. Android多媒体开发技术

    周末参加了线下安卓巴士论坛组织的"安卓开发者的修炼之道",几位嘉宾分享的内容都很赞.没时间整理文字版,直接分享嘉宾的PPT了. 第二位嘉宾何俊林,前爱奇艺多媒体开发,据说活动现场很 ...

  4. Android App 开发技术图谱

    Android App 开发技术图谱 转载请注明出处:www.leoyanblog.com 本文出自 LeoYan 的博客 本文同步发表于我的微信公众号,扫一扫文章底部的二维码或在微信搜索 LeoYa ...

  5. linux内核epub,Android底层开发技术实战详解——内核、移植和驱动(第2版)[EPUB][MOBI][AZW3][42.33MB]...

    内容简介 本书从底层原理开始讲起,结合真实的案例向读者详细介绍了Android内核.移植和驱动开发的整个流程.全书分为21章,依次讲解驱动移植的必要性, Goldfish.OMAP内核和驱动解析,显示 ...

  6. 【Android FFMPEG 开发】FFMPEG 音频重采样 ( 初始化音频重采样上下文 SwrContext | 计算音频延迟 | 计算输出样本个数 | 音频重采样 swr_convert )

    文章目录 I . FFMPEG 播放视频流程 II . FFMPEG 音频重采样流程 III . FFMPEG 音频重采样 IV . FFMPEG 初始化音频重采样上下文 SwrContext V . ...

  7. 聊聊真实的 Android TV 开发技术栈

    智能电视越来越普及了,华为说四月发布智能电视跳票了,一加也说今后要布局智能电视,在智能电视方向,小米已经算是先驱了.但是还有不少开发把智能电视简单的理解成手机屏幕的放大,其实这两者并不一样. 一.序 ...

  8. Android平台开发技术大作业:数独游戏

    目录 <Andriod平台应用与开发技术实验> PAGEREF _Toc24643 \h 1 实验报告 PAGEREF _Toc15437 \h 1 第一章引言 - 1 - 第二章调研阶段 ...

  9. Android SDK开发技术分享

    最近在工作中负责统一支付平台的SDK开发部分,就此总结下SDK开发的技术点.注意事项.与普通app开发的差别,作为自我总结,也作为公司内部互相学习的分享,希望有Android开发需求或者对Androi ...

最新文章

  1. 【H.265】H.265(HEVC)编码过程和名词解释
  2. R语言基于Bagging算法(融合多个决策树)构建集成学习Bagging分类模型、并评估模型在测试集和训练集上的分类效果(accuray、F1、偏差Deviance):Bagging算法与随机森林对比
  3. 「数据结构」图基础篇
  4. java 文件树形_java 显示树形文件结构,类似windows的tree命令
  5. 10月23日见?疑似魅族16T预热海报曝光:定位大屏娱乐旗舰
  6. 全国计算机二级c语言和江苏教材一样吗,计算机二级省级和全国计算机二级考试内容一样吗...
  7. UNIX环境高级编程——线程同步之条件变量以及属性
  8. 函数:找出一句话中的第二个单词
  9. 数据意识崛起,从企业应用看BI软件的未来发展
  10. python网络爬虫学习笔记(二):爬虫基本概述
  11. Motion 5.6.1 for Mac(视频后期特效处理软件)
  12. pdf转换器注册码及pdf转换器使用步骤
  13. JS 右键鼠标事件练习
  14. matlab实时编辑器怎么用,Markdown 实时编辑器
  15. html js 做一个钟表,html,css,js实现的一个钟表
  16. 文件服务器raid1+5,服务器上的raid1 raid5,什么意思啊!
  17. 和诸君学习做一个黑客 内网ARP欺骗[上]外接网卡的安装和启动(3)
  18. Warning[Pe069]: integer conversion resulted in truncation
  19. 旧电脑利用:windows网页版魔镜【不需树莓派】
  20. html卡片式ui,十分钟认识UI设计中卡片式设计技法

热门文章

  1. 重庆计算机财经学院,重庆财经学院
  2. 地铁三号线 - 搬家故事
  3. sql server
  4. uni-app 应用换肤功能
  5. 腾讯T3大牛亲自教你!2021大厂Android面试经验,经典好文
  6. 展示正在活动时间内的活动,过期活动不显示
  7. RTX3070和2080Ti 哪个好
  8. 单片机小精灵(延时、定时计算软件)
  9. 315来了,跨境卖家们赶紧自检容易被维权举报的问题
  10. 计算机基础知识文件的复制移动,如何复制文件