Android10.0AudioFocus之如何使用(一)

前言

对于音频焦点,很多人会感到很陌生,也很迷惑,不清楚音频焦点到底处理什么的,怎么用。有人说要播放音乐,必须先申请焦点,只有拿到焦点后才能播放音乐,可也有人说我不申请音频焦点也能播放音乐,因此,今天我们就来说说到底什么是音频焦点。

正文

AudioFocus机制实在Android2.2引入的,当初是为了协调各应用之间竞争Audio资源的问题,举个简单例子QQ音乐要播放音乐,优酷要播放视频。对于手机上的这两个应用,如果视频和音乐同时播放,效果可想而知,那么他们之间怎么实现互斥播放的呢,当然实现的方式很多,广播 binder的进程间通信等,但你觉得QQ音乐会告诉优酷你接下我的广播,或者优酷告诉QQ音乐你bind下我,如果在加入一个网易云音乐,爱奇艺视频,显然是不可以的,谷歌爸爸显然又不可能让大家胡闹下去,因为好的用户体验还是很重要的嘛,因此这个时候AudioFocus就出现了。
谷歌爸爸说我来制定一套游戏规则,大家遵守规则就可以愉快的一起玩耍了,但既然只是规则,那么就有遵守游戏规则的好孩子以及不遵守游戏规则的好孩子。
遵不遵守游戏规则都是可以一起玩耍的,这就回到了我们开始说的问题。有人说要播放音乐,必须先申请焦点,只有拿到焦点后才能播放音乐(遵守游戏规则的好孩子),可也有人说我不申请音频焦点也能播放音乐(不遵守游戏规则的好孩子)
说到这我想这回对音频焦点都有了一个初步的认时,既然是规则,显然是个弱管理。也就是说如果你想播放,不管拿不拿得到音频焦点,都是可以播放的。影响的只是体验效果,不是播放问题。这个一定要搞懂。
废话连篇的说了好多,那么如何使用呢?过时的使用方法就不说了,我们只说最新的关于AudioFocus的Api。

package com.example.myapplication;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.media.AudioAttributes;
import android.media.AudioFocusRequest;
import android.media.AudioManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import androidx.annotation.NonNull;

public class MainActivity extends Activity {

    private AudioManager mAudioManager;
    private AudioFocusRequest mFocusRequest;
    private AudioManager.OnAudioFocusChangeListener mListener;
    private AudioAttributes mAttribute;
    @SuppressLint("HandlerLeak")
    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
        mListener = new AudioManager.OnAudioFocusChangeListener() {
            @Override
            public void onAudioFocusChange(int focusChange) {
                switch (focusChange) {
                    case AudioManager.AUDIOFOCUS_GAIN:
                       // TBD 继续播放
                        break;
                    case AudioManager.AUDIOFOCUS_LOSS:
                       // TBD 停止播放
                        break;
                    case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
                        // TBD 暂停播放
                        break;
                    case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
                        // TBD 混音播放 
                        break;
                    default:
                        break;
                }

            }
        };
        //android 版本 5.0
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            mAttribute = new AudioAttributes.Builder()
                    .setUsage(AudioAttributes.USAGE_MEDIA)
                    .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
                    .build();
        }
        //android 版本 8.0
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
            mFocusRequest = new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN)
                    .setWillPauseWhenDucked(true)
                    .setAcceptsDelayedFocusGain(true)
                    .setOnAudioFocusChangeListener(mListener, mHandler)
                    .setAudioAttributes(mAttribute)
                    .build();
        }
    }

    private void requestAudioFocus() {

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            int ret = mAudioManager.requestAudioFocus(mFocusRequest);       
            if (ret == AudioManager.AUDIOFOCUS_REQUEST_FAILED) {
				// TBD 焦点申请失败 不执行播放
            } else if (ret == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
				// TBD 焦点申请成功 执行播放
            } else if (ret == AudioManager.AUDIOFOCUS_REQUEST_DELAYED) {
				// TBD 焦点申请delay 不执行播放(这种时候一般电话中,我们播放音乐会有这种状态,如果ret是delay,那么如果可以播放的时候会收到对应AUDIOFOCUS_GAIN的callback)
            }
        }
    }

    private void abandonAudioFocus() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            mAudioManager.abandonAudioFocusRequest(mFocusRequest);
        }

    }
}

