2026/1/7 6:11:22
网站建设
项目流程
德安县建设局网站,上海知名的网站公司,章丘建设网站,个人域名用来做淘宝客网站Usage 和 StreamType 是 Android 音频系统中两代不同的音频分类机制。简单来说#xff1a;StreamType 是旧的、简单的分类#xff0c;音量流类型#xff0c;Usage 是新的、更精细的分类#xff0c;音频场景类型。
核心区别总结维度StreamType (旧)AudioAttributes.Usage (新…Usage 和 StreamType 是 Android 音频系统中两代不同的音频分类机制。简单来说StreamType 是旧的、简单的分类音量流类型Usage 是新的、更精细的分类音频场景类型。核心区别总结维度StreamType (旧)AudioAttributes.Usage (新)引入时间Android 2.3 及更早Android 5.0 (Lollipop)设计理念基于播放流类型基于音频使用场景数量固定的 7-8 种类型灵活扩展标准 10 种音量控制1:1 绑定到音量条可灵活映射到音量条优先级隐含在类型中显式优先级控制扩展性固定不可扩展可自定义扩展推荐使用已废弃仅兼容旧代码Android 5.0 推荐详细对比1.定义和范围StreamType有限、固定// AudioManager.javapublicstaticfinalintSTREAM_VOICE_CALL0;// 通话publicstaticfinalintSTREAM_SYSTEM1;// 系统声音publicstaticfinalintSTREAM_RING2;// 铃声publicstaticfinalintSTREAM_MUSIC3;// 媒体音乐、视频、游戏publicstaticfinalintSTREAM_ALARM4;// 闹钟publicstaticfinalintSTREAM_NOTIFICATION5;// 通知publicstaticfinalintSTREAM_DTMF8;// 双音多频publicstaticfinalintSTREAM_ACCESSIBILITY10;// 无障碍// 总共只有 8 种且不可扩展Usage丰富、灵活// AudioAttributes.javapublicstaticfinalintUSAGE_UNKNOWN0;publicstaticfinalintUSAGE_MEDIA1;// 媒体publicstaticfinalintUSAGE_VOICE_COMMUNICATION2;// 语音通话publicstaticfinalintUSAGE_VOICE_COMMUNICATION_SIGNALLING3;// 通话信令publicstaticfinalintUSAGE_ALARM4;// 闹钟publicstaticfinalintUSAGE_NOTIFICATION5;// 通知publicstaticfinalintUSAGE_NOTIFICATION_TELEPHONY_RINGTONE6;// 电话铃声publicstaticfinalintUSAGE_NOTIFICATION_COMMUNICATION_REQUEST7;// 通信请求publicstaticfinalintUSAGE_NOTIFICATION_COMMUNICATION_INSTANT8;// 即时消息publicstaticfinalintUSAGE_NOTIFICATION_COMMUNICATION_DELAYED9;// 延迟消息publicstaticfinalintUSAGE_NOTIFICATION_EVENT10;// 事件publicstaticfinalintUSAGE_ASSISTANCE_ACCESSIBILITY11;// 无障碍publicstaticfinalintUSAGE_ASSISTANCE_NAVIGATION_GUIDANCE12;// 导航publicstaticfinalintUSAGE_ASSISTANCE_SONIFICATION13;// UI提示音publicstaticfinalintUSAGE_GAME14;// 游戏publicstaticfinalintUSAGE_VIRTUAL_SOURCE15;// 虚拟声源publicstaticfinalintUSAGE_ASSISTANT16;// 语音助手// 还可由厂商自定义扩展2.设计哲学差异StreamType“我在播放什么类型的音频流”关注音频的技术来源类型简单但粗粒度难以满足复杂场景一个 StreamType 包含多种语义场景// ❌ StreamType 的问题过于笼统// STREAM_MUSIC 包含了// 1. 背景音乐// 2. 游戏音效// 3. 视频音频// 4. 播客// 5. UI 音效// 系统无法区分这些场景的不同需求Usage“这段音频的用途和场景是什么”关注音频的使用场景和目的细粒度可精确描述意图系统可做更智能的决策// ✅ Usage 的精确描述.setUsage(USAGE_GAME)// 游戏音效可能启用低延迟.setUsage(USAGE_ASSISTANCE_NAVIGATION_GUIDANCE)// 导航可打断音乐.setUsage(USAGE_NOTIFICATION_EVENT)// 日历提醒需要确保用户听到.setUsage(USAGE_ASSISTANT)// 语音助手需要特殊音频路由3.实际使用方式对比StreamType 方式旧 API// MediaPlayerMediaPlayerplayernewMediaPlayer();player.setAudioStreamType(AudioManager.STREAM_MUSIC);// 设置流类型player.setDataSource(music.mp3);player.prepare();player.start();// 设置音量全局影响AudioManageram(AudioManager)getSystemService(Context.AUDIO_SERVICE);am.setStreamVolume(AudioManager.STREAM_MUSIC,volume,0);// SoundPoolSoundPoolspnewSoundPool.Builder().setMaxStreams(10).setAudioAttributes(null)// ❌ 老方式用不了 Usage.build();// SoundPool 默认只能用 STREAM_MUSICAudioAttributes新 API包含 Usage// 1. 创建 AudioAttributes包含 usage 和其他属性AudioAttributesattributesnewAudioAttributes.Builder().setUsage(AudioAttributes.USAGE_GAME)// 使用场景游戏.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)// 内容类型音效.setFlags(AudioAttributes.FLAG_AUDIBILITY_ENFORCED)// 标志强制可听.setHapticChannelsMuted(false)// 触觉通道.build();// 2. MediaPlayer推荐方式MediaPlayerplayernewMediaPlayer();player.setAudioAttributes(attributes);// ✅ 设置完整的音频属性player.setDataSource(game_sound.mp3);player.prepare();player.start();// 3. AudioTrackAudioTracktracknewAudioTrack.Builder().setAudioAttributes(attributes)// ✅.setAudioFormat(format).setBufferSizeInBytes(bufferSize).setTransferMode(AudioTrack.MODE_STREAM).build();// 4. SoundPoolAndroid 5.0SoundPoolspnewSoundPool.Builder().setMaxStreams(10).setAudioAttributes(attributes)// ✅ 终于可以指定 usage 了.build();// 5. 音量控制更精确// 不再直接控制 STREAM_MUSIC而是通过 usageintvolumeaudioManager.getStreamVolume(AudioAttributes.usageToStream(AudioAttributes.USAGE_GAME));4.映射关系系统内部会将 Usage 映射到 StreamType 以保持兼容性// frameworks/base/media/java/android/media/AudioAttributes.javapublicstaticintusageToStream(intusage){switch(usage){caseUSAGE_UNKNOWN:returnAudioManager.STREAM_MUSIC;caseUSAGE_MEDIA:caseUSAGE_GAME:caseUSAGE_ASSISTANCE_ACCESSIBILITY:caseUSAGE_ASSISTANCE_NAVIGATION_GUIDANCE:// 导航映射到音乐流returnAudioManager.STREAM_MUSIC;caseUSAGE_ASSISTANCE_SONIFICATION:returnAudioManager.STREAM_SYSTEM;caseUSAGE_VOICE_COMMUNICATION:returnAudioManager.STREAM_VOICE_CALL;caseUSAGE_VOICE_COMMUNICATION_SIGNALLING:returnAudioManager.STREAM_DTMF;caseUSAGE_ALARM:returnAudioManager.STREAM_ALARM;caseUSAGE_NOTIFICATION:caseUSAGE_NOTIFICATION_COMMUNICATION_REQUEST:caseUSAGE_NOTIFICATION_COMMUNICATION_INSTANT:caseUSAGE_NOTIFICATION_COMMUNICATION_DELAYED:caseUSAGE_NOTIFICATION_EVENT:caseUSAGE_NOTIFICATION_TELEPHONY_RINGTONE:returnAudioManager.STREAM_NOTIFICATION;default:returnAudioManager.STREAM_MUSIC;}}注意这个映射是有损的丢失了 Usage 的精细信息。5.音频焦点处理差异StreamType 时代的焦点// 旧方式基于流类型的简单焦点AudioManageram(AudioManager)getSystemService(Context.AUDIO_SERVICE);am.requestAudioFocus(focusChangeListener,AudioManager.STREAM_MUSIC,// 只能指定流类型AudioManager.AUDIOFOCUS_GAIN);// 问题所有 STREAM_MUSIC 都被同样对待// 游戏、音乐、视频、导航播报无法区分优先级AudioAttributes 时代的焦点// 新方式基于 Usage 的精确焦点AudioAttributesattributesnewAudioAttributes.Builder().setUsage(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE)// 明确是导航.setContentType(AudioAttributes.CONTENT_TYPE_SPEECH).build();AudioFocusRequestfocusRequestnewAudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK).setAudioAttributes(attributes)// ✅ 携带详细的音频属性.setAcceptsDelayedFocusGain(true).setOnAudioFocusChangeListener(focusChangeListener).setWillPauseWhenDucked(false).build();intresultaudioManager.requestAudioFocus(focusRequest);// 系统可以// 1. 知道这是导航语音可适当打断音乐// 2. 但不是紧急通知不需要完全暂停// 3. 可采用闪避ducking而非暂停6.音频路由策略差异StreamType 路由// 简单路由基于设备类型if(streamTypeAudioManager.STREAM_VOICE_CALL){routeTo(DEVICE_EARPIECE);// 通话只能路由到听筒}elseif(streamTypeAudioManager.STREAM_MUSIC){routeTo(DEVICE_SPEAKER);// 音乐只能路由到扬声器}// 不智能无法处理复杂场景Usage 路由// 智能路由基于使用场景switch(usage){caseUSAGE_VOICE_COMMUNICATION:// 语音通话优先蓝牙耳机其次听筒if(bluetoothAvailable)routeTo(BLUETOOTH_HEADSET);elserouteTo(EARPIECE);break;caseUSAGE_MEDIA:// 媒体播放根据上下文选择if(headphonesConnected)routeTo(HEADPHONES);elseif(carMode)routeTo(CAR_SPEAKERS);elserouteTo(SPEAKER);break;caseUSAGE_ASSISTANCE_NAVIGATION_GUIDANCE:// 导航车载系统特殊处理if(inCar)routeTo(CAR_FRONT_SPEAKERS);elserouteTo(SPEAKER);break;caseUSAGE_ASSISTANT:// 语音助手可能用智能音箱if(smartSpeakerAvailable)routeTo(SMART_SPEAKER);elserouteTo(DEVICE_DEFAULT);break;}7.音量控制差异StreamType 音量控制// 7个独立的音量条AudioManageram(AudioManager)getSystemService(Context.AUDIO_SERVICE);// 媒体音量控制音乐、游戏、视频、导航等所有媒体am.setStreamVolume(AudioManager.STREAM_MUSIC,mediaVolume,0);// 铃声音量am.setStreamVolume(AudioManager.STREAM_RING,ringVolume,0);// 闹钟音量am.setStreamVolume(AudioManager.STREAM_ALARM,alarmVolume,0);// 通话音量am.setStreamVolume(AudioManager.STREAM_VOICE_CALL,callVolume,0);// 问题导航音量调整会影响音乐音量Usage 音量控制// 更细粒度的音量控制概念上// 注意Android 仍然通过 StreamType 控制音量// 但通过 usage 到 stream 的映射可以实现更合理控制// 系统内部可以根据 usage 做特殊处理if(usageUSAGE_ASSISTANCE_NAVIGATION_GUIDANCE){// 导航语音可以在媒体音量基础上做偏移floatnavigationGaincalculateNavigationGain(mediaVolume);applyVolume(navigationGain);}elseif(usageUSAGE_GAME){// 游戏音效可单独记忆音量intgameVolumegetSavedVolume(USAGE_GAME);am.setStreamVolume(AudioManager.STREAM_MUSIC,gameVolume,0);}迁移指南从 StreamType 迁移到 Usage// ❌ 旧的 StreamType 方式已废弃player.setAudioStreamType(AudioManager.STREAM_MUSIC);am.requestAudioFocus(listener,AudioManager.STREAM_MUSIC,AudioManager.AUDIOFOCUS_GAIN);// ✅ 新的 AudioAttributes 方式AudioAttributesattributesnewAudioAttributes.Builder().setUsage(AudioAttributes.USAGE_MEDIA)// 对应 STREAM_MUSIC.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC).build();player.setAudioAttributes(attributes);AudioFocusRequestrequestnewAudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN).setAudioAttributes(attributes).setOnAudioFocusChangeListener(listener).build();am.requestAudioFocus(request);映射参考表StreamType建议的 Usage说明STREAM_MUSICUSAGE_MEDIA普通媒体播放STREAM_MUSICUSAGE_GAME游戏音效STREAM_MUSICUSAGE_ASSISTANCE_NAVIGATION_GUIDANCE导航语音STREAM_ALARMUSAGE_ALARM闹钟STREAM_RINGUSAGE_NOTIFICATION_TELEPHONY_RINGTONE电话铃声STREAM_NOTIFICATIONUSAGE_NOTIFICATION普通通知STREAM_NOTIFICATIONUSAGE_NOTIFICATION_EVENT事件提醒STREAM_VOICE_CALLUSAGE_VOICE_COMMUNICATION语音通话STREAM_SYSTEMUSAGE_ASSISTANCE_SONIFICATION系统音效STREAM_ACCESSIBILITYUSAGE_ASSISTANCE_ACCESSIBILITY无障碍实际建议什么时候用 StreamType✅ 维护遗留代码Android 4.x 及更早✅ 简单的音频播放需求✅ 不需要精细的音频策略控制什么时候必须用 AudioAttributes.Usage✅Android 5.0 的新应用✅ 需要细粒度音频控制✅ 需要精确的音频焦点处理✅ 车载、电视、手表等特殊设备✅ 语音助手、导航、游戏等特殊场景✅ 需要控制音频路由如强制蓝牙输出实际代码示例对比// 场景游戏应用播放音效// ❌ 旧方式问题无法区分游戏和音乐soundPoolnewSoundPool(10,AudioManager.STREAM_MUSIC,0);// 用户调整媒体音量时游戏音效和音乐一起被调整// ✅ 新方式正确明确标记为游戏AudioAttributesgameAttrsnewAudioAttributes.Builder().setUsage(AudioAttributes.USAGE_GAME).setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION).build();soundPoolnewSoundPool.Builder().setMaxStreams(10).setAudioAttributes(gameAttrs)// 明确是游戏.build();// 系统可以// 1. 启用低延迟模式// 2. 应用游戏音效优化// 3. 在音频焦点冲突时合理处理总结StreamType 是流类型思维Usage 是使用场景思维StreamType回答“这是什么类型的音频流”Usage回答“这段音频是用来干什么的”迁移到 Usage 的优势更精细的控制可区分音乐、游戏、导航、通知等更智能的路由系统可根据场景选择最佳输出设备更合理的焦点不同场景有不同优先级更好的兼容性适应车载、电视、穿戴设备等新场景未来扩展性可自定义新的 usage 类型对于新应用强烈建议使用 AudioAttributes.Usage它提供了更现代、更精确的音频控制方式。