使用过Android系统的朋友应该都知道,Android里面声音是区分好几种情况,每种情况下的音频大小是独立的。也就是说你调节了电话铃声大小不会影响多媒体播放的声音大小。这个涉及了AudioStream的使用,今天会详细讲解一下AudioStream相关知识。另外我们用耳机上按钮控制音乐播放器等音频程序,可以使用MediaButton来实现远程控制。另外会详细讲解MediaButton的两种注册方法以及他们的区别。

(PS:新建的QQ群,有兴趣可以加入一起讨论:Android群:322599434)

1、AudioStream分类

  首先看看AudioStream的分类,Android为不同的应用场合定义了不同的AudioStream: Voice Call, Ring, Music,Alarm, Notification, DTMF。 这些AudioStream是相互独立的,所以也有各自的音量。AudioStream的定义在android.media.AudioManager中。

2、AudioStream控制

  但我们按下调音量大小的按键,缺省情况下,按下音量控制的硬件控制键Vol+/-,调节的是当前被激活的AudioStream的音量,如果你的程序当前没有正在播放任何声音,按下Vol+/-调节的是来电铃声的音量。在某一个程序运行时,希望按下Vol+/-调节的是当前所使用的AudioStream的音量,Android在Activity中提供了setVolumeControlStream()方法用来指定你的应用程序使用的Audio Stream类型。所以,如果你的程序用到Audio的播放,你首先要知道你的程序所用的AudioStream类型,并在onCreate()中调用setVolumeControlStream()来设定AudioStream的类型。

  例如下面是音乐播放器打开的时候,设置的AudioStream:

 this.setVolumeControlStream(AudioManager.STREAM_MUSIC);

3、MediaButton

  这里说的MediaButton其实是对应系统的ACTION_MEDIA_BUTTON,ACTION_MEDIA_BUTTON的定义为“android.intent.action.MEDIA_BUTTON”,是系统控制远程音乐和其他多媒体的方法。在手机上常见的应用就是耳机上的控制按钮。一般我们手机或者平板上的音乐、视频播放器都会响应这个广播。例如Android系统自带的Music工程,里面就响应了这个广播。

  除了在手机平板这些对音视频控制,其实在智能电视或者对于需要高度整合的系统来说,这个消息都十分有用。例如:智能电视里面,我们可以利用这个广播实现远程遥控,系统底层接收遥控播放、暂停、下一曲、上一曲等消息,然后通过ACTION_MEDIA_BUTTON广播给上层应用。高度整合的系统,一般都是针对深度定制的系统,用于特定环境的系统。这种系统对于应用之间的配合要求十分高。例如一些工控的机器。这些系统定制比一般的手机系统要求高很多,这些情况下,ACTION_MEDIA_BUTTON就可以发挥很重要的作用。

  下面我们看看怎么使用ACTION_MEDIA_BUTTON这个广播。


//Edited by mythou
//http://www.cnblogs.com/mythou/
public class RemoteControlClientReceiver extends BroadcastReceiver
{
@SuppressWarnings("unused")
private static final String TAG = "mythou_ACTION_MEDIA_BUTTON"; /*
* It should be safe to use static variables here once registered via the
* AudioManager
*/
private static long mHeadsetDownTime = ;
private static long mHeadsetUpTime = ; @Override
public void onReceive(Context context, Intent intent)
{
     //获取对应Acton,判断是否是需要的ACTION_MEDIA_BUTTON
String action = intent.getAction();if (action.equalsIgnoreCase(Intent.ACTION_MEDIA_BUTTON))
{
KeyEvent event = (KeyEvent) intent
.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
if (event == null)
return; if (event.getKeyCode() != KeyEvent.KEYCODE_HEADSETHOOK
&& event.getKeyCode() != KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE
&& event.getAction() != KeyEvent.ACTION_DOWN)
return; Intent i = null;
switch (event.getKeyCode())
{
/*
* one click => play/pause long click => previous double click =>
* next
*/
        //这里根据按下的时间和操作,分离出具体的控制
case KeyEvent.KEYCODE_HEADSETHOOK:
case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
long time = SystemClock.uptimeMillis();
switch (event.getAction())
{
case KeyEvent.ACTION_DOWN:
if (event.getRepeatCount() > )
break;
mHeadsetDownTime = time;
break;
case KeyEvent.ACTION_UP:
// long click
if (time - mHeadsetDownTime >= )
{
i = new Intent(AudioService.ACTION_REMOTE_BACKWARD);
time = ;
// double click
} else if (time - mHeadsetUpTime <= )
{
i = new Intent(AudioService.ACTION_REMOTE_FORWARD);
}
// one click
else
{
if (mLibVLC.isPlaying())
i = new Intent(AudioService.ACTION_REMOTE_PAUSE);
else
i = new Intent(AudioService.ACTION_REMOTE_PLAY);
}
mHeadsetUpTime = time;
break;
}
break;
       //下面是常规的播放、暂停、停止、上下曲 
case KeyEvent.KEYCODE_MEDIA_PLAY:
i = new Intent(AudioService.ACTION_REMOTE_PLAY);
break;
case KeyEvent.KEYCODE_MEDIA_PAUSE:
i = new Intent(AudioService.ACTION_REMOTE_PAUSE);
break;
case KeyEvent.KEYCODE_MEDIA_STOP:
i = new Intent(AudioService.ACTION_REMOTE_STOP);
break;
case KeyEvent.KEYCODE_MEDIA_NEXT:
i = new Intent(AudioService.ACTION_REMOTE_FORWARD);
break;
case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
i = new Intent(AudioService.ACTION_REMOTE_BACKWARD);
break;
} if (isOrderedBroadcast())
abortBroadcast();
if (i != null)
context.sendBroadcast(i);
}
}
}

  上面是音乐播放器里面的一个ACTION_MEDIA_BUTTON 的接收器。接收ACTION_MEDIA_BUTTON  跟我们一般的广播差不多,也是需要定义一个BroadcastReceiver,如何定义BroadcastReceiver这里不多说。

  从上面的代码可以看到,我们可以根据接收的ACTION判断是否是ACTION_MEDIA_BUTTON ,然后获取里面的KeyEvent的值来判断是什么操作。里面包含了常规的媒体控制的值。编写完BroadcastReceiver后,我们只需要在AndroidManifest.xml注册即可。

