Android触感反馈
触感反馈框架的用户体验基础
当前原则
下表列出了所有可用的触感反馈 API。
API | 方法 | 添加年份 |
---|---|---|
android.view.HapticFeedbackConstants | CONTEXT_CLICK CLOCK_TICK VIRTUAL_KEY KEYBOARD_TAP LONG_PRESS | 2016 年之前 |
KEYBOARD_PRESS KEYBOARD_RELEASE TEXT_HANDLE_MOVE VIRTUAL_KEY_RELEASE | 2017 年 (Android 8) | |
CONFIRM REJECT GESTURE_START GESTURE_END | 2020 年 (Android 11) | |
android.View | performHapticFeedback() | 2016 年之前 |
android.os.Vibrator | vibrate() hasVibrator() | 2016 年之前 |
hasAmplitudeControl() | 2017 年 (Android 8) | |
areAllEffectsSupported() areAllPrimitivesSupported() areEffectsSupported() arePrimitivesSupported() | 2020 年 (Android 11) | |
android.os.VibrationEffect | createOneShot() createWaveform() | 2017 年 (Android 8) |
EFFECT_TICK EFFECT_CLICK EFFECT_HEAVY_CLICK EFFECT_DOUBLE_CLICK createPredefined() | 2019 年 (Android 10) | |
android.os.VibrationEffect.Composition | PRIMITIVE_TICK PRIMITIVE_CLICK addPrimitive() compose() | 2020 年 (Android 11) |
android.media.AudioAttributes.Builder | setHapticChannelsMuted() | 2019 年 (Android 10) |
蜂鸣振动
早在寻呼机和非智能手机时代,低质量但节能的 ERM 蜂鸣器振动就已经被用来代替静音模式下的听觉铃声。
旧版硬件组件会产生令人不悦的较大噪声,并且往往质量不佳(例如廉价、破损的手机),会损害触感反馈用户体验。
清晰触感反馈
清晰触感反馈支持感知离散状态变化(例如,开机/关机过程中的二元变化)。
由于离散特征的性质,系统会将清晰触感反馈生成为单个实体(例如,每个输入事件有一个触感反馈效果)。
Android 的目标是提供清晰触感反馈,有强烈而尖锐的感觉,而不是蜂鸣或轻柔的感觉。
为提供清晰触感反馈而创建的预定义触感反馈常量包括以下内容。
CLOCK_TICK
CONFIRM
CONTEXT_CLICK
GESTURE_END
GESTURE_START
KEYBOARD_PRESS
KEYBOARD_RELEASE
KEYBOARD_TAP
LONG_PRESS
REJECT
TEXT_HANDLE_MOVE
VIRTUAL_KEY
VIRTUAL_KEY_RELEASE
在 VibrationEffect
中:
EFFECT_CLICK
EFFECT_DOUBLE_CLICK
EFFECT_HEAVY_CLICK
EFFECT_TICK
在设备制造商和开发者之间建立共识对于提升 Android 生态系统的总体触感反馈质量至关重要。
图 3. 按下和松开。
丰富触感反馈
丰富触感反馈是一个不断变化的触感反馈类别,超越了基于单个脉冲的效果。
Android 旨在提供丰富触感反馈,以实现更高可组合性和可调性,并提供精细粒度。Android 11 或更低版本支持以下用例。
图 4. 带滑动纹理的丰富触感反馈
图 5. 拖动和滑动
用例 1:滑动纹理
如果在手指滑过触控面时触感反馈效果重复(例如,拖动、滑动、探索具有幻觉触感纹理的表面),重复的触感反馈效果最好是清脆而不易察觉。
如果个别效果产生蜂鸣而不清脆,重复之间的间隔很可能已被抹去。结果会导致一声长时间的蜂鸣声,而不是出现多个离散信号。
如果振幅不够小,感知的触感反馈能量会在重复过程中不断累积,从而在重复结束时产生非常强烈的触感反馈。
实现用于滑动和拖动手势的简单表面触感纹理
在 HapticFeedbackConstants
中使用 CLOCK_TICK
和 TEXT_HANDLE_MOVE
。这些常量预定义了重复和振幅的特性。
创建您的专属效果
如需创建您的专属效果,请通过将 VibrationEffect.Composition
中的 PRIMITIVE_CLICK
和 PRIMITIVE_TICK
序列组合在一起来构建设计。您可以使用 addPrimitive(int primitiveID, float scale, int delay)
调整重复和振幅比例的特征。支持与否依赖于振动器 HAL 接口的 CAP_COMPOSE_EFFECTS
功能。
用例 2:带缓入效果的长时间振动
长时间振动是从 0 转换到目标振幅的平滑振幅振动。长时间振动会产生容易感知和引起注意的触感反馈。然而,在安静的环境中,突发的长时间振动可能会使用户受到惊吓,并且通常会产生能听到的蜂鸣噪声。如需生成更令人愉悦的长时间振动,请在长时间振动开始时应用缓入效果。这样会产生一个平滑的振幅过渡,从而累积达到目标振幅。
应用缓入效果
- 使用
android.os.Vibrator.hasAmplitudeControl()
检查振幅控制的硬件功能。- 结果必须为
true
,才能产生不同振幅的缓入效果。
- 结果必须为
- 使用
VibrationEffect
.createWaveform(timings[\], amplitudes[], int repeat)
。 - 调整
timings[]
和amplitudes[]
系列以生成缓入曲线,如图 6 所示。
图 6. 长时间振动缓入曲线
用例 3:音频耦合触感反馈
音频耦合触感反馈是指将触感反馈模式与音频节奏相结合,以引起用户的注意。
音频耦合触感反馈:优势
如需实现音频耦合触感反馈,请将清晰触感反馈与长时间振动相结合。清晰触感反馈强烈而短暂的触感反馈感受能产生一种有节奏的离散模式。如果再加上长时间振动所带来的高刺激,就能很好地吸引用户的注意。
请务必考虑感觉节奏模式。如果没有节奏感,用户就会将触感反馈感知为随机蜂鸣声,并倾向于忽略它们。
图 7. 音频耦合触感反馈示例
音频耦合触感反馈:实现方法提示
如需实现音频耦合触感反馈,需要对音频和触感反馈通道的内容播放有基本的了解。请注意以下几点。
使用
MediaPlayer
或SoundPool
类。- OGG 格式的资源带有一个特殊的元数据键(
ANDROID_HAPTIC
后跟很多触感反馈通道),表示存在触感反馈数据,可以用MediaPlayer
和SoundPool
播放。
- OGG 格式的资源带有一个特殊的元数据键(
表示支持
audio_policy_configuration.xml
中的触感反馈和音频播放。- 使用具有触感反馈通道
AUDIO_CHANNEL_OUT_HAPTIC_A|B
的输出配置文件。 - 对于带有触感反馈通道的输出流,请记住,触感反馈通道在数据中表示为 extra 通道。
示例
如果输出流的通道掩码如下所示:
AUDIO_CHANNEL_OUT_STEREO_HAPTIC_A
那么每个示例应如下所示:
AUDIO_LEFT_CHANNEL,AUDIO_RIGHT_CHANNEL,HAPTIC_CHANNEL_A
- 使用具有触感反馈通道
将
AudioAttributes.Builder( ).setHapticChannelsMuted(boolean muted)
改为false
以播放触感反馈通道。- 默认情况下,触感反馈通道会被静音 (
true
)。 - 用例包括具有同步触感反馈和反馈的铃声和界面声音。
- 默认情况下,触感反馈通道会被静音 (
振动器 HAL 必须实现外部控件支持。
- 对于 HIDL 实现,请使用
setExternalControl(bool enabled) generates (Status status)
。 - 对于 AIDL 实现,请使用
void setExternalControl(in boolean enabled)
。
图 8. 实现音频耦合触感反馈
- 对于 HIDL 实现,请使用
音频耦合触感反馈:触感反馈生成器
HapticGenerator
是 Android 12 中推出的一种音频效果,它可以通过音频声道生成触感反馈数据,并把这些数据作为音频耦合触感反馈实时播放。此效果会应用于 AudioTrack
,如图 9 所示。
图 9. 触感反馈生成器架构
如需确保您的触感反馈生成器算法生成高质量的触感反馈,请调整用于配置应用于音频波形的滤波器链的参数,将生成算法调整为设备振动器电机。
本部分详细介绍了这些参数,并说明了如何根据硬件规范调整这些参数。
带通滤波器的共振频率
振动器共振频率是触感反馈致动器的最大输出频率。该参数会调整反共振器,使响应传递函数部分扁平化,以便获得更宽的带宽。Android 框架会自动将此值与振动器 HAL 方法
IVibrator.getResonantFrequency
的输出相关联。此参数的默认值为 150Hz。这可以通过此处的代码进行修改。
慢包络的归一化功率
此参数决定了部分归一化(自动增益控制)的指数。其默认值为 -0.8,这意味着此增益控制步骤会移除 80% 的动态范围变体。这可以通过此处的代码进行修改。
带阻滤波器的因数 Q
振动器品质因数(因数 Q)由两个参数确定:
- Zero Q:带阻滤波器中零值的品质因数,可部分取消共振。
- Pole Q:带阻滤波器中两极的品质因数。
这两个值的比率限制了共振的抑制,以便降低频率并扩大算法响应。例如,Zero Q 的默认值为 8,Pole Q 的默认值为 4,比率为 2,共振抑制系数则限制为 2 (6 dB)。Android 框架会将这两个值都链接到振动器 HAL 方法
IVibrator.getQFactor
的输出中。如果默认值不考虑设备电机强度的阻尼,建议您同时修改这两个值,同时增加或减少这两个值。Zero Q 与 Pole Q 的比率应大于 1。这可以通过此处的代码进行修改。
失真的转角频率
转角频率通过低通滤波器应用,该滤波器可抑制低级别振动,并使用立方失真增强更高级别的振动。其默认值为 300Hz。这可以通过此处的代码进行修改。
失真的输入增益和立方体阈值
这些参数由应用于输入波形的非线性失真滤波器使用,用于阻挡低频信号的振幅并增加高频信号的振幅。
- 输入增益系数的默认值为 0.3。
- 立方体阈值的默认值为 0.1。
建议您同时修改这两个值。您可以在此处的代码中找到这两个值。
如需详细了解此滤波器所应用的函数,请参阅此处介绍的实现。 如需详细了解这两个参数如何影响输出,建议您绘制滤波器的频率响应,并观察频率响应如何随不同的参数值发生变化。
失真的输出增益
此参数控制最终的振动幅度。它是在软限制器之后应用的最终增益,软限制器将振动振幅限制为小于 1。此参数的默认值为 1.5,可通过此处的代码进行修改。如果振幅太小,请提高该值。如果您听见致动器硬件有杂音,请降低该值。