• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >Android > Android java层音频相关的分析与理解(三)调用相关

Android java层音频相关的分析与理解(三)调用相关

作者:网友 字体:[增加 减小] 来源:互联网 时间:2017-05-26

网友通过本文主要向大家介绍了android js调用java,android c 调用java,android调用java接口,androidjava,java android开发等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

Android java层音频相关的分析与理解(三)调用相关


Android中会有多个应用需要支持音频的播放。当同一时间内有多个应用需要输出音频的时候,到底是全部输出?还是输出其中一个?假如输出其中一个,那到底输出哪个?以什么标准去界定?为了处理这些关系。Android在2.3的时候引入了AudioFocus机制并沿用到现在。

 

1 AudioFocus简介

 

AudioFocus是一个没有优先级概念的抢占式的机制。一般情况下,最后申请使用AudioFoucs的应用或取得当前的AudioFocus从而将前面申请的应用给停掉。但是,有一种情况是特殊的,就是通话。通话作为手机的重要功能,从响铃到通话接受,Telephony都会申请AudioFocus,所有应用都不能从Telephony中获取音频焦点,但Telephony可以从任何应用中获取到AudioFocus。

 

当前Android6.0下AudioFocus有几种状态,分别为:

\


从上面AudioFocus的状态可以看出,其实AudioFocus的状态是对应的。当后一个应用去GainAudioFocus时,前一个应用就相对应地LossAudioFocus。后一个应用以什么形式去Gain,前一个应该就会受到相应Loss的通知。但是,当前一个应用收到这个Loss通知时,应用怎么处理是应用内部的事情。因为AudioFoucs机制是一个建议性而不是强制性的机制。应用使用这种机制只是使用户体验更加好,而不采用这套机制,甚至不遵循这套机制,对应用与系统本身来是,是没有什么影响的。

再补充说明一下,当应用通过AudioFocus机制去输出音频的时候,它可以因为其他应用通过获取AudioFocus去暂停输出。但是,应用也可以不通过AudioFocus去输出音频。此时该应用的一切音频输出逻辑由本身控制。不受AudioFocus机制影响。

2 AudioFocus的实现

 

AudioFocus机制其实相当于一个栈。

\

 


如上图所示,AudioFocus机制是以栈的形式实现,位于栈顶的应用能获取到AudioFocus从而能输出音频。非栈顶应用会暂时失去AudioFocus直至位于其上面的全部应用关闭或主动丢失AudioFocus。

AudioFocus的实现是从AudioManager.java开始的。

一般来说,应用内部会通过调用AudioManager的requestAudioFocus()方法去获取AudioFocus。AudioManager这一次,与以往不同,不只是作为一个类似于传递者的角色直接获取AudioService的句柄然后将参数传递过去,而是先通过一系列的判断和封装,通过2次重载,将应用的相关消息保存并调用AudioSercvice中的requestAudioFocus(),进一步处理获取AudioFocus操作。


 

所以我们来看一下AudioManager的requestAudioFocus()的主要内容:

public int requestAudioFocus (OnAudioFocusChangeListener l,
            @NonNull AudioAttributes requestAttributes,
            int durationHint,
            int flags,
            AudioPolicy ap) throws IllegalArgumentException {
        ……//一系列的参数判断
        int status = AUDIOFOCUS_REQUEST_FAILED;
        //将申请AudioFocus的应用的listener放进mAudioFocusIdListenerMap中
registerAudioFocusListener(l);
        IAudioService service = getService();
        try {
            //调用AudioService的requestAudioFocus()
            status = service.requestAudioFocus(requestAttributes, durationHint, mICallBack,
                    mAudioFocusDispatcher, getIdForAudioFocusListener(l),
                    getContext().getOpPackageName() /* package name */, flags,
                    ap != null ? ap.cb() : null);
        } catch (RemoteException e) {
            Log.e(TAG, "Can't call requestAudioFocus() on AudioService:", e);
        }
        return status;
    }

在requestAudioFocus()中,与以往的稍有不同的是,requestAudioFocus()先一步对传入的参数进行处理,并将申请应用的listener放进了mAudioFocusIdListenerMap中保存。而传入的参数中,多了mAudioFocusDispatcher和getIdForAudioFocusListener(l)。getIdForAudioFocusListener(l)很明显,就是将这个listener的名字传进去。那mAudioFocusDispatcher到底是干什么的呢?

 

接下来,我们先来关注一下mAudioFocusDispatcher:

 

    private final IAudioFocusDispatcher mAudioFocusDispatcher = new IAudioFocusDispatcher.Stub() {

        public void dispatchAudioFocusChange(int focusChange, String id) {
            Message m = mAudioFocusEventHandlerDelegate.getHandler().obtainMessage(focusChange, id);
            mAudioFocusEventHandlerDelegate.getHandler().sendMessage(m);
        }
    };

 