//Edited by mythou
//http://www.cnblogs.com/mythou/
    <receiver android:name="RemoteControlClientReceiver" >
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
</receiver>

4、独占MEDIA_BUTTON广播

  上面说的注册方法是一般情况下使用,但是ACTION_MEDIA_BUTTON 比较特殊,你可以注册一个ACTION_MEDIA_BUTTON 。只有你一个能接收到,其他人都不能接收。因为这个是控制多媒体的,所以存在一个音视频冲突问题。做过一些系统整合的朋友应该都遇到过这个问题。基本上在我工作里面,我最不想处理的就是音视频冲突,特别在多任务系统里面。

  下面我们说说如何注册一个只有你能接收的ACTION_MEDIA_BUTTON :


//Edited by mythou
//http://www.cnblogs.com/mythou/

//获取音频服务

AudioManager audioManager = (AudioManager) this.getSystemService(AUDIO_SERVICE);
//注册接收的Receiver
ComponentName mRemoteControlClientReceiverComponent;
mRemoteControlClientReceiverComponent = new ComponentName(
getPackageName(), RemoteControlClientReceiver.class.getName());
//注册MediaButton
audioManager.registerMediaButtonEventReceiver(mRemoteControlClientReceiverComponent);

不需要的时候,只要取消注册即可:

//取消注册
audioManager.unregisterMediaButtonEventReceiver(mRemoteControlClientReceiverComponent);

5、两种注册情况对比

  下面说说两种注册ACTION_MEDIA_BUTTON不同的地方,需要说这个就要讲解一下ACTION_MEDIA_BUTTON的发送机制。这个主要是AudioManager做的事情,AudioManager是上层的一个高层封装的音频管理类,真正实现音频的管理的是IAudioService 实现,这里面涉及了Android的底层核心Binder机制,这个是分析Android系统层必须掌握的课程。今天主要是讲解ACTION_MEDIA_BUTTON,所以我这里不做深入分析Binder机制和下面的IAudioService ,后面有空我会写一些分析Binder机制的文章。

  下面简单说一下ACTION_MEDIA_BUTTON消息是如何广播分发的,让大家使用的时候知道何时使用哪种注册方式。

A、AudioManager或者说AudioService服务端对象内部会利用一个栈来管理所有registerMediaButtonEventReceiver()注册的ComponentName对象,最后调用registerMediaButtonEventReceiver()注册的ComponentName就位置这个栈的栈顶。

B、当系统发送MEDIA_BUTTON,系统MediaButtonBroadcastReceiver 监听到系统广播,它会做如下处理:

  • 如果栈为空,则所有注册了该Action的广播都会接受到,因为它是由系统发送的。
  • 如果栈不为空,那么只有栈顶的那个广播能接受到MEDIA_BUTTON的广播,手动发送了MEDIA_BUTTON广播,并且指定了目标对象(栈顶对象)去处理该MEDIA_BUTTON 。

  上面的两条规则,大家一定要记住,这个关系我们注册的ACTION_MEDIA_BUTTON能否正常工作。当然这个是系统全局广播,需要大家的APP都遵守这个规则才可以让系统正常运行。

Edited by mythou

原创博文,转载请标明出处:http://www.cnblogs.com/mythou/p/3302347.html 