以上就是App使用AudioFocus的一个简单demo,那么我们在使用的时候申请一个什么类型的焦点呢?有几个值的含义是一定要明确的:
AUDIOFOCUS_GAIN:长时间获取焦点,一般用于音视频。
AUDIOFOCUS_GAIN_TRANSIENT:短暂获得,一般用于电话,语音助理等
AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK:混音,一般用于导航
AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE:(android后加的)与AUDIOFOCUS_GAIN_TRANSIENT类似,表示一个短暂的获取焦点,一般用于语音识别什么的,很少用。
既然提到了电话这里先吐槽下谷歌做的音频焦点,那是真的烂,因此才会有那么多的厂商来定制音频焦点这块,本来一个requestAudioFocus就可以了,但发现电话时好像不应该被其他应用抢去焦点,那可咋整,哦,加个接口吧,于是乎 public void requestAudioFocusForCall(int streamType, int durationHint) 来了,requestAudioFocus(AudioFocusRequest requset)被更新来更新去, requestAudioFocusForCall(int streamType, int durationHint) 貌似出了之后发现不是很好在就一直没有更新过,requestAudioFocusForCall优先级最高,也不需要返回值,方法执行成功与否也不知道,对应abandonAudioFocusForCall()也是简单粗暴。其实个人觉得requestAudioFocusForCall(int streamType, int durationHint)这个durationHint基本可以写死AUDIOFOCUS_GAIN_TRANSIENT,这样岂不更简单粗暴。
说的有点跑题,综上,根据这些值含义,我们基本知道了我们要申请什么样的音频焦点,下一篇说一下申请每一种音频焦点对应的listener会给的callback都有哪些,以及从源码角度来分析整个音频焦点的原理。

总结

其实音频焦点要说的还有很多,包括Car上的Audio,从下篇开始,我们就从源码角度一点一点分析其原理。
归根结底音频焦点本身是一种弱管理,只是规则的制订,至于是否遵守是应用自身行为,就像红绿灯,如果你非要闯红灯,非要逆行,音频焦点本身控制不了交通,最终依赖车辆自身行为。就是这个道理。
希望这篇文章,对于新接触Android音频焦点的朋友有一点点的帮助。

  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
### 回答1: android 10.0系统应用默认授权是指在android 10.0系统中,部分应用在安装后默认会被授予一些权限,而不需要用户在应用启动后再去手动开启这些权限,这样可以提高用户的使用体验。 android 10.0系统应用默认授权的目的是为了加强应用的安全性,提高用户的隐私保护。应用需要访问某些敏感数据或功能时,用户在使用前需要手动开启权限,这样可以减少恶意应用通过获取用户授权的方式获取用户的私人信息。 在android 10.0系统中,应用默认被授权的权限包括日历、相机、联系人、位置、麦克风、电话、短信、存储空间等。这些权限是应用正常运行所必需的,用户可以在应用管理器中查看和管理应用授权的权限。 尽管android 10.0系统应用默认授权提高了用户的使用体验,但也存在一些风险。如果用户使用的是恶意应用,这些应用也可以默认获取一些敏感权限,从而获取用户的私人信息。因此,用户需要保持对应用的警惕,并仔细审核应用的权限请求。 ### 回答2: 在Android 10.0系统中,应用默认授权是一种新的权限模型。它改变了以往Android系统中权限管理的方式,使用户对应用程序的权限管理更加方便和安全。 传统的权限管理模型通常是一次性处理权限请求,无法区分应用程序对某一项权限的使用情况。这种方式缺少细节和灵活性,可能导致应用程序通过某些权限去访问用户的隐私信息。而Android 10.0系统应用默认授权则可以保护用户的隐私信息和数据安全。 应用默认授权模型允许应用程序在不请求用户手动授权的情况下,自动获得某些权限,并在必要的时候再向用户请求授权。这种方式可以减少用户被安装并包含恶意代码的应用程序所利用的风险。 具体地说,当应用程序请求任何运行时权限时,Android 10.0系统将无法立即授予权限。相反,它将显示一个对话框,询问用户是否要授予权限。只有在用户同意授予权限时,应用程序才能获得此权限。 此外,应用默认授权模型还能够自动限制应用程序对某些权限的访问,比如位置信息和网络数据,除非用户主动授予权限或应用程序已经获得了相应的批准。 总之,Android 10.0系统的应用默认授权能够保护用户隐私,增加应用程序的灵活性,并减少用户遭受来自恶意应用程序的风险。 ### 回答3: Android 10.0系统的应用默认授权,是指所有应用程序在安装时系统会默认授予其部分权限,而不是像以前版本的系统一样需要用户在应用使用时手动授权。 Android 10.0系统应用默认授权的目的,是为了提高应用程序的用户便利性和操作流畅性,同时还可以降低用户在使用应用程序时需要授权的次数。但是这也有可能导致一些应用程序获取用户隐私的风险。 在Android 10.0系统中,应用程序默认被授权的权限包括:网络访问、用户日历、联系人和传感器等。对于其他一些权限,如摄像头、麦克风、存储空间和定位等信息,用户在应用程序使用时需要手动授权才能访问。 因此,用户在使用Android 10.0系统时需要非常谨慎地选择哪些应用程序可以获得自己的隐私权限。建议用户在安装应用程序前,仔细检查其权限请求,尽可能减少不必要的隐私授权操作。 同时,为了更好地保护用户的隐私,Android 10.0系统也提供了更加严格的权限管理功能。用户可以通过设置菜单中的 “应用程序和通知”-“应用程序权限” 来查看和修改应用程序的权限,在此基础上更好地控制应用程序的使用和权限访问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

轻量级LZ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值