从上面我们可以看出,mAudioFocusDispatcher是IaudioFocusDispatcher的一个实现。他里面有一个方法,负责调用mAudioFocusEventHandlerDelegate去处理消息的内容。那mAudioFocusEventHandlerDelegate又是干什么呢?我们继续往下看。

    private class FocusEventHandlerDelegate {
        private final Handler mHandler;
        FocusEventHandlerDelegate() {
            Looper looper;
            if ((looper = Looper.myLooper()) == null) {
                looper = Looper.getMainLooper();
            }
            if (looper != null) {
                // implement the event handler delegate to receive audio focus events
                mHandler = new Handler(looper) {
                    @Override
                    public void handleMessage(Message msg) {
                        OnAudioFocusChangeListener listener = null;
                        synchronized(mFocusListenerLock) {
                            listener = findFocusListener((String)msg.obj);
                        }
                        if (listener != null) {
                            Log.d(TAG, "AudioManager dispatching onAudioFocusChange("
                                    + msg.what + ") for " + msg.obj);
                            listener.onAudioFocusChange(msg.what);
                        }
                    }
                };
            } else {
                mHandler = null;
            }
        }
        Handler getHandler() {
            return mHandler;
        }
    }

从上面我们可以看出,调用mAudioFocusEventHandlerDelegate就是为了回调传入的listener的onAudioFocusChange方法去处理相关的内容。那明明可以直接通过l.onAudioFocusChange(focusChange)去处理这些信息,为什么要多此一举专门用一个handle去处理了?于是我去查了一下啊,原因如下:因为这个回调尚在Binder的调用线程中,如果在这里因为用户传入的listener的代码有问题而爆出异常或阻塞甚至恶意拖延,则会导致Binder的另一端因异常而崩溃或阻塞。所以到此为止,AudioService已经尽到了通知的义务,应该通过Handler将后续的操作发往另外一个线程,使AudioService尽可能远离回调现实的影响。

 

所以,现在我们可以进入AudioService去看一下到底AudioService是怎样处理的。

AudioService. requestAudioFocus()如下:

public int requestAudioFocus(AudioAttributes aa, int durationHint, IBinder cb,
            IAudioFocusDispatcher fd, String clientId, String callingPackageName, int flags,
            IAudioPolicyCallback pcb) {
        // 检测权限
        if ((flags & AudioManager.AUDIOFOCUS_FLAG_LOCK) == AudioManager.AUDIOFOCUS_FLAG_LOCK) {     //奇怪的地方1
            if (AudioSystem.IN_VOICE_COMM_FOCUS_ID.equals(clientId)) {
                if (PackageManager.PERMISSION_GRANTED != mContext.checkCallingOrSelfPermission(
                            android.Manifest.permission.MODIFY_PHONE_STATE)) {
                    Log.e(TAG, "Invalid permission to (un)lock audio focus", new Exception());
                    return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
                }
            } else {
                //注册一个AudioPolicy去获取AudioFocus
                synchronized (mAudioPolicies) {    //奇怪的地方2
                    if (!mAudioPolicies.containsKey(pcb.asBinder())) {
                        Log.e(TAG, "Invalid unregistered AudioPolicy to (un)lock audio focus");
                        return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
                    }
                }
            }
        }

        retur



 
分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • Android java层音频相关的分析与理解(三)调用相关

相关文章

  • 2017-05-26Android触摸事件(一)-AbsTouchEventHandle
  • 2017-05-26greendao3.2.3配置时遇到的问题,greendao3.2.3遇到
  • 2017-05-26Android的Kotlin秘方(I):OnGlobalLayoutListener,
  • 2017-05-26Android Studio导入第三方库(SlidingMenu)教程,androidslidingmenu
  • 2017-05-26使用Android studio创建的AIDL编译时找不到自定义类的解决办法,androidaidl
  • 2017-05-26Android——eclipse下运行android项目报错 Conversion to Dalvik format failed with error 1解决,androiddalvik
  • 2017-05-26Xamarin.Android 的照相機使用,xamarin.android
  • 2017-05-26Android新手入门2016(10)--GridView
  • 2017-05-26android开发之路05,android之路05
  • 2017-05-26Android studio环境搭建,androidstudio搭建

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • SIMLock锁卡功能解析,simlock锁解析
    • Android百度地图API集成三《搜索》,android《搜索》
    • Cordova系列学习教程02 开发环境的准备和运行
    • 初识genymotion安装遇上的VirtualBox问题,genymotionvirtualbox
    • Solaris IPMP两种配置方法
    • android开发环境以及genymotion虚拟机配合HBuilder测试(自总结),genymotionhbuilder
    • 谷歌IAP:skusBundle array associated with key ITEM_ID_LIST cannot contain more than 20 items.,jsarraycontain
    • android Listview的自定义界面的使用
    • android-webview的使用小结,android-webview
    • 《转》深入理解Activity启动流程(一)–Activity启动的概要流程,《转》activity

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有