Android Audio控制和MediaButton远程控制(音视频控制配合)的更多相关文章

  1. Android Webview中解决H5的音视频不能自动播放的问题

    在开发webview的时候,当加载有声音的网页的时候,声音不会自动播放, 解决方法:在webview中调用js方法.这个方法需要在webview的setWebViewClient方法之后在onPage ...

  2. 腾讯技术分享:微信小程序音视频技术背后的故事

    1.引言 微信小程序自2017年1月9日正式对外公布以来,越来越受到关注和重视,小程序上的各种技术体验也越来越丰富.而音视频作为高速移动网络时代下增长最快的应用形式之一,在微信小程序中也当然不能错过. ...

  3. [SimplePlayer] 8. 音视频同步

    音频与视频在播放当中可能会由于种种原因(如:音视频并非在同一时间开始播放,或视频由于解码任务繁重导致输出图像延迟等)导致音频与视频的播放时间出现偏差,这种就是音视频的同步问题,本文会对音视频同步进行讨 ...

  4. android音视频点/直播模块开发

      音视频 版权声明:本文为博主原创文章,未经博主允许不得转载. 前言 随着音视频领域的火热,在很多领域(教育,游戏,娱乐,体育,跑步,餐饮,音乐等)尝试做音视频直播/点播功能,那么作为开发一个小白, ...

  5. Android WebRTC 音视频开发总结

    www.cnblogs.com/lingyunhu/p/3621057.html 前面介绍了WebRTCDemo的基本结构,本节主要介绍WebRTC音视频服务端的处理,,转载请说明出处(博客园RTC. ...

  6. Android 音视频同步机制

    一.概述 音视频同步(avsync),是影响多媒体应用体验质量的一个重要因素.而我们在看到音视频同步的时候,最先想到的就是对齐两者的pts,但是实际使用中的各类播放器,其音视频同步机制都比这些复杂的多 ...

  7. Android音视频点/直播模块开发实践总结-zz

    随着音视频领域的火热,在很多领域(教育,游戏,娱乐,体育,跑步,餐饮,音乐等)尝试做音视频直播/点播功能.那么作为开发一个小白,如何快速学习音视频基础知识,了解音视频编解码的传输协议,编解码方式,以及 ...

  8. Android音视频之MediaRecorder音视频录制

    前言: 公司产品有很多地方都需要上传音频视频,今天抽空总结一下音频视频的录制.学习的主角是MediaRecorder类. MediaRecorder类介绍: MediaRecorder类是Androi ...

  9. Android IOS WebRTC 音视频开发总结(八十五)-- 使用WebRTC广播网络摄像头视频(下)

    本文主要介绍WebRTC (我们翻译和整理的,译者:weizhenwei,校验:blacker),最早发表在[编风网] 支持原创,转载必须注明出处,欢迎关注我的微信公众号blacker(微信ID:bl ...

随机推荐

  1. Java list的用法排序及遍历

    原文地址:http://baike.xsoftlab.net/view/208.html 1用法 ·ArrayList ·LinkedList 2排序 ·数字排序 ·中文排序 ·实体类排序 3遍历 · ...

  2. 教你把UltraEdit如何注册激活教程及UltraEdit 22.0.0.48 官方中文版下载

    UltraEdit 22.0.0.48 官方中文版下载:链接: http://pan.baidu.com/s/1i3f7mZV 密码: r23v2015-5-30号更新 第一.关闭网络连接(或者直接拔 ...

  3. C语言itoa()函数和atoi()函数详解(整数转字符C实现)

    1.int/float to string/array: C语言提供了几个标准库函数,可以将任意类型(整型.长整型.浮点型等)的数字转换为字符串,下面列举了各函数的方法及其说明. ● itoa():将 ...

  4. mysql(或者mariadb)连接工具HeidiSQL

    Some infos around HeidiSQL Project website: http://www.heidisql.com/Google Code: http://code.google. ...

  5. 【基础知识】.Net基础加强09天

    委托: 1. 委托是一种数据类型,像类一样{可以声明委托变量类型} 2. deleate关键字定义委托 : public delegate void MethodDelegate();//这就是定义了 ...

  6. C++11 并发指南系列

    本系列文章主要介绍 C++11 并发编程,计划分为 9 章介绍 C++11 的并发和多线程编程,分别如下: C++11 并发指南一(C++11 多线程初探)(本章计划 1-2 篇,已完成 1 篇) C ...

  7. spring三种实例化bean的方式

    1构造函数实例化 2静态工厂方法实例化 3实例工厂方法实例化 service接口: package service; public interface PersonService { public v ...

  8. HTML5 ——本地存储

    目录 一.HTML4客户端存储 1.1.提交表单发送到服务器的信息 1.2.客户端本地存储概要 二.localStorage 2.1.添加 2.2.取值 2.3.修改 2.4.删除 2.5.跨页面与跨 ...

  9. SSDB安装配置

    1.下载ssdb wget -O ssdb-master.zip https://codeload.github.com/ideawu/ssdb/zip/master 2.编译安装 unzip ssd ...

  10. 【Android】进入Material Design时代

    由于本文引用了大量官方文档.图片资源,以及开源社区的Lib和相关图片资源,因此在转载的时候,务必注明来源,如果使用资源请注明资源的出处,尊重版权,尊重别人的劳动成果,谢谢! Material Desi